@agent-native/core 0.91.0 → 0.91.2
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.
- package/blueprints/action/crud.md +1 -1
- package/blueprints/channel/discord.md +1 -1
- package/blueprints/provider/stripe.md +1 -1
- package/blueprints/sandbox/docker.md +1 -1
- package/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +26 -0
- package/corpus/core/blueprints/action/crud.md +1 -1
- package/corpus/core/blueprints/channel/discord.md +1 -1
- package/corpus/core/blueprints/provider/stripe.md +1 -1
- package/corpus/core/blueprints/sandbox/docker.md +1 -1
- package/corpus/core/package.json +6 -5
- package/corpus/core/src/agent/run-manager.ts +23 -2
- package/corpus/core/src/agent/run-store.ts +2 -2
- package/corpus/core/src/cli/add.ts +1 -1
- package/corpus/core/src/cli/create.ts +8 -3
- package/corpus/core/src/cli/design-connect.ts +53 -9
- package/corpus/core/src/cli/index.ts +5 -4
- package/corpus/core/src/client/extensions/ExtensionSlot.tsx +7 -0
- package/corpus/core/src/client/session-replay.ts +97 -3
- package/corpus/core/src/jobs/scheduler.ts +30 -1
- package/corpus/core/src/localization/default-messages.ts +21 -0
- package/corpus/core/src/templates/default/app/i18n/ar-SA.ts +21 -0
- package/corpus/core/src/templates/default/app/i18n/de-DE.ts +21 -0
- package/corpus/core/src/templates/default/app/i18n/en-US.ts +21 -0
- package/corpus/core/src/templates/default/app/i18n/es-ES.ts +21 -0
- package/corpus/core/src/templates/default/app/i18n/fr-FR.ts +21 -0
- package/corpus/core/src/templates/default/app/i18n/hi-IN.ts +20 -0
- package/corpus/core/src/templates/default/app/i18n/ja-JP.ts +21 -0
- package/corpus/core/src/templates/default/app/i18n/ko-KR.ts +20 -0
- package/corpus/core/src/templates/default/app/i18n/pt-BR.ts +21 -0
- package/corpus/core/src/templates/default/app/i18n/zh-CN.ts +20 -0
- package/corpus/core/src/templates/default/app/i18n/zh-TW.ts +19 -0
- package/corpus/core/src/templates/default/package.json +2 -2
- package/corpus/core/src/templates/headless/package.json +3 -3
- package/corpus/core/src/templates/workspace-core/package.json +6 -6
- package/corpus/core/src/templates/workspace-root/package.json +2 -2
- package/corpus/core/src/triggers/dispatcher.ts +30 -2
- package/corpus/core/src/vite/client.ts +96 -1
- package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +21 -2
- package/corpus/templates/analytics/app/global.css +26 -10
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +2 -0
- package/corpus/templates/analytics/app/i18n-data.ts +25 -0
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +548 -237
- package/corpus/templates/analytics/app/pages/sessions/SessionDevToolsPanel.tsx +285 -294
- package/corpus/templates/analytics/changelog/2026-07-08-console-details-expand-inline-under-each-row-and-the-event-t.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-session-replay-clamps-ultra-wide-viewports-while-keeping-the.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-session-replay-keeps-a-usable-stage-when-dev-tools-is-open-a.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-session-replay-resumes-after-scrubbing-and-expands-console-r.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-session-replays-wait-for-full-load-keep-a-normal-viewport-an.md +6 -0
- package/corpus/templates/analytics/package.json +2 -2
- package/corpus/templates/assets/package.json +2 -2
- package/corpus/templates/brain/package.json +2 -2
- package/corpus/templates/calendar/AGENTS.md +10 -0
- package/corpus/templates/calendar/actions/create-event.ts +5 -1
- package/corpus/templates/calendar/actions/event-action-helpers.ts +41 -0
- package/corpus/templates/calendar/actions/get-attendee-timezones.ts +28 -0
- package/corpus/templates/calendar/actions/set-attendee-timezone.ts +68 -0
- package/corpus/templates/calendar/app/components/calendar/EventAttendeesSection.tsx +150 -11
- package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +36 -1
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +32 -0
- package/corpus/templates/calendar/app/hooks/use-attendee-timezones.ts +24 -0
- package/corpus/templates/calendar/app/i18n/zh-TW.ts +2 -0
- package/corpus/templates/calendar/app/i18n-data.ts +20 -0
- package/corpus/templates/calendar/app/lib/attendee-local-time.ts +122 -0
- package/corpus/templates/calendar/changelog/2026-07-08-event-details-now-support-extension-widgets-and-you-can-see-.md +6 -0
- package/corpus/templates/calendar/changelog/2026-07-08-when-you-invite-guests-to-a-new-event-you-now-appear-in.md +6 -0
- package/corpus/templates/calendar/package.json +2 -2
- package/corpus/templates/calendar/server/handlers/events.ts +5 -1
- package/corpus/templates/calendar/shared/api.ts +6 -0
- package/corpus/templates/chat/package.json +2 -2
- package/corpus/templates/clips/.agents/skills/meetings/SKILL.md +6 -2
- package/corpus/templates/clips/actions/create-meeting.ts +8 -3
- package/corpus/templates/clips/actions/list-meetings.ts +31 -3
- package/corpus/templates/clips/changelog/2026-07-08-after-finishing-a-desktop-recording-reopening-clips-restor.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-clips-now-pops-up-to-take-notes-when-you-join-an-adhoc-zoom-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-desktop-clip-recordings-are-louder-after-capture-mic-only.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-meeting-reminders-now-appear-1-minute-before-start-stay-unti.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-the-desktop-meetings-panel-has-room-for-its-drop-shadow-and-.md +6 -0
- package/corpus/templates/clips/chrome-extension/package.json +2 -2
- package/corpus/templates/clips/desktop/package.json +2 -2
- package/corpus/templates/clips/desktop/src/app.tsx +91 -34
- package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +15 -5
- package/corpus/templates/clips/desktop/src/lib/meeting-notification-timing.ts +83 -0
- package/corpus/templates/clips/desktop/src/lib/native-recording-warm.ts +21 -0
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +98 -20
- package/corpus/templates/clips/desktop/src/overlays/meeting-notification.tsx +174 -50
- package/corpus/templates/clips/desktop/src/styles.css +128 -53
- package/corpus/templates/clips/desktop/src-tauri/src/adhoc_meetings_watcher.rs +364 -0
- package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +1 -1
- package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +5 -0
- package/corpus/templates/clips/desktop/src-tauri/src/meetings_watcher.rs +91 -11
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +69 -19
- package/corpus/templates/clips/desktop/src-tauri/src/native_speech.rs +36 -1
- package/corpus/templates/clips/desktop/src-tauri/src/notifications.rs +62 -10
- package/corpus/templates/clips/desktop/src-tauri/src/silence_detector.rs +1 -24
- package/corpus/templates/clips/desktop/src-tauri/src/util.rs +36 -1
- package/corpus/templates/clips/package.json +2 -2
- package/corpus/templates/content/actions/_content-database-personal-view.ts +80 -0
- package/corpus/templates/content/actions/get-content-database-personal-view.ts +27 -0
- package/corpus/templates/content/actions/update-content-database-personal-view.ts +31 -0
- package/corpus/templates/content/actions/update-content-database-view.ts +3 -0
- package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +1 -1
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +2584 -546
- package/corpus/templates/content/app/components/editor/database/filter-sort.ts +220 -18
- package/corpus/templates/content/app/hooks/use-content-database.ts +32 -0
- package/corpus/templates/content/app/i18n/zh-TW.ts +16 -0
- package/corpus/templates/content/app/i18n-data.ts +154 -0
- package/corpus/templates/content/changelog/2026-07-08-database-filters-now-support-notion-style-reset-save-for-eve.md +6 -0
- package/corpus/templates/content/changelog/2026-07-08-date-filters-can-now-target-a-between-range.md +6 -0
- package/corpus/templates/content/package.json +2 -2
- package/corpus/templates/content/parity/matrix.md +1 -1
- package/corpus/templates/content/parity/matrix.ts +2 -0
- package/corpus/templates/content/shared/api.ts +24 -0
- package/corpus/templates/design/AGENTS.md +9 -0
- package/corpus/templates/design/actions/request-localhost-write-consent.ts +141 -0
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +13 -19
- package/corpus/templates/design/package.json +2 -2
- package/corpus/templates/design/server/lib/verify-write-grant.ts +4 -2
- package/corpus/templates/dispatch/app/i18n/zh-TW.ts +34 -1
- package/corpus/templates/dispatch/app/i18n-data.ts +387 -10
- package/corpus/templates/dispatch/app/routes/automations.tsx +1 -0
- package/corpus/templates/dispatch/changelog/2026-07-08-added-an-automations-page-to-review-pause-and-create.md +6 -0
- package/corpus/templates/dispatch/changelog/2026-07-08-destinations-now-shows-outbound-delivery-queue-health.md +6 -0
- package/corpus/templates/dispatch/package.json +2 -2
- package/corpus/templates/forms/package.json +2 -2
- package/corpus/templates/macros/package.json +2 -2
- package/corpus/templates/mail/app/hooks/use-emails.ts +56 -44
- package/corpus/templates/mail/app/lib/gmail-mutation-queue.ts +325 -0
- package/corpus/templates/mail/changelog/2026-07-08-rapid-archive-and-mark-read-now-batch-gmail-updates-so-the-i.md +6 -0
- package/corpus/templates/mail/package.json +2 -2
- package/corpus/templates/plan/package.json +2 -2
- package/corpus/templates/slides/app/components/editor/ImageDropPromptPopover.tsx +46 -29
- package/corpus/templates/slides/app/context/DeckContext.tsx +45 -18
- package/corpus/templates/slides/app/i18n/ar-SA.ts +4 -0
- package/corpus/templates/slides/app/i18n/de-DE.ts +4 -0
- package/corpus/templates/slides/app/i18n/en-US.ts +4 -0
- package/corpus/templates/slides/app/i18n/es-ES.ts +4 -0
- package/corpus/templates/slides/app/i18n/fr-FR.ts +4 -0
- package/corpus/templates/slides/app/i18n/hi-IN.ts +4 -0
- package/corpus/templates/slides/app/i18n/ja-JP.ts +4 -0
- package/corpus/templates/slides/app/i18n/ko-KR.ts +4 -0
- package/corpus/templates/slides/app/i18n/pt-BR.ts +4 -0
- package/corpus/templates/slides/app/i18n/zh-CN.ts +4 -0
- package/corpus/templates/slides/app/i18n/zh-TW.ts +4 -0
- package/corpus/templates/slides/app/lib/image-drop-to-agent.ts +115 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +22 -13
- package/corpus/templates/slides/changelog/2026-07-08-dropping-an-image-onto-a-slide-and-sending-it-to-the-agent-w.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-08-undo-works-after-the-agent-edits-a-slide-so-you-can-reverse.md +6 -0
- package/corpus/templates/slides/package.json +2 -2
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +23 -2
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/run-store.js +2 -2
- package/dist/agent/run-store.js.map +1 -1
- package/dist/catalog.json +2 -2
- package/dist/cli/add.js +1 -1
- package/dist/cli/add.js.map +1 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +8 -3
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/design-connect.d.ts.map +1 -1
- package/dist/cli/design-connect.js +40 -10
- package/dist/cli/design-connect.js.map +1 -1
- package/dist/cli/index.js +5 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/client/extensions/ExtensionSlot.js +6 -0
- package/dist/client/extensions/ExtensionSlot.js.map +1 -1
- package/dist/client/session-replay.d.ts +8 -0
- package/dist/client/session-replay.d.ts.map +1 -1
- package/dist/client/session-replay.js +80 -3
- package/dist/client/session-replay.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/jobs/scheduler.js +26 -1
- package/dist/jobs/scheduler.js.map +1 -1
- package/dist/localization/default-messages.d.ts +19 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +19 -0
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +1 -1
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/templates/default/app/i18n/ar-SA.ts +21 -0
- package/dist/templates/default/app/i18n/de-DE.ts +21 -0
- package/dist/templates/default/app/i18n/en-US.ts +21 -0
- package/dist/templates/default/app/i18n/es-ES.ts +21 -0
- package/dist/templates/default/app/i18n/fr-FR.ts +21 -0
- package/dist/templates/default/app/i18n/hi-IN.ts +20 -0
- package/dist/templates/default/app/i18n/ja-JP.ts +21 -0
- package/dist/templates/default/app/i18n/ko-KR.ts +20 -0
- package/dist/templates/default/app/i18n/pt-BR.ts +21 -0
- package/dist/templates/default/app/i18n/zh-CN.ts +20 -0
- package/dist/templates/default/app/i18n/zh-TW.ts +19 -0
- package/dist/templates/default/package.json +2 -2
- package/dist/templates/headless/package.json +3 -3
- package/dist/templates/workspace-core/package.json +6 -6
- package/dist/templates/workspace-root/package.json +2 -2
- package/dist/triggers/dispatcher.js +27 -2
- package/dist/triggers/dispatcher.js.map +1 -1
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +70 -1
- package/dist/vite/client.js.map +1 -1
- package/package.json +7 -6
- package/src/templates/default/app/i18n/ar-SA.ts +21 -0
- package/src/templates/default/app/i18n/de-DE.ts +21 -0
- package/src/templates/default/app/i18n/en-US.ts +21 -0
- package/src/templates/default/app/i18n/es-ES.ts +21 -0
- package/src/templates/default/app/i18n/fr-FR.ts +21 -0
- package/src/templates/default/app/i18n/hi-IN.ts +20 -0
- package/src/templates/default/app/i18n/ja-JP.ts +21 -0
- package/src/templates/default/app/i18n/ko-KR.ts +20 -0
- package/src/templates/default/app/i18n/pt-BR.ts +21 -0
- package/src/templates/default/app/i18n/zh-CN.ts +20 -0
- package/src/templates/default/app/i18n/zh-TW.ts +19 -0
- package/src/templates/default/package.json +2 -2
- package/src/templates/headless/package.json +3 -3
- package/src/templates/workspace-core/package.json +6 -6
- package/src/templates/workspace-root/package.json +2 -2
|
@@ -1,16 +1,32 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
IconAlertCircle,
|
|
3
|
+
IconChevronDown,
|
|
4
|
+
IconNotes,
|
|
5
|
+
IconVideo,
|
|
6
|
+
IconX,
|
|
7
|
+
} from "@tabler/icons-react";
|
|
2
8
|
import { invoke } from "@tauri-apps/api/core";
|
|
3
9
|
import { emit, listen } from "@tauri-apps/api/event";
|
|
4
10
|
import { getCurrentWindow } from "@tauri-apps/api/window";
|
|
5
11
|
import { open as openExternal } from "@tauri-apps/plugin-shell";
|
|
6
12
|
import { useEffect, useRef, useState } from "react";
|
|
7
13
|
|
|
14
|
+
import {
|
|
15
|
+
detectMeetingJoinProvider,
|
|
16
|
+
joinProviderLabel,
|
|
17
|
+
meetingNotificationAutoHideMs,
|
|
18
|
+
type MeetingJoinProvider,
|
|
19
|
+
} from "../lib/meeting-notification-timing";
|
|
20
|
+
|
|
8
21
|
interface NotificationData {
|
|
9
22
|
type: "calendar" | "adhoc";
|
|
10
23
|
title: string;
|
|
11
24
|
subtitle: string;
|
|
12
25
|
meetingId: string;
|
|
13
26
|
joinUrl?: string | null;
|
|
27
|
+
platform?: string | null;
|
|
28
|
+
scheduledStart?: string | null;
|
|
29
|
+
scheduledEnd?: string | null;
|
|
14
30
|
autoStart?: boolean;
|
|
15
31
|
}
|
|
16
32
|
|
|
@@ -19,12 +35,11 @@ interface TranscriptionStatusPayload {
|
|
|
19
35
|
error?: string;
|
|
20
36
|
}
|
|
21
37
|
|
|
22
|
-
const DEFAULT_AUTO_HIDE_MS = 30_000;
|
|
23
38
|
const SNOOZE_MS = 5 * 60_000;
|
|
39
|
+
const FALLBACK_AUTO_HIDE_MS = 6 * 60_000;
|
|
24
40
|
|
|
25
41
|
/**
|
|
26
|
-
* Open a meeting join URL via the Tauri shell plugin.
|
|
27
|
-
* notification's dedicated Join CTA (notes start is a separate action).
|
|
42
|
+
* Open a meeting join URL via the Tauri shell plugin.
|
|
28
43
|
*/
|
|
29
44
|
async function openJoinUrl(url: string | null | undefined): Promise<void> {
|
|
30
45
|
if (!url) return;
|
|
@@ -35,40 +50,71 @@ async function openJoinUrl(url: string | null | undefined): Promise<void> {
|
|
|
35
50
|
}
|
|
36
51
|
}
|
|
37
52
|
|
|
53
|
+
function ProviderGlyph({ provider }: { provider: MeetingJoinProvider }) {
|
|
54
|
+
// Lightweight glyphs — keep the overlay free of extra assets. Zoom blue
|
|
55
|
+
// camera / Meet green / Teams purple, otherwise a generic video icon.
|
|
56
|
+
if (provider === "zoom") {
|
|
57
|
+
return (
|
|
58
|
+
<span
|
|
59
|
+
className="meeting-notification-provider meeting-notification-provider-zoom"
|
|
60
|
+
aria-hidden
|
|
61
|
+
>
|
|
62
|
+
<IconVideo size={14} stroke={2.2} />
|
|
63
|
+
</span>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
if (provider === "meet") {
|
|
67
|
+
return (
|
|
68
|
+
<span
|
|
69
|
+
className="meeting-notification-provider meeting-notification-provider-meet"
|
|
70
|
+
aria-hidden
|
|
71
|
+
>
|
|
72
|
+
<IconVideo size={14} stroke={2.2} />
|
|
73
|
+
</span>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
if (provider === "teams") {
|
|
77
|
+
return (
|
|
78
|
+
<span
|
|
79
|
+
className="meeting-notification-provider meeting-notification-provider-teams"
|
|
80
|
+
aria-hidden
|
|
81
|
+
>
|
|
82
|
+
<IconVideo size={14} stroke={2.2} />
|
|
83
|
+
</span>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
return (
|
|
87
|
+
<span
|
|
88
|
+
className="meeting-notification-provider meeting-notification-provider-other"
|
|
89
|
+
aria-hidden
|
|
90
|
+
>
|
|
91
|
+
<IconNotes size={14} stroke={2.2} />
|
|
92
|
+
</span>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
38
96
|
/**
|
|
39
97
|
* Granola-style meeting notification — small card in the top-right corner.
|
|
40
|
-
* Variants:
|
|
41
98
|
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* - Ad-hoc call: dashed left bar (slate), "Call detected", app name,
|
|
45
|
-
* same controls.
|
|
99
|
+
* Primary split button: join the call and open Clips notes in one click.
|
|
100
|
+
* Chevron exposes secondary actions (join only / notes only / snooze).
|
|
46
101
|
*
|
|
47
|
-
* Data arrives via Tauri event `meetings:show-notification`.
|
|
48
|
-
*
|
|
49
|
-
* persistent popover transcription session surface inline beneath the title
|
|
50
|
-
* so the user isn't left wondering why nothing happened.
|
|
102
|
+
* Data arrives via Tauri event `meetings:show-notification`. Visibility holds
|
|
103
|
+
* from 1 minute before start until 5 minutes after, unless dismissed.
|
|
51
104
|
*/
|
|
52
105
|
export function MeetingNotification() {
|
|
53
106
|
const [data, setData] = useState<NotificationData | null>(null);
|
|
54
107
|
const [showClose, setShowClose] = useState(false);
|
|
108
|
+
const [menuOpen, setMenuOpen] = useState(false);
|
|
55
109
|
const [error, setError] = useState<string | null>(null);
|
|
56
110
|
const [pending, setPending] = useState(false);
|
|
57
111
|
const autoHideTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
58
112
|
const dataRef = useRef<NotificationData | null>(null);
|
|
59
113
|
|
|
60
|
-
// Keep a ref to the latest data so the transcription-status listeners can
|
|
61
|
-
// match incoming events against the meeting currently on screen without
|
|
62
|
-
// re-subscribing on every render.
|
|
63
114
|
useEffect(() => {
|
|
64
115
|
dataRef.current = data;
|
|
65
116
|
}, [data]);
|
|
66
117
|
|
|
67
|
-
// The notification window is a single persistent overlay (created once at
|
|
68
|
-
// startup so it can receive `meetings:show-notification` events). Drive its
|
|
69
|
-
// OS-level visibility from React state: a shown-but-empty transparent window
|
|
70
|
-
// would otherwise sit at the top of the screen swallowing clicks. Visible
|
|
71
|
-
// only while there's a notification on screen.
|
|
72
118
|
useEffect(() => {
|
|
73
119
|
const win = getCurrentWindow();
|
|
74
120
|
if (data) {
|
|
@@ -84,8 +130,15 @@ export function MeetingNotification() {
|
|
|
84
130
|
) {
|
|
85
131
|
setData(payload);
|
|
86
132
|
setError(null);
|
|
133
|
+
setMenuOpen(false);
|
|
87
134
|
setPending(!!payload.autoStart && !options?.hydrated);
|
|
88
|
-
|
|
135
|
+
const startMs = payload.scheduledStart
|
|
136
|
+
? Date.parse(payload.scheduledStart)
|
|
137
|
+
: NaN;
|
|
138
|
+
const hideMs = Number.isFinite(startMs)
|
|
139
|
+
? meetingNotificationAutoHideMs(startMs)
|
|
140
|
+
: FALLBACK_AUTO_HIDE_MS;
|
|
141
|
+
scheduleAutoHide(hideMs);
|
|
89
142
|
}
|
|
90
143
|
|
|
91
144
|
useEffect(() => {
|
|
@@ -112,6 +165,15 @@ export function MeetingNotification() {
|
|
|
112
165
|
}),
|
|
113
166
|
);
|
|
114
167
|
|
|
168
|
+
// Cold overlay boot: hydrate any payload stored before this webview
|
|
169
|
+
// mounted (calendar or adhoc).
|
|
170
|
+
invoke<NotificationData | null>("take_pending_meeting_notification")
|
|
171
|
+
.then((pending) => {
|
|
172
|
+
if (stopped || !pending) return;
|
|
173
|
+
showNotification(pending, { hydrated: true });
|
|
174
|
+
})
|
|
175
|
+
.catch(() => {});
|
|
176
|
+
|
|
115
177
|
trackListen(
|
|
116
178
|
listen<TranscriptionStatusPayload>("meetings:hide-notification", (ev) => {
|
|
117
179
|
if (ev.payload.meetingId !== dataRef.current?.meetingId) return;
|
|
@@ -154,14 +216,30 @@ export function MeetingNotification() {
|
|
|
154
216
|
|
|
155
217
|
function scheduleAutoHide(ms: number) {
|
|
156
218
|
clearAutoHide();
|
|
219
|
+
if (ms <= 0) {
|
|
220
|
+
hideNotification();
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
157
223
|
autoHideTimerRef.current = setTimeout(() => hideNotification(), ms);
|
|
158
224
|
}
|
|
159
225
|
|
|
226
|
+
function resumeAutoHide() {
|
|
227
|
+
const current = dataRef.current;
|
|
228
|
+
const startMs = current?.scheduledStart
|
|
229
|
+
? Date.parse(current.scheduledStart)
|
|
230
|
+
: NaN;
|
|
231
|
+
const hideMs = Number.isFinite(startMs)
|
|
232
|
+
? meetingNotificationAutoHideMs(startMs)
|
|
233
|
+
: FALLBACK_AUTO_HIDE_MS;
|
|
234
|
+
scheduleAutoHide(hideMs);
|
|
235
|
+
}
|
|
236
|
+
|
|
160
237
|
function hideNotification() {
|
|
161
238
|
clearAutoHide();
|
|
162
239
|
setData(null);
|
|
163
240
|
setError(null);
|
|
164
241
|
setPending(false);
|
|
242
|
+
setMenuOpen(false);
|
|
165
243
|
dataRef.current = null;
|
|
166
244
|
}
|
|
167
245
|
|
|
@@ -169,6 +247,7 @@ export function MeetingNotification() {
|
|
|
169
247
|
if (!data || pending) return;
|
|
170
248
|
setPending(true);
|
|
171
249
|
setError(null);
|
|
250
|
+
setMenuOpen(false);
|
|
172
251
|
emit("meetings:start-transcription", {
|
|
173
252
|
meetingId: data.meetingId,
|
|
174
253
|
joinUrl: data.joinUrl,
|
|
@@ -181,14 +260,23 @@ export function MeetingNotification() {
|
|
|
181
260
|
|
|
182
261
|
async function joinMeeting() {
|
|
183
262
|
if (!data?.joinUrl) return;
|
|
263
|
+
setMenuOpen(false);
|
|
184
264
|
await openJoinUrl(data.joinUrl);
|
|
185
265
|
}
|
|
186
266
|
|
|
267
|
+
/** Granola primary: join the call and start Clips notes together. */
|
|
268
|
+
async function joinAndOpenClips() {
|
|
269
|
+
if (!data || pending) return;
|
|
270
|
+
setMenuOpen(false);
|
|
271
|
+
if (data.joinUrl) {
|
|
272
|
+
await openJoinUrl(data.joinUrl);
|
|
273
|
+
}
|
|
274
|
+
await takeNotes();
|
|
275
|
+
}
|
|
276
|
+
|
|
187
277
|
function snooze() {
|
|
188
278
|
if (!data) return;
|
|
189
|
-
|
|
190
|
-
// delay even though this overlay window closes right away. A setTimeout
|
|
191
|
-
// here would be torn down with the window and never fire.
|
|
279
|
+
setMenuOpen(false);
|
|
192
280
|
invoke("meetings_snooze", {
|
|
193
281
|
meetingId: data.meetingId,
|
|
194
282
|
minutes: Math.round(SNOOZE_MS / 60_000),
|
|
@@ -202,6 +290,14 @@ export function MeetingNotification() {
|
|
|
202
290
|
|
|
203
291
|
const isCalendar = data.type === "calendar";
|
|
204
292
|
const hasJoin = Boolean(data.joinUrl);
|
|
293
|
+
const provider = detectMeetingJoinProvider(data.joinUrl, data.platform);
|
|
294
|
+
const providerName = joinProviderLabel(provider);
|
|
295
|
+
const primaryLabel = hasJoin
|
|
296
|
+
? provider === "other"
|
|
297
|
+
? "Join meeting"
|
|
298
|
+
: `Join ${providerName}`
|
|
299
|
+
: "Start notes";
|
|
300
|
+
const secondaryLabel = hasJoin ? "& open Clips" : null;
|
|
205
301
|
|
|
206
302
|
return (
|
|
207
303
|
<div
|
|
@@ -212,14 +308,11 @@ export function MeetingNotification() {
|
|
|
212
308
|
}}
|
|
213
309
|
onMouseLeave={() => {
|
|
214
310
|
setShowClose(false);
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
scheduleAutoHide(DEFAULT_AUTO_HIDE_MS);
|
|
311
|
+
setMenuOpen(false);
|
|
312
|
+
resumeAutoHide();
|
|
218
313
|
}}
|
|
219
314
|
>
|
|
220
|
-
<div
|
|
221
|
-
className={`meeting-notification${hasJoin ? " meeting-notification-with-join" : ""}`}
|
|
222
|
-
>
|
|
315
|
+
<div className="meeting-notification">
|
|
223
316
|
<div
|
|
224
317
|
className={`meeting-notification-bar ${isCalendar ? "meeting-notification-bar-calendar" : "meeting-notification-bar-adhoc"}`}
|
|
225
318
|
/>
|
|
@@ -233,34 +326,65 @@ export function MeetingNotification() {
|
|
|
233
326
|
</div>
|
|
234
327
|
) : null}
|
|
235
328
|
</div>
|
|
236
|
-
<div className="meeting-notification-
|
|
329
|
+
<div className="meeting-notification-split">
|
|
237
330
|
<button
|
|
238
|
-
className="meeting-notification-
|
|
239
|
-
onClick={takeNotes}
|
|
331
|
+
className="meeting-notification-split-main"
|
|
332
|
+
onClick={hasJoin ? joinAndOpenClips : takeNotes}
|
|
240
333
|
disabled={pending}
|
|
241
334
|
data-no-drag
|
|
242
335
|
>
|
|
243
|
-
{
|
|
336
|
+
<ProviderGlyph provider={provider} />
|
|
337
|
+
<span className="meeting-notification-split-copy">
|
|
338
|
+
<span className="meeting-notification-split-primary">
|
|
339
|
+
{pending ? "Starting…" : primaryLabel}
|
|
340
|
+
</span>
|
|
341
|
+
{secondaryLabel && !pending ? (
|
|
342
|
+
<span className="meeting-notification-split-secondary">
|
|
343
|
+
{secondaryLabel}
|
|
344
|
+
</span>
|
|
345
|
+
) : null}
|
|
346
|
+
</span>
|
|
244
347
|
</button>
|
|
245
|
-
{hasJoin ? (
|
|
246
|
-
<button
|
|
247
|
-
className="meeting-notification-btn meeting-notification-btn-secondary"
|
|
248
|
-
onClick={joinMeeting}
|
|
249
|
-
data-no-drag
|
|
250
|
-
>
|
|
251
|
-
Join
|
|
252
|
-
</button>
|
|
253
|
-
) : null}
|
|
254
348
|
<button
|
|
255
|
-
className="meeting-notification-
|
|
256
|
-
onClick={
|
|
349
|
+
className="meeting-notification-split-chevron"
|
|
350
|
+
onClick={() => setMenuOpen((open) => !open)}
|
|
351
|
+
aria-label="More actions"
|
|
352
|
+
aria-expanded={menuOpen}
|
|
257
353
|
data-no-drag
|
|
258
|
-
aria-label="Snooze 5 minutes"
|
|
259
|
-
title="Snooze 5 min"
|
|
260
354
|
>
|
|
261
|
-
<
|
|
262
|
-
<span>5m</span>
|
|
355
|
+
<IconChevronDown size={14} aria-hidden="true" />
|
|
263
356
|
</button>
|
|
357
|
+
{menuOpen ? (
|
|
358
|
+
<div className="meeting-notification-menu" role="menu">
|
|
359
|
+
{hasJoin ? (
|
|
360
|
+
<button
|
|
361
|
+
role="menuitem"
|
|
362
|
+
className="meeting-notification-menu-item"
|
|
363
|
+
onClick={joinMeeting}
|
|
364
|
+
data-no-drag
|
|
365
|
+
>
|
|
366
|
+
Join only
|
|
367
|
+
</button>
|
|
368
|
+
) : null}
|
|
369
|
+
<button
|
|
370
|
+
role="menuitem"
|
|
371
|
+
className="meeting-notification-menu-item"
|
|
372
|
+
onClick={takeNotes}
|
|
373
|
+
disabled={pending}
|
|
374
|
+
data-no-drag
|
|
375
|
+
>
|
|
376
|
+
Start notes only
|
|
377
|
+
</button>
|
|
378
|
+
<button
|
|
379
|
+
role="menuitem"
|
|
380
|
+
className="meeting-notification-menu-item"
|
|
381
|
+
onClick={snooze}
|
|
382
|
+
data-no-drag
|
|
383
|
+
>
|
|
384
|
+
Snooze 5 min
|
|
385
|
+
</button>
|
|
386
|
+
</div>
|
|
387
|
+
) : null}
|
|
264
388
|
</div>
|
|
265
389
|
{showClose ? (
|
|
266
390
|
<button
|
|
@@ -25,7 +25,9 @@
|
|
|
25
25
|
--radius: 12px;
|
|
26
26
|
--radius-sm: 8px;
|
|
27
27
|
--radius-pill: 999px;
|
|
28
|
-
|
|
28
|
+
/* Must cover `--shadow-md` blur (24px in dark mode) or the transparent
|
|
29
|
+
Tauri window clips the drop shadow on every edge. */
|
|
30
|
+
--popover-shadow-gutter: 24px;
|
|
29
31
|
--overlay-shadow-gutter: 18px;
|
|
30
32
|
|
|
31
33
|
--shadow-sm: 0 1px 2px rgba(23, 23, 23, 0.06);
|
|
@@ -1419,6 +1421,13 @@ body[data-clips-route="recording-pill"] #root {
|
|
|
1419
1421
|
overscroll-behavior: contain;
|
|
1420
1422
|
}
|
|
1421
1423
|
|
|
1424
|
+
/* Meetings / dictation drill-ins: a touch more room under the last row so
|
|
1425
|
+
content isn't flush with the panel edge. Must follow `.setup` so it wins
|
|
1426
|
+
over the shorthand padding above. */
|
|
1427
|
+
.setup.popover-view {
|
|
1428
|
+
padding-bottom: 20px;
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1422
1431
|
.setup h2 {
|
|
1423
1432
|
margin: 0;
|
|
1424
1433
|
font-size: 14px;
|
|
@@ -3599,7 +3608,7 @@ body[data-clips-route="recording-pill"] #root {
|
|
|
3599
3608
|
position: relative;
|
|
3600
3609
|
display: flex;
|
|
3601
3610
|
align-items: center;
|
|
3602
|
-
gap:
|
|
3611
|
+
gap: 12px;
|
|
3603
3612
|
padding: 12px 14px;
|
|
3604
3613
|
border-radius: 14px;
|
|
3605
3614
|
background: rgba(20, 22, 28, 0.94);
|
|
@@ -3611,37 +3620,26 @@ body[data-clips-route="recording-pill"] #root {
|
|
|
3611
3620
|
0 2px 6px rgba(0, 0, 0, 0.3);
|
|
3612
3621
|
color: white;
|
|
3613
3622
|
pointer-events: auto;
|
|
3614
|
-
min-width:
|
|
3615
|
-
max-width:
|
|
3616
|
-
}
|
|
3617
|
-
|
|
3618
|
-
.meeting-notification-with-join {
|
|
3619
|
-
flex-wrap: wrap;
|
|
3620
|
-
align-items: flex-start;
|
|
3621
|
-
row-gap: 10px;
|
|
3622
|
-
}
|
|
3623
|
-
|
|
3624
|
-
.meeting-notification-with-join .meeting-notification-actions {
|
|
3625
|
-
flex: 1 1 100%;
|
|
3626
|
-
justify-content: flex-end;
|
|
3627
|
-
padding-left: 13px; /* align under content past the bar */
|
|
3623
|
+
min-width: 320px;
|
|
3624
|
+
max-width: 440px;
|
|
3628
3625
|
}
|
|
3629
3626
|
|
|
3630
3627
|
.meeting-notification-bar {
|
|
3631
3628
|
width: 3px;
|
|
3632
|
-
height:
|
|
3633
|
-
border-radius:
|
|
3629
|
+
height: 36px;
|
|
3630
|
+
border-radius: 999px;
|
|
3634
3631
|
flex-shrink: 0;
|
|
3635
3632
|
}
|
|
3636
3633
|
|
|
3637
3634
|
.meeting-notification-bar-calendar {
|
|
3638
|
-
background: #
|
|
3635
|
+
background: #7dd3fc;
|
|
3639
3636
|
}
|
|
3640
3637
|
|
|
3641
3638
|
.meeting-notification-bar-adhoc {
|
|
3642
3639
|
background: transparent;
|
|
3643
3640
|
border-left: 3px dashed #a3a3a3;
|
|
3644
3641
|
width: 3px;
|
|
3642
|
+
border-radius: 0;
|
|
3645
3643
|
}
|
|
3646
3644
|
|
|
3647
3645
|
.meeting-notification-content {
|
|
@@ -3650,6 +3648,7 @@ body[data-clips-route="recording-pill"] #root {
|
|
|
3650
3648
|
display: flex;
|
|
3651
3649
|
flex-direction: column;
|
|
3652
3650
|
gap: 2px;
|
|
3651
|
+
padding-right: 4px;
|
|
3653
3652
|
}
|
|
3654
3653
|
|
|
3655
3654
|
.meeting-notification-title {
|
|
@@ -3666,65 +3665,141 @@ body[data-clips-route="recording-pill"] #root {
|
|
|
3666
3665
|
color: rgba(255, 255, 255, 0.55);
|
|
3667
3666
|
}
|
|
3668
3667
|
|
|
3669
|
-
.meeting-notification-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
background: rgba(255, 255, 255, 0.1);
|
|
3674
|
-
color: white;
|
|
3675
|
-
font-size: 12px;
|
|
3676
|
-
font-weight: 600;
|
|
3677
|
-
cursor: pointer;
|
|
3678
|
-
white-space: nowrap;
|
|
3668
|
+
.meeting-notification-split {
|
|
3669
|
+
position: relative;
|
|
3670
|
+
display: inline-flex;
|
|
3671
|
+
align-items: stretch;
|
|
3679
3672
|
flex-shrink: 0;
|
|
3673
|
+
border: 1px solid rgba(255, 255, 255, 0.14);
|
|
3674
|
+
border-radius: 10px;
|
|
3675
|
+
overflow: visible;
|
|
3676
|
+
background: rgba(255, 255, 255, 0.04);
|
|
3680
3677
|
}
|
|
3681
3678
|
|
|
3682
|
-
.meeting-notification-
|
|
3683
|
-
|
|
3679
|
+
.meeting-notification-split-main {
|
|
3680
|
+
display: inline-flex;
|
|
3681
|
+
align-items: center;
|
|
3682
|
+
gap: 8px;
|
|
3683
|
+
border: none;
|
|
3684
|
+
background: transparent;
|
|
3685
|
+
color: white;
|
|
3686
|
+
padding: 6px 10px;
|
|
3687
|
+
cursor: pointer;
|
|
3688
|
+
text-align: left;
|
|
3689
|
+
min-height: 40px;
|
|
3684
3690
|
}
|
|
3685
3691
|
|
|
3686
|
-
.meeting-notification-
|
|
3687
|
-
|
|
3692
|
+
.meeting-notification-split-main:hover {
|
|
3693
|
+
background: rgba(255, 255, 255, 0.06);
|
|
3688
3694
|
}
|
|
3689
3695
|
|
|
3690
|
-
.meeting-notification-
|
|
3691
|
-
opacity: 0.
|
|
3696
|
+
.meeting-notification-split-main:disabled {
|
|
3697
|
+
opacity: 0.65;
|
|
3692
3698
|
cursor: progress;
|
|
3693
3699
|
}
|
|
3694
3700
|
|
|
3695
|
-
.meeting-notification-
|
|
3696
|
-
|
|
3697
|
-
|
|
3701
|
+
.meeting-notification-split-copy {
|
|
3702
|
+
display: flex;
|
|
3703
|
+
flex-direction: column;
|
|
3704
|
+
gap: 0;
|
|
3705
|
+
line-height: 1.15;
|
|
3698
3706
|
}
|
|
3699
3707
|
|
|
3700
|
-
.meeting-notification-
|
|
3701
|
-
|
|
3708
|
+
.meeting-notification-split-primary {
|
|
3709
|
+
font-size: 12px;
|
|
3710
|
+
font-weight: 600;
|
|
3711
|
+
color: white;
|
|
3712
|
+
white-space: nowrap;
|
|
3702
3713
|
}
|
|
3703
3714
|
|
|
3704
|
-
.meeting-notification-
|
|
3705
|
-
|
|
3706
|
-
|
|
3715
|
+
.meeting-notification-split-secondary {
|
|
3716
|
+
font-size: 10px;
|
|
3717
|
+
font-weight: 500;
|
|
3718
|
+
color: rgba(255, 255, 255, 0.55);
|
|
3719
|
+
white-space: nowrap;
|
|
3707
3720
|
}
|
|
3708
3721
|
|
|
3709
|
-
.meeting-notification-
|
|
3722
|
+
.meeting-notification-split-chevron {
|
|
3710
3723
|
display: inline-flex;
|
|
3711
3724
|
align-items: center;
|
|
3712
|
-
|
|
3713
|
-
|
|
3725
|
+
justify-content: center;
|
|
3726
|
+
width: 28px;
|
|
3727
|
+
border: none;
|
|
3728
|
+
border-left: 1px solid rgba(255, 255, 255, 0.12);
|
|
3729
|
+
background: transparent;
|
|
3730
|
+
color: rgba(255, 255, 255, 0.75);
|
|
3731
|
+
cursor: pointer;
|
|
3732
|
+
border-radius: 0 10px 10px 0;
|
|
3714
3733
|
}
|
|
3715
3734
|
|
|
3716
|
-
.meeting-notification-
|
|
3735
|
+
.meeting-notification-split-chevron:hover {
|
|
3736
|
+
background: rgba(255, 255, 255, 0.06);
|
|
3737
|
+
color: white;
|
|
3738
|
+
}
|
|
3739
|
+
|
|
3740
|
+
.meeting-notification-provider {
|
|
3741
|
+
width: 22px;
|
|
3742
|
+
height: 22px;
|
|
3743
|
+
border-radius: 6px;
|
|
3717
3744
|
display: inline-flex;
|
|
3718
3745
|
align-items: center;
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
color: rgba(255, 255, 255, 0.85);
|
|
3746
|
+
justify-content: center;
|
|
3747
|
+
flex-shrink: 0;
|
|
3748
|
+
color: white;
|
|
3723
3749
|
}
|
|
3724
3750
|
|
|
3725
|
-
.meeting-notification-
|
|
3751
|
+
.meeting-notification-provider-zoom {
|
|
3752
|
+
background: #2d8cff;
|
|
3753
|
+
}
|
|
3754
|
+
|
|
3755
|
+
.meeting-notification-provider-meet {
|
|
3756
|
+
background: #34a853;
|
|
3757
|
+
}
|
|
3758
|
+
|
|
3759
|
+
.meeting-notification-provider-teams {
|
|
3760
|
+
background: #6264a7;
|
|
3761
|
+
}
|
|
3762
|
+
|
|
3763
|
+
.meeting-notification-provider-other {
|
|
3726
3764
|
background: rgba(255, 255, 255, 0.12);
|
|
3727
|
-
|
|
3765
|
+
}
|
|
3766
|
+
|
|
3767
|
+
.meeting-notification-menu {
|
|
3768
|
+
position: absolute;
|
|
3769
|
+
top: calc(100% + 6px);
|
|
3770
|
+
right: 0;
|
|
3771
|
+
min-width: 160px;
|
|
3772
|
+
padding: 4px;
|
|
3773
|
+
border-radius: 10px;
|
|
3774
|
+
background: rgba(24, 26, 32, 0.98);
|
|
3775
|
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
3776
|
+
box-shadow: 0 12px 28px rgba(0, 0, 0, 0.4);
|
|
3777
|
+
z-index: 5;
|
|
3778
|
+
display: flex;
|
|
3779
|
+
flex-direction: column;
|
|
3780
|
+
gap: 2px;
|
|
3781
|
+
}
|
|
3782
|
+
|
|
3783
|
+
.meeting-notification-menu-item {
|
|
3784
|
+
border: none;
|
|
3785
|
+
background: transparent;
|
|
3786
|
+
color: rgba(255, 255, 255, 0.9);
|
|
3787
|
+
text-align: left;
|
|
3788
|
+
font-size: 12px;
|
|
3789
|
+
font-weight: 500;
|
|
3790
|
+
padding: 8px 10px;
|
|
3791
|
+
border-radius: 7px;
|
|
3792
|
+
cursor: pointer;
|
|
3793
|
+
white-space: nowrap;
|
|
3794
|
+
}
|
|
3795
|
+
|
|
3796
|
+
.meeting-notification-menu-item:hover {
|
|
3797
|
+
background: rgba(255, 255, 255, 0.08);
|
|
3798
|
+
}
|
|
3799
|
+
|
|
3800
|
+
.meeting-notification-menu-item:disabled {
|
|
3801
|
+
opacity: 0.5;
|
|
3802
|
+
cursor: progress;
|
|
3728
3803
|
}
|
|
3729
3804
|
|
|
3730
3805
|
.meeting-notification-error {
|