Skip to content

feat: 新增对第三方日历的支持 - #32

Merged
zhxycn merged 4 commits into
mainfrom
lichx/calender-support
Jul 28, 2026
Merged

feat: 新增对第三方日历的支持#32
zhxycn merged 4 commits into
mainfrom
lichx/calender-support

Conversation

@li-chx

@li-chx li-chx commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

fix #23

@zhxycn zhxycn changed the title ✨ feat: 新增对第三方日历的支持 feat: 新增对第三方日历的支持 Jul 28, 2026
@zhxycn
zhxycn marked this pull request as ready for review July 28, 2026 12:57
@zhxycn
zhxycn self-requested a review as a code owner July 28, 2026 12:57
Copilot AI review requested due to automatic review settings July 28, 2026 12:57
@zhxycn
zhxycn enabled auto-merge July 28, 2026 12:59

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

该 PR 为“课程同步到系统日历”功能新增了对第三方/云日历的写入支持,并通过新增日历选择器与更稳健的同步/清理逻辑来解决 Issue #23(Google Calendar 等第三方日历导入/同步体验问题)。

Changes:

  • 新增可写日历列表获取与“选择同步日历”的 UI(支持本地日历 + 第三方日历多选)。
  • 重构日历同步流程:支持指定目标日历 ID、外部事件 ID 持久化与删除、按周重复事件以减少写入量。
  • 新增设置项持久化 syncedCalendarIds,并在自动同步与删除流程中使用/维护该配置。

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
store/settings.ts 新增并持久化 syncedCalendarIds 及其 setter,用于记录用户选择的同步目标日历。
services/calendar-sync.ts 核心同步逻辑重构:支持目标日历选择、外部事件 ID 清理、重复规则写入,并新增可写日历查询与清理 API。
lib/i18n/locales/zh.json 新增日历选择器与移除确认相关文案,并调整“系统日历”措辞为更通用的“日历”。
lib/i18n/locales/en.json 同步补充英文文案,匹配新选择器与移除确认流程。
app/onboarding.tsx 关闭日历同步时增加失败提示(并改为基于返回结果决定是否关同步开关)。
app/(pages)/settings/calendar.tsx 新增“选择同步日历”的 BottomSheet、移除确认 ConfirmSheet,以及同步/移除流程与状态管理。
app/_layout.tsx 自动同步时带上已选择的目标日历 IDs;无课程数据时清理已同步数据。

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread services/calendar-sync.ts
Comment on lines +171 to +181
export async function getWritableCalendars(): Promise<CalendarInfo[]> {
const calendars = await getCalendars(EntityTypes.EVENT);
return calendars
.filter(
(calendar) =>
!isAppCalendar(calendar) &&
calendar.allowsModifications &&
(Platform.OS !== "android" || calendar.isPrimary),
)
.map(toCalendarInfo);
}
Comment thread app/onboarding.tsx

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6d4ba1bfb1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread services/calendar-sync.ts Outdated
Comment on lines +358 to +359
const failedOldEventIds = await deleteEventIds(oldExternalEventIds);
setStoredEventIds([...failedOldEventIds, ...createdExternalIds]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve old events when replacement writes fail

When a resync writes at least one event but other writes fail, this unconditionally deletes every previously tracked external event. For example, if the user targets both the local and a cloud calendar and only the local writes succeed, count is nonzero, so all existing cloud events are removed even though none of their replacements were created; the operation then reports only partial success while the cloud schedule disappears. Preserve old events per target until that target's complete replacement has succeeded.

Useful? React with 👍 / 👎.

Comment thread services/calendar-sync.ts
Comment on lines +425 to +429
try {
event = await ExpoCalendarEvent.get(id);
} catch {
continue;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Retain IDs when event lookup fails

If ExpoCalendarEvent.get(id) rejects for a transient provider or cloud-calendar error, this path treats the event as already absent and drops its ID from persistent tracking. A subsequent remove can therefore report success and disable sync while the course event remains in the user's external calendar with no way for the app to find it again. Only discard an ID for a confirmed not-found result; retain it for other lookup failures.

Useful? React with 👍 / 👎.

Comment thread services/calendar-sync.ts Outdated
Comment on lines +353 to +356
for (const calendar of staleAppCalendars) {
await deleteCalendarSafe(calendar);
}
setStoredCalendarId(newAppCalendar?.id ?? null);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Abort replacement when an iOS calendar cannot be removed

On iOS, if deleting a stale app calendar fails, the return value is ignored and the stored ID is immediately replaced with the new calendar's ID. Because isAppCalendar now recognizes iOS calendars only by that single stored ID, the undeleted old calendar becomes permanently untracked, leaving duplicate course entries that later sync or removal operations cannot clean up. Handle a failed deletion before overwriting the stored ID.

Useful? React with 👍 / 👎.

@zhxycn
zhxycn force-pushed the lichx/calender-support branch from 6d4ba1b to c84260c Compare July 28, 2026 13:10
@zhxycn
zhxycn disabled auto-merge July 28, 2026 13:15
@zhxycn
zhxycn enabled auto-merge (squash) July 28, 2026 13:15
@zhxycn
zhxycn merged commit a52ebef into main Jul 28, 2026
8 checks passed
@zhxycn
zhxycn deleted the lichx/calender-support branch July 28, 2026 13:23
zhxycn added a commit that referenced this pull request Jul 28, 2026
Co-authored-by: zhxycn <admin@owo.cab>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

com.google.android.calendar导入课程失败

3 participants