@agent-native/core 0.180.0-nightly-20260915184036 → 0.180.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/CHANGELOG.md +10 -0
  3. package/corpus/templates/calendar/CHANGELOG.md +39 -0
  4. package/corpus/templates/calendar/INTERACTION-MATRIX.md +19 -17
  5. package/corpus/templates/calendar/actions/update-calendar-visual-preferences.ts +21 -0
  6. package/corpus/templates/calendar/actions/view-screen.ts +10 -2
  7. package/corpus/templates/calendar/app/components/calendar/CreateEventDialog.tsx +11 -0
  8. package/corpus/templates/calendar/app/components/calendar/MonthView.tsx +174 -145
  9. package/corpus/templates/calendar/app/components/calendar/WeekView.tsx +20 -16
  10. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +1 -0
  11. package/corpus/templates/calendar/app/hooks/use-events.ts +16 -0
  12. package/corpus/templates/calendar/app/hooks/use-view-preferences.ts +126 -14
  13. package/corpus/templates/calendar/app/i18n-data.ts +90 -0
  14. package/corpus/templates/calendar/app/lib/calendar-navigation.ts +29 -9
  15. package/corpus/templates/calendar/app/lib/calendar-timezone.ts +2 -0
  16. package/corpus/templates/calendar/app/lib/event-time-range.ts +34 -0
  17. package/corpus/templates/calendar/app/pages/CalendarView.tsx +245 -35
  18. package/corpus/templates/calendar/changelog/2026-09-13-calendar-sidebar-overflow-is-easier-to-discover.md +6 -0
  19. package/corpus/templates/calendar/changelog/2026-09-15-calendar-mirrors-notion-calendar-s-customizable-day-ranges-a.md +6 -0
  20. package/corpus/templates/calendar/shared/calendar-view-preferences.ts +36 -0
  21. package/corpus/templates/calendar/shared/timezone.ts +9 -2
  22. package/corpus/templates/clips/.agents/skills/video-sharing/SKILL.md +2 -0
  23. package/corpus/templates/clips/CHANGELOG.md +19 -0
  24. package/corpus/templates/clips/actions/save-browser-diagnostics.ts +43 -4
  25. package/corpus/templates/clips/app/components/player/browser-diagnostics-panel.tsx +114 -1
  26. package/corpus/templates/clips/app/i18n/en-US.ts +7 -0
  27. package/corpus/templates/clips/app/lib/browser-diagnostics-capture.ts +108 -0
  28. package/corpus/templates/clips/app/routes/record.tsx +1 -0
  29. package/corpus/templates/clips/changelog/2026-09-15-recordings-include-a-structured-timeline-of-browser-interact.md +6 -0
  30. package/corpus/templates/clips/chrome-extension/public/manifest.json +7 -0
  31. package/corpus/templates/clips/chrome-extension/src/background.ts +235 -9
  32. package/corpus/templates/clips/chrome-extension/src/content-history-bridge.ts +80 -0
  33. package/corpus/templates/clips/chrome-extension/src/content-script.ts +166 -5
  34. package/corpus/templates/clips/chrome-extension/vite.config.ts +4 -0
  35. package/corpus/templates/clips/server/db/schema.ts +3 -0
  36. package/corpus/templates/clips/server/lib/public-agent-context.ts +40 -2
  37. package/corpus/templates/clips/server/plugins/db.ts +5 -0
  38. package/corpus/templates/clips/shared/browser-diagnostics.ts +171 -0
  39. package/corpus/templates/content/.agents/skills/content/SKILL.md +4 -2
  40. package/corpus/templates/content/.agents/skills/document-editing/SKILL.md +8 -1
  41. package/corpus/templates/content/AGENTS.md +5 -6
  42. package/corpus/templates/content/CHANGELOG.md +24 -0
  43. package/corpus/templates/content/actions/_content-database-row-migration.ts +67 -36
  44. package/corpus/templates/content/actions/_document-edit-mutation.ts +74 -23
  45. package/corpus/templates/content/actions/edit-document.ts +48 -8
  46. package/corpus/templates/content/actions/migrate-content-database-rows.ts +69 -28
  47. package/corpus/templates/content/server/plugins/agent-chat.ts +1 -1
  48. package/corpus/templates/design/CHANGELOG.md +22 -0
  49. package/corpus/templates/factory/CHANGELOG.md +11 -0
  50. package/corpus/templates/forms/CHANGELOG.md +6 -0
  51. package/corpus/templates/mail/.agents/skills/mail-interaction-parity/references/interaction-matrix.md +24 -4
  52. package/corpus/templates/mail/CHANGELOG.md +68 -0
  53. package/corpus/templates/mail/app/components/email/ComposeBubbleToolbar.tsx +8 -0
  54. package/corpus/templates/mail/app/components/email/ComposeModal.tsx +33 -13
  55. package/corpus/templates/mail/app/components/email/EmailListItem.tsx +23 -4
  56. package/corpus/templates/mail/app/components/email/EmailThread.tsx +56 -13
  57. package/corpus/templates/mail/app/components/email/InlineReplyComposer.tsx +23 -4
  58. package/corpus/templates/mail/app/components/email/RecipientInput.tsx +9 -0
  59. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +8 -1
  60. package/corpus/templates/mail/app/i18n/en-US.ts +31 -0
  61. package/corpus/templates/mail/changelog/2026-09-15-mail-labels-recipient-and-account-controls-for-keyboard-and-.md +6 -0
  62. package/corpus/templates/slides/CHANGELOG.md +32 -0
  63. package/dist/client/CommandMenu.js +14 -2
  64. package/dist/client/settings/AccountSettingsCard.js +3 -2
  65. package/dist/client/settings/SettingsTabsPage.js +9 -1
  66. package/dist/client/settings/agent-settings-search.js +5 -1
  67. package/dist/client/sign-out.d.ts +1 -0
  68. package/dist/client/sign-out.js +8 -0
  69. package/dist/collab/routes.d.ts +1 -1
  70. package/dist/file-upload/actions/upload-image.d.ts +2 -2
  71. package/dist/observability/routes.d.ts +3 -3
  72. package/dist/org/handlers.d.ts +1 -1
  73. package/dist/resources/handlers.d.ts +1 -1
  74. package/dist/secrets/routes.d.ts +3 -3
  75. package/dist/server/agent-engine-api-key-route.d.ts +2 -2
  76. package/dist/server/transcribe-voice.d.ts +1 -1
  77. package/package.json +4 -4
@@ -150,6 +150,28 @@ export function shouldApplyPreferencePoll(
150
150
  return requestedAtRevision === confirmedRevision;
151
151
  }
152
152
 
153
+ export function mergePendingVisualPreferences(
154
+ remote: CalendarViewPreferences,
155
+ pending: Partial<CalendarViewPreferences>,
156
+ ): CalendarViewPreferences {
157
+ return normalizeCalendarViewPreferences({ ...remote, ...pending });
158
+ }
159
+
160
+ export function rollbackVisualPreferencePatch(
161
+ current: CalendarViewPreferences,
162
+ optimistic: Partial<CalendarViewPreferences>,
163
+ rollback: Partial<CalendarViewPreferences>,
164
+ activeKeys: readonly (keyof CalendarViewPreferences)[],
165
+ ): CalendarViewPreferences {
166
+ const rollbackEntries = activeKeys.flatMap((key) =>
167
+ Object.is(current[key], optimistic[key]) ? [[key, rollback[key]]] : [],
168
+ );
169
+ return normalizeCalendarViewPreferences({
170
+ ...current,
171
+ ...Object.fromEntries(rollbackEntries),
172
+ });
173
+ }
174
+
153
175
  export function enqueueSourcePreferenceMutation<T>(
154
176
  chains: Record<string, Promise<unknown>>,
155
177
  preferenceKey: string,
@@ -160,6 +182,17 @@ export function enqueueSourcePreferenceMutation<T>(
160
182
  return request;
161
183
  }
162
184
 
185
+ export function enqueueVisualPreferenceMutation<T>(
186
+ chains: Record<string, Promise<unknown>>,
187
+ run: () => Promise<T>,
188
+ ): Promise<T> {
189
+ return enqueueSourcePreferenceMutation(
190
+ chains,
191
+ CALENDAR_VIEW_PREFERENCES_KEY,
192
+ run,
193
+ );
194
+ }
195
+
163
196
  async function readAppStatePreferences(): Promise<CalendarViewPreferences | null> {
164
197
  const controller = new AbortController();
165
198
  const abortTimer = setTimeout(() => controller.abort(), REFRESH_ABORT_MS);
@@ -192,6 +225,13 @@ function useViewPreferencesState(): ViewPreferencesContextValue {
192
225
  const visibilityMutationChains = useRef<Record<string, Promise<unknown>>>({});
193
226
  const colorMutationChains = useRef<Record<string, Promise<unknown>>>({});
194
227
  const accountMutationChains = useRef<Record<string, Promise<unknown>>>({});
228
+ const visualPreferenceRequestIds = useRef<
229
+ Partial<Record<keyof CalendarViewPreferences, number>>
230
+ >({});
231
+ const visualPreferenceMutationChains = useRef<
232
+ Record<string, Promise<unknown>>
233
+ >({});
234
+ const pendingVisualPreferences = useRef<Partial<CalendarViewPreferences>>({});
195
235
  const confirmedServerRevision = useRef(0);
196
236
 
197
237
  useEffect(() => {
@@ -237,14 +277,19 @@ function useViewPreferencesState(): ViewPreferencesContextValue {
237
277
  ...(pendingPreferences?.colors ?? {}),
238
278
  ...pendingAccountColors.current,
239
279
  };
280
+ const remoteWithPendingVisualPreferences =
281
+ mergePendingVisualPreferences(
282
+ remote,
283
+ pendingVisualPreferences.current,
284
+ );
240
285
  const next = normalizeCalendarViewPreferences({
241
- ...remote,
286
+ ...remoteWithPendingVisualPreferences,
242
287
  googleCalendarVisibility: {
243
- ...remote.googleCalendarVisibility,
288
+ ...remoteWithPendingVisualPreferences.googleCalendarVisibility,
244
289
  ...pendingVisibility.current,
245
290
  },
246
291
  googleCalendarColors: {
247
- ...remote.googleCalendarColors,
292
+ ...remoteWithPendingVisualPreferences.googleCalendarColors,
248
293
  ...Object.fromEntries(
249
294
  Object.entries(pendingGoogleColors.current).filter(
250
295
  (entry): entry is [string, string] => entry[1] !== null,
@@ -254,7 +299,7 @@ function useViewPreferencesState(): ViewPreferencesContextValue {
254
299
  ...(Object.keys(pendingColors).length > 0
255
300
  ? {
256
301
  accountColorModes: {
257
- ...remote.accountColorModes,
302
+ ...remoteWithPendingVisualPreferences.accountColorModes,
258
303
  ...Object.fromEntries(
259
304
  Object.keys(pendingColors).map((accountEmail) => [
260
305
  accountEmail,
@@ -263,7 +308,7 @@ function useViewPreferencesState(): ViewPreferencesContextValue {
263
308
  ),
264
309
  },
265
310
  accountColors: {
266
- ...remote.accountColors,
311
+ ...remoteWithPendingVisualPreferences.accountColors,
267
312
  ...pendingColors,
268
313
  },
269
314
  }
@@ -310,15 +355,82 @@ function useViewPreferencesState(): ViewPreferencesContextValue {
310
355
  };
311
356
  }, [demo]);
312
357
 
313
- const update = useCallback((patch: Partial<ViewPreferences>) => {
314
- setPrefs((prev) => {
315
- const next = normalizeCalendarViewPreferences({ ...prev, ...patch });
316
- save(next);
317
- window.dispatchEvent(new Event(CALENDAR_VIEW_PREFERENCES_CHANGE_EVENT));
318
- return next;
319
- });
320
- callAction("update-calendar-visual-preferences", patch).catch(() => {});
321
- }, []);
358
+ const update = useCallback(
359
+ (patch: Partial<ViewPreferences>) => {
360
+ const preferenceKeys = Object.keys(
361
+ patch,
362
+ ) as (keyof CalendarViewPreferences)[];
363
+ if (preferenceKeys.length === 0) return;
364
+ const requestIds = new Map<keyof CalendarViewPreferences, number>();
365
+ for (const key of preferenceKeys) {
366
+ const requestId = (visualPreferenceRequestIds.current[key] ?? 0) + 1;
367
+ visualPreferenceRequestIds.current[key] = requestId;
368
+ requestIds.set(key, requestId);
369
+ }
370
+ let rollbackValues: Partial<CalendarViewPreferences> = {};
371
+ let optimisticValues: Partial<CalendarViewPreferences> = {};
372
+ setPrefs((prev) => {
373
+ const next = normalizeCalendarViewPreferences({ ...prev, ...patch });
374
+ rollbackValues = Object.fromEntries(
375
+ preferenceKeys.map((key) => [key, prev[key]]),
376
+ ) as Partial<CalendarViewPreferences>;
377
+ optimisticValues = Object.fromEntries(
378
+ preferenceKeys.map((key) => [key, next[key]]),
379
+ ) as Partial<CalendarViewPreferences>;
380
+ for (const key of preferenceKeys) {
381
+ pendingVisualPreferences.current[key] = next[key] as never;
382
+ }
383
+ save(next);
384
+ window.dispatchEvent(new Event(CALENDAR_VIEW_PREFERENCES_CHANGE_EVENT));
385
+ return next;
386
+ });
387
+
388
+ enqueueVisualPreferenceMutation(
389
+ visualPreferenceMutationChains.current,
390
+ () => callAction("update-calendar-visual-preferences", patch),
391
+ )
392
+ .then(() => {
393
+ let confirmed = false;
394
+ for (const key of preferenceKeys) {
395
+ if (
396
+ visualPreferenceRequestIds.current[key] === requestIds.get(key)
397
+ ) {
398
+ delete pendingVisualPreferences.current[key];
399
+ confirmed = true;
400
+ }
401
+ }
402
+ if (confirmed) confirmedServerRevision.current += 1;
403
+ })
404
+ .catch(() => {
405
+ const activeKeys = preferenceKeys.filter(
406
+ (key) =>
407
+ visualPreferenceRequestIds.current[key] === requestIds.get(key),
408
+ );
409
+ if (activeKeys.length === 0) return;
410
+ for (const key of activeKeys) {
411
+ delete pendingVisualPreferences.current[key];
412
+ }
413
+ setPrefs((current) => {
414
+ const next = rollbackVisualPreferencePatch(
415
+ current,
416
+ optimisticValues,
417
+ rollbackValues,
418
+ activeKeys,
419
+ );
420
+ if (calendarViewPreferencesEqual(current, next)) return current;
421
+ save(next);
422
+ window.dispatchEvent(
423
+ new Event(CALENDAR_VIEW_PREFERENCES_CHANGE_EVENT),
424
+ );
425
+ return next;
426
+ });
427
+ toast.error(
428
+ `${t("settings.saveFailed")}. ${t("common.tryAgain")}`, // i18n-key-ignore generated calendar catalog
429
+ );
430
+ });
431
+ },
432
+ [t],
433
+ );
322
434
 
323
435
  const updateAccountColor = useCallback(
324
436
  (accountEmail: string, accountColor: string) => {
@@ -665,6 +665,8 @@ const enUS = {
665
665
  calendarSettingsLoading:
666
666
  "Calendar settings are still loading. Try again in a moment.",
667
667
  day: "Day",
668
+ daysCount: "{{count}} days",
669
+ declinedEvents: "Declined events",
668
670
  display: "Display",
669
671
  endTimeAfterStart: "End time must be after start time",
670
672
  eventDeleted: "Event deleted",
@@ -675,6 +677,7 @@ const enUS = {
675
677
  failedRestoreAttendance: "Failed to restore attendance",
676
678
  failedMoveEvent: "Failed to move event",
677
679
  failedUpdateEvent: "Failed to update event",
680
+ generalSettings: "General settings",
678
681
  googleCalendarLinkUnavailable: "Google Calendar link unavailable",
679
682
  hideWeekends: "Hide weekends",
680
683
  loadingCalendars: "Loading calendars",
@@ -684,11 +687,17 @@ const enUS = {
684
687
  notificationEmptyDescription:
685
688
  "Calendar can pop browser alerts while this app is open. Clips desktop handles fuller meeting prompts with one-click notes.",
686
689
  openNavigation: "Open navigation",
690
+ numberOfDays: "Number of days",
691
+ other: "Other…",
687
692
  today: "Today",
688
693
  undo: "Undo",
689
694
  updatingEvent: "Updating event...",
690
695
  updatingRecurringEvent: "Updating recurring event...",
691
696
  week: "Week",
697
+ weekNumber: "Week {{number}}",
698
+ weekNumbers: "Week numbers",
699
+ weekends: "Weekends",
700
+ viewSettings: "View settings",
692
701
  timezoneSwitchTitle: "Use your browser timezone?",
693
702
  timezoneSwitchDescription:
694
703
  "Calendar is pinned to {{savedTimezone}}, but your browser is in {{browserTimezone}}. Switch the calendar timezone?",
@@ -7894,6 +7903,8 @@ const translatedCalendarRawBurnDown = {
7894
7903
  addTitleBeforeCreate: "创建事件前请添加标题",
7895
7904
  calendarSettingsLoading: "日历设置仍在加载。请稍后再试。",
7896
7905
  day: "日",
7906
+ daysCount: "{{count}} 天",
7907
+ declinedEvents: "已拒绝的事件",
7897
7908
  display: "显示",
7898
7909
  endTimeAfterStart: "结束时间必须晚于开始时间",
7899
7910
  eventDeleted: "事件已删除",
@@ -7904,6 +7915,7 @@ const translatedCalendarRawBurnDown = {
7904
7915
  failedRestoreAttendance: "恢复出席状态失败",
7905
7916
  failedMoveEvent: "移动事件失败",
7906
7917
  failedUpdateEvent: "更新事件失败",
7918
+ generalSettings: "常规设置",
7907
7919
  googleCalendarLinkUnavailable: "Google Calendar 链接不可用",
7908
7920
  hideWeekends: "隐藏周末",
7909
7921
  loadingCalendars: "正在加载日历",
@@ -7913,11 +7925,17 @@ const translatedCalendarRawBurnDown = {
7913
7925
  notificationEmptyDescription:
7914
7926
  "此应用打开时,Calendar 可以显示浏览器提醒。Clips 桌面版会处理更完整的会议提示,并支持一键备注。",
7915
7927
  openNavigation: "打开导航",
7928
+ numberOfDays: "天数",
7929
+ other: "其他…",
7916
7930
  today: "今天",
7917
7931
  undo: "撤销",
7918
7932
  updatingEvent: "正在更新事件...",
7919
7933
  updatingRecurringEvent: "正在更新重复事件...",
7920
7934
  week: "周",
7935
+ weekNumber: "第 {{number}} 周",
7936
+ weekNumbers: "周数",
7937
+ weekends: "周末",
7938
+ viewSettings: "视图设置",
7921
7939
  timezoneSwitchTitle: "使用浏览器时区?",
7922
7940
  timezoneSwitchDescription:
7923
7941
  "日历固定为 {{savedTimezone}},但浏览器使用 {{browserTimezone}}。要切换日历时区吗?",
@@ -8070,6 +8088,8 @@ const translatedCalendarRawBurnDown = {
8070
8088
  calendarSettingsLoading:
8071
8089
  "La configuración del calendario aún se está cargando. Inténtalo de nuevo en un momento.",
8072
8090
  day: "Día",
8091
+ daysCount: "{{count}} días",
8092
+ declinedEvents: "Eventos rechazados",
8073
8093
  display: "Mostrar",
8074
8094
  endTimeAfterStart:
8075
8095
  "La hora de finalización debe ser posterior a la de inicio",
@@ -8081,6 +8101,7 @@ const translatedCalendarRawBurnDown = {
8081
8101
  failedRestoreAttendance: "No se pudo restaurar la asistencia",
8082
8102
  failedMoveEvent: "No se pudo mover el evento",
8083
8103
  failedUpdateEvent: "No se pudo actualizar el evento",
8104
+ generalSettings: "Configuración general",
8084
8105
  googleCalendarLinkUnavailable:
8085
8106
  "El enlace de Google Calendar no está disponible",
8086
8107
  hideWeekends: "Ocultar fines de semana",
@@ -8091,11 +8112,17 @@ const translatedCalendarRawBurnDown = {
8091
8112
  notificationEmptyDescription:
8092
8113
  "Calendar puede mostrar alertas del navegador mientras esta app está abierta. Clips de escritorio gestiona avisos de reunión más completos con notas en un clic.",
8093
8114
  openNavigation: "Abrir navegación",
8115
+ numberOfDays: "Número de días",
8116
+ other: "Otro…",
8094
8117
  today: "Hoy",
8095
8118
  undo: "Deshacer",
8096
8119
  updatingEvent: "Actualizando evento...",
8097
8120
  updatingRecurringEvent: "Actualizando evento recurrente...",
8098
8121
  week: "Semana",
8122
+ weekNumber: "Semana {{number}}",
8123
+ weekNumbers: "Números de semana",
8124
+ weekends: "Fines de semana",
8125
+ viewSettings: "Configuración de vista",
8099
8126
  timezoneSwitchTitle: "¿Usar la zona horaria del navegador?",
8100
8127
  timezoneSwitchDescription:
8101
8128
  "El calendario está fijado en {{savedTimezone}}, pero tu navegador usa {{browserTimezone}}. ¿Cambiar la zona horaria del calendario?",
@@ -8254,6 +8281,8 @@ const translatedCalendarRawBurnDown = {
8254
8281
  calendarSettingsLoading:
8255
8282
  "Les paramètres du calendrier sont encore en cours de chargement. Réessayez dans un instant.",
8256
8283
  day: "Jour",
8284
+ daysCount: "{{count}} jours",
8285
+ declinedEvents: "Événements refusés",
8257
8286
  display: "Affichage",
8258
8287
  endTimeAfterStart: "L'heure de fin doit être après l'heure de début",
8259
8288
  eventDeleted: "Événement supprimé",
@@ -8264,6 +8293,7 @@ const translatedCalendarRawBurnDown = {
8264
8293
  failedRestoreAttendance: "Échec de la restauration de la participation",
8265
8294
  failedMoveEvent: "Échec du déplacement de l'événement",
8266
8295
  failedUpdateEvent: "Échec de la mise à jour de l'événement",
8296
+ generalSettings: "Paramètres généraux",
8267
8297
  googleCalendarLinkUnavailable: "Lien Google Calendar indisponible",
8268
8298
  hideWeekends: "Masquer les week-ends",
8269
8299
  loadingCalendars: "Chargement des calendriers",
@@ -8273,11 +8303,17 @@ const translatedCalendarRawBurnDown = {
8273
8303
  notificationEmptyDescription:
8274
8304
  "Calendar peut afficher des alertes du navigateur tant que cette app est ouverte. Clips desktop gère des rappels de réunion plus complets avec des notes en un clic.",
8275
8305
  openNavigation: "Ouvrir la navigation",
8306
+ numberOfDays: "Nombre de jours",
8307
+ other: "Autre…",
8276
8308
  today: "Aujourd'hui",
8277
8309
  undo: "Annuler",
8278
8310
  updatingEvent: "Mise à jour de l'événement...",
8279
8311
  updatingRecurringEvent: "Mise à jour de l'événement récurrent...",
8280
8312
  week: "Semaine",
8313
+ weekNumber: "Semaine {{number}}",
8314
+ weekNumbers: "Numéros de semaine",
8315
+ weekends: "Week-ends",
8316
+ viewSettings: "Paramètres d'affichage",
8281
8317
  timezoneSwitchTitle: "Utiliser le fuseau horaire du navigateur ?",
8282
8318
  timezoneSwitchDescription:
8283
8319
  "Le calendrier est fixé sur {{savedTimezone}}, mais votre navigateur utilise {{browserTimezone}}. Changer le fuseau horaire du calendrier ?",
@@ -8439,6 +8475,8 @@ const translatedCalendarRawBurnDown = {
8439
8475
  calendarSettingsLoading:
8440
8476
  "Die Kalendereinstellungen werden noch geladen. Versuchen Sie es gleich erneut.",
8441
8477
  day: "Tag",
8478
+ daysCount: "{{count}} Tage",
8479
+ declinedEvents: "Abgelehnte Ereignisse",
8442
8480
  display: "Anzeige",
8443
8481
  endTimeAfterStart: "Die Endzeit muss nach der Startzeit liegen",
8444
8482
  eventDeleted: "Ereignis gelöscht",
@@ -8450,6 +8488,7 @@ const translatedCalendarRawBurnDown = {
8450
8488
  "Teilnahme konnte nicht wiederhergestellt werden",
8451
8489
  failedMoveEvent: "Ereignis konnte nicht verschoben werden",
8452
8490
  failedUpdateEvent: "Ereignis konnte nicht aktualisiert werden",
8491
+ generalSettings: "Allgemeine Einstellungen",
8453
8492
  googleCalendarLinkUnavailable: "Google Calendar-Link nicht verfügbar",
8454
8493
  hideWeekends: "Wochenenden ausblenden",
8455
8494
  loadingCalendars: "Kalender werden geladen",
@@ -8459,11 +8498,17 @@ const translatedCalendarRawBurnDown = {
8459
8498
  notificationEmptyDescription:
8460
8499
  "Calendar kann Browserbenachrichtigungen anzeigen, während diese App geöffnet ist. Clips Desktop übernimmt umfassendere Meeting-Hinweise mit Notizen per Klick.",
8461
8500
  openNavigation: "Navigation öffnen",
8501
+ numberOfDays: "Anzahl der Tage",
8502
+ other: "Andere…",
8462
8503
  today: "Heute",
8463
8504
  undo: "Rückgängig",
8464
8505
  updatingEvent: "Ereignis wird aktualisiert...",
8465
8506
  updatingRecurringEvent: "Wiederkehrendes Ereignis wird aktualisiert...",
8466
8507
  week: "Woche",
8508
+ weekNumber: "Woche {{number}}",
8509
+ weekNumbers: "Kalenderwochen",
8510
+ weekends: "Wochenenden",
8511
+ viewSettings: "Ansichtseinstellungen",
8467
8512
  timezoneSwitchTitle: "Browser-Zeitzone verwenden?",
8468
8513
  timezoneSwitchDescription:
8469
8514
  "Der Kalender ist auf {{savedTimezone}} festgelegt, aber Ihr Browser verwendet {{browserTimezone}}. Kalenderzeitzone wechseln?",
@@ -8623,6 +8668,8 @@ const translatedCalendarRawBurnDown = {
8623
8668
  calendarSettingsLoading:
8624
8669
  "カレンダー設定を読み込み中です。少し待ってからもう一度お試しください。",
8625
8670
  day: "日",
8671
+ daysCount: "{{count}}日",
8672
+ declinedEvents: "辞退した予定",
8626
8673
  display: "表示",
8627
8674
  endTimeAfterStart: "終了時刻は開始時刻より後にしてください",
8628
8675
  eventDeleted: "イベントを削除しました",
@@ -8633,6 +8680,7 @@ const translatedCalendarRawBurnDown = {
8633
8680
  failedRestoreAttendance: "出席の復元に失敗しました",
8634
8681
  failedMoveEvent: "イベントを移動できませんでした",
8635
8682
  failedUpdateEvent: "イベントを更新できませんでした",
8683
+ generalSettings: "一般設定",
8636
8684
  googleCalendarLinkUnavailable: "Google Calendar リンクを利用できません",
8637
8685
  hideWeekends: "週末を非表示",
8638
8686
  loadingCalendars: "カレンダーを読み込み中",
@@ -8642,11 +8690,17 @@ const translatedCalendarRawBurnDown = {
8642
8690
  notificationEmptyDescription:
8643
8691
  "このアプリを開いている間、Calendar はブラウザー通知を表示できます。Clips デスクトップでは、ワンクリックのメモ付きでより詳しい会議通知を扱えます。",
8644
8692
  openNavigation: "ナビゲーションを開く",
8693
+ numberOfDays: "表示日数",
8694
+ other: "その他…",
8645
8695
  today: "今日",
8646
8696
  undo: "元に戻す",
8647
8697
  updatingEvent: "イベントを更新中...",
8648
8698
  updatingRecurringEvent: "繰り返しイベントを更新中...",
8649
8699
  week: "週",
8700
+ weekNumber: "第{{number}}週",
8701
+ weekNumbers: "週番号",
8702
+ weekends: "週末",
8703
+ viewSettings: "表示設定",
8650
8704
  timezoneSwitchTitle: "ブラウザのタイムゾーンを使用しますか?",
8651
8705
  timezoneSwitchDescription:
8652
8706
  "カレンダーは {{savedTimezone}} に固定されていますが、ブラウザは {{browserTimezone}} を使用しています。カレンダーのタイムゾーンを切り替えますか?",
@@ -8801,6 +8855,8 @@ const translatedCalendarRawBurnDown = {
8801
8855
  calendarSettingsLoading:
8802
8856
  "캘린더 설정을 아직 불러오는 중입니다. 잠시 후 다시 시도하세요.",
8803
8857
  day: "일",
8858
+ daysCount: "{{count}}일",
8859
+ declinedEvents: "거절된 일정",
8804
8860
  display: "표시",
8805
8861
  endTimeAfterStart: "종료 시간은 시작 시간보다 늦어야 합니다",
8806
8862
  eventDeleted: "이벤트가 삭제되었습니다",
@@ -8811,6 +8867,7 @@ const translatedCalendarRawBurnDown = {
8811
8867
  failedRestoreAttendance: "참석 상태를 복원하지 못했습니다",
8812
8868
  failedMoveEvent: "이벤트를 이동하지 못했습니다",
8813
8869
  failedUpdateEvent: "이벤트를 업데이트하지 못했습니다",
8870
+ generalSettings: "일반 설정",
8814
8871
  googleCalendarLinkUnavailable:
8815
8872
  "Google Calendar 링크를 사용할 수 없습니다",
8816
8873
  hideWeekends: "주말 숨기기",
@@ -8821,11 +8878,17 @@ const translatedCalendarRawBurnDown = {
8821
8878
  notificationEmptyDescription:
8822
8879
  "이 앱이 열려 있는 동안 Calendar가 브라우저 알림을 표시할 수 있습니다. Clips 데스크톱은 원클릭 메모가 포함된 더 자세한 회의 알림을 처리합니다.",
8823
8880
  openNavigation: "탐색 열기",
8881
+ numberOfDays: "표시할 일수",
8882
+ other: "기타…",
8824
8883
  today: "오늘",
8825
8884
  undo: "실행 취소",
8826
8885
  updatingEvent: "이벤트 업데이트 중...",
8827
8886
  updatingRecurringEvent: "반복 이벤트 업데이트 중...",
8828
8887
  week: "주",
8888
+ weekNumber: "{{number}}주",
8889
+ weekNumbers: "주 번호",
8890
+ weekends: "주말",
8891
+ viewSettings: "보기 설정",
8829
8892
  timezoneSwitchTitle: "브라우저 시간대를 사용할까요?",
8830
8893
  timezoneSwitchDescription:
8831
8894
  "캘린더는 {{savedTimezone}}에 고정되어 있지만 브라우저는 {{browserTimezone}}을(를) 사용합니다. 캘린더 시간대를 전환할까요?",
@@ -8982,6 +9045,8 @@ const translatedCalendarRawBurnDown = {
8982
9045
  calendarSettingsLoading:
8983
9046
  "As configurações do calendário ainda estão carregando. Tente novamente em instantes.",
8984
9047
  day: "Dia",
9048
+ daysCount: "{{count}} dias",
9049
+ declinedEvents: "Eventos recusados",
8985
9050
  display: "Exibição",
8986
9051
  endTimeAfterStart:
8987
9052
  "O horário de término deve ser depois do horário de início",
@@ -8993,6 +9058,7 @@ const translatedCalendarRawBurnDown = {
8993
9058
  failedRestoreAttendance: "Falha ao restaurar a participação",
8994
9059
  failedMoveEvent: "Falha ao mover evento",
8995
9060
  failedUpdateEvent: "Falha ao atualizar evento",
9061
+ generalSettings: "Configurações gerais",
8996
9062
  googleCalendarLinkUnavailable: "Link do Google Calendar indisponível",
8997
9063
  hideWeekends: "Ocultar fins de semana",
8998
9064
  loadingCalendars: "Carregando calendários",
@@ -9002,11 +9068,17 @@ const translatedCalendarRawBurnDown = {
9002
9068
  notificationEmptyDescription:
9003
9069
  "Calendar pode exibir alertas do navegador enquanto este app estiver aberto. O Clips desktop cuida de lembretes de reunião mais completos com notas em um clique.",
9004
9070
  openNavigation: "Abrir navegação",
9071
+ numberOfDays: "Número de dias",
9072
+ other: "Outro…",
9005
9073
  today: "Hoje",
9006
9074
  undo: "Desfazer",
9007
9075
  updatingEvent: "Atualizando evento...",
9008
9076
  updatingRecurringEvent: "Atualizando evento recorrente...",
9009
9077
  week: "Semana",
9078
+ weekNumber: "Semana {{number}}",
9079
+ weekNumbers: "Números da semana",
9080
+ weekends: "Fins de semana",
9081
+ viewSettings: "Configurações de visualização",
9010
9082
  timezoneSwitchTitle: "Usar o fuso horário do navegador?",
9011
9083
  timezoneSwitchDescription:
9012
9084
  "O calendário está fixado em {{savedTimezone}}, mas o navegador usa {{browserTimezone}}. Mudar o fuso horário do calendário?",
@@ -9163,6 +9235,8 @@ const translatedCalendarRawBurnDown = {
9163
9235
  calendarSettingsLoading:
9164
9236
  "कैलेंडर सेटिंग अभी लोड हो रही हैं। कृपया थोड़ी देर में फिर कोशिश करें।",
9165
9237
  day: "दिन",
9238
+ daysCount: "{{count}} दिन",
9239
+ declinedEvents: "अस्वीकृत इवेंट",
9166
9240
  display: "डिस्प्ले",
9167
9241
  endTimeAfterStart: "समाप्ति समय प्रारंभ समय के बाद होना चाहिए",
9168
9242
  eventDeleted: "इवेंट मिटा दिया गया",
@@ -9173,6 +9247,7 @@ const translatedCalendarRawBurnDown = {
9173
9247
  failedRestoreAttendance: "उपस्थिति बहाल करने में विफल",
9174
9248
  failedMoveEvent: "इवेंट स्थानांतरित करने में विफल",
9175
9249
  failedUpdateEvent: "इवेंट अपडेट करने में विफल",
9250
+ generalSettings: "सामान्य सेटिंग",
9176
9251
  googleCalendarLinkUnavailable: "Google Calendar लिंक उपलब्ध नहीं है",
9177
9252
  hideWeekends: "सप्ताहांत छिपाएं",
9178
9253
  loadingCalendars: "कैलेंडर लोड हो रहे हैं",
@@ -9182,11 +9257,17 @@ const translatedCalendarRawBurnDown = {
9182
9257
  notificationEmptyDescription:
9183
9258
  "यह ऐप खुला होने पर Calendar ब्राउज़र अलर्ट दिखा सकता है। Clips डेस्कटॉप एक-क्लिक नोट्स के साथ अधिक पूर्ण मीटिंग संकेत संभालता है।",
9184
9259
  openNavigation: "नेविगेशन खोलें",
9260
+ numberOfDays: "दिनों की संख्या",
9261
+ other: "अन्य…",
9185
9262
  today: "आज",
9186
9263
  undo: "पहले जैसा करें",
9187
9264
  updatingEvent: "इवेंट अपडेट हो रहा है...",
9188
9265
  updatingRecurringEvent: "दोहराया जाने वाला इवेंट अपडेट हो रहा है...",
9189
9266
  week: "सप्ताह",
9267
+ weekNumber: "सप्ताह {{number}}",
9268
+ weekNumbers: "सप्ताह संख्या",
9269
+ weekends: "सप्ताहांत",
9270
+ viewSettings: "दृश्य सेटिंग",
9190
9271
  timezoneSwitchTitle: "ब्राउज़र का टाइमज़ोन इस्तेमाल करें?",
9191
9272
  timezoneSwitchDescription:
9192
9273
  "कैलेंडर {{savedTimezone}} पर पिन है, लेकिन आपका ब्राउज़र {{browserTimezone}} पर है। कैलेंडर टाइमज़ोन बदलें?",
@@ -9342,6 +9423,8 @@ const translatedCalendarRawBurnDown = {
9342
9423
  calendarSettingsLoading:
9343
9424
  "لا تزال إعدادات التقويم قيد التحميل. حاول مرة أخرى بعد قليل.",
9344
9425
  day: "اليوم",
9426
+ daysCount: "{{count}} يوم",
9427
+ declinedEvents: "الأحداث المرفوضة",
9345
9428
  display: "العرض",
9346
9429
  endTimeAfterStart: "يجب أن يكون وقت الانتهاء بعد وقت البدء",
9347
9430
  eventDeleted: "تم حذف الحدث",
@@ -9352,6 +9435,7 @@ const translatedCalendarRawBurnDown = {
9352
9435
  failedRestoreAttendance: "فشل استعادة الحضور",
9353
9436
  failedMoveEvent: "فشل نقل الحدث",
9354
9437
  failedUpdateEvent: "فشل تحديث الحدث",
9438
+ generalSettings: "الإعدادات العامة",
9355
9439
  googleCalendarLinkUnavailable: "رابط Google Calendar غير متاح",
9356
9440
  hideWeekends: "إخفاء عطلات نهاية الأسبوع",
9357
9441
  loadingCalendars: "جارٍ تحميل التقويمات",
@@ -9361,11 +9445,17 @@ const translatedCalendarRawBurnDown = {
9361
9445
  notificationEmptyDescription:
9362
9446
  "يمكن لـ Calendar عرض تنبيهات المتصفح أثناء فتح هذا التطبيق. يتولى Clips لسطح المكتب مطالبات اجتماع أكثر اكتمالًا مع ملاحظات بنقرة واحدة.",
9363
9447
  openNavigation: "فتح التنقل",
9448
+ numberOfDays: "عدد الأيام",
9449
+ other: "أخرى…",
9364
9450
  today: "اليوم",
9365
9451
  undo: "تراجع",
9366
9452
  updatingEvent: "جارٍ تحديث الحدث...",
9367
9453
  updatingRecurringEvent: "جارٍ تحديث الحدث المتكرر...",
9368
9454
  week: "الأسبوع",
9455
+ weekNumber: "الأسبوع {{number}}",
9456
+ weekNumbers: "أرقام الأسابيع",
9457
+ weekends: "عطلات نهاية الأسبوع",
9458
+ viewSettings: "إعدادات العرض",
9369
9459
  timezoneSwitchTitle: "استخدام المنطقة الزمنية للمتصفح؟",
9370
9460
  timezoneSwitchDescription:
9371
9461
  "التقويم مثبت على {{savedTimezone}}، لكن متصفحك يستخدم {{browserTimezone}}. هل تريد تبديل المنطقة الزمنية للتقويم؟",
@@ -1,11 +1,10 @@
1
1
  import {
2
2
  addDays,
3
3
  addMonths,
4
- addWeeks,
4
+ eachDayOfInterval,
5
5
  startOfWeek,
6
6
  subDays,
7
7
  subMonths,
8
- subWeeks,
9
8
  } from "date-fns";
10
9
 
11
10
  import { dateKeyToDate, dateToCalendarDateKey } from "./calendar-timezone";
@@ -18,6 +17,7 @@ export function navigateCalendarDate(
18
17
  selectedDate: Date,
19
18
  direction: CalendarNavigationDirection,
20
19
  weekStartsOn: 0 | 1,
20
+ numberOfDays = 7,
21
21
  ): Date {
22
22
  switch (viewMode) {
23
23
  case "month":
@@ -25,13 +25,20 @@ export function navigateCalendarDate(
25
25
  ? addMonths(selectedDate, 1)
26
26
  : subMonths(selectedDate, 1);
27
27
  case "week": {
28
- const navigatedDate =
29
- direction === "next"
30
- ? addWeeks(selectedDate, 1)
31
- : subWeeks(selectedDate, 1);
32
- return dateKeyToDate(
33
- dateToCalendarDateKey(startOfWeek(navigatedDate, { weekStartsOn })),
34
- );
28
+ const displayedDays = Number.isInteger(numberOfDays)
29
+ ? Math.min(31, Math.max(1, numberOfDays))
30
+ : 7;
31
+ const periodStart =
32
+ displayedDays === 7
33
+ ? dateKeyToDate(
34
+ dateToCalendarDateKey(
35
+ startOfWeek(selectedDate, { weekStartsOn }),
36
+ ),
37
+ )
38
+ : selectedDate;
39
+ return direction === "next"
40
+ ? addDays(periodStart, displayedDays)
41
+ : subDays(periodStart, displayedDays);
35
42
  }
36
43
  case "day":
37
44
  return direction === "next"
@@ -39,3 +46,16 @@ export function navigateCalendarDate(
39
46
  : subDays(selectedDate, 1);
40
47
  }
41
48
  }
49
+
50
+ export function getVisibleCalendarDays(
51
+ start: Date,
52
+ end: Date,
53
+ hideWeekends: boolean,
54
+ ): Date[] {
55
+ const fullRange = eachDayOfInterval({ start, end });
56
+ if (!hideWeekends) return fullRange;
57
+ const weekdays = fullRange.filter(
58
+ (day) => day.getDay() !== 0 && day.getDay() !== 6,
59
+ );
60
+ return weekdays.length > 0 ? weekdays : fullRange;
61
+ }
@@ -167,12 +167,14 @@ export function getViewDateRange(
167
167
  selectedDate: Date,
168
168
  timezone: string,
169
169
  weekStartsOn: 0 | 1 = 0,
170
+ numberOfDays = 7,
170
171
  ): { from: string; to: string } {
171
172
  return getCalendarViewDateRange(
172
173
  viewMode,
173
174
  dateToCalendarDateKey(selectedDate),
174
175
  normalizeTimezone(timezone),
175
176
  weekStartsOn,
177
+ numberOfDays,
176
178
  );
177
179
  }
178
180
 
@@ -165,6 +165,40 @@ export function shiftEndForStartChange(
165
165
  return { ...next, endDate: repaired.date, endTime: repaired.time };
166
166
  }
167
167
 
168
+ /**
169
+ * Move a timed event's start date without changing its visible duration. The
170
+ * end date is shifted by the same number of calendar days; this keeps a
171
+ * multi-day event intact when its start date changes in the composer.
172
+ */
173
+ export function shiftEndForDateChange(
174
+ range: EventTimeRange,
175
+ nextDate: string,
176
+ ): EventTimeRange {
177
+ const next = { ...range, date: nextDate };
178
+ const currentStart = rangeToAbsoluteMinutes(range.date, range.startTime);
179
+ const nextStart = rangeToAbsoluteMinutes(nextDate, range.startTime);
180
+ if (currentStart === null || nextStart === null) return next;
181
+
182
+ const shifted = addMinutesToTimeValue(
183
+ range.endDate,
184
+ range.endTime,
185
+ nextStart - currentStart,
186
+ );
187
+ if (!shifted) return next;
188
+ const shiftedEnd = rangeToAbsoluteMinutes(shifted.date, shifted.time);
189
+ if (shiftedEnd !== null && shiftedEnd > nextStart) {
190
+ return { ...next, endDate: shifted.date, endTime: shifted.time };
191
+ }
192
+
193
+ const repaired = addMinutesToTimeValue(
194
+ nextDate,
195
+ range.startTime,
196
+ TIME_SLOT_MINUTES,
197
+ );
198
+ if (!repaired) return next;
199
+ return { ...next, endDate: repaired.date, endTime: repaired.time };
200
+ }
201
+
168
202
  /**
169
203
  * Resolves an end-time pick against the start. A pick that reads as earlier in
170
204
  * the day is the wrapped option from `buildTimeOptions`, so it belongs to the