mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-06-27 20:29:44 +02:00
option to join meeting and take notes
This commit is contained in:
parent
d363363b70
commit
0107dc5dbf
7 changed files with 84 additions and 36 deletions
|
|
@ -1524,7 +1524,13 @@ export const BuiltinTools: z.infer<typeof BuiltinToolsSchema> = {
|
|||
link: z.string().url().refine((v) => /^(https?|rowboat):\/\//i.test(v), {
|
||||
message: "link must be an http(s):// or rowboat:// URL",
|
||||
}).optional().describe("Optional URL opened when the user clicks the notification. Accepts http(s):// (opens in browser) or rowboat:// (opens a view inside Rowboat — see the notify-user skill for deep-link shapes)."),
|
||||
actionLabel: z.string().min(1).max(20).optional().describe("Optional label for an inline action button on the notification (e.g. 'Open', 'View', 'Take Notes'). Only shown when `link` is set. Click on the button triggers the same action as clicking the notification body. Note: macOS may render the button inline (Banner) or behind a chevron (Alert) depending on the user's notification style for Rowboat."),
|
||||
actionLabel: z.string().min(1).max(20).optional().describe("Optional label for an inline action button on the notification (e.g. 'Open', 'View', 'Take Notes'). Only shown when `link` is set. Click on the button triggers the same action as clicking the notification body."),
|
||||
secondaryActions: z.array(z.object({
|
||||
label: z.string().min(1).max(30),
|
||||
link: z.string().url().refine((v) => /^(https?|rowboat):\/\//i.test(v), {
|
||||
message: "secondary action link must be an http(s):// or rowboat:// URL",
|
||||
}),
|
||||
})).max(4).optional().describe("Additional action buttons. macOS shows them in the chevron menu next to the primary button (or all inline in Alert style). Each has its own label and link — clicking the button triggers that link, independent of the primary `link`."),
|
||||
}),
|
||||
isAvailable: async () => {
|
||||
try {
|
||||
|
|
@ -1533,13 +1539,13 @@ export const BuiltinTools: z.infer<typeof BuiltinToolsSchema> = {
|
|||
return false;
|
||||
}
|
||||
},
|
||||
execute: async ({ title, message, link, actionLabel }: { title?: string; message: string; link?: string; actionLabel?: string }) => {
|
||||
execute: async ({ title, message, link, actionLabel, secondaryActions }: { title?: string; message: string; link?: string; actionLabel?: string; secondaryActions?: Array<{ label: string; link: string }> }) => {
|
||||
try {
|
||||
const service = container.resolve<INotificationService>('notificationService');
|
||||
if (!service.isSupported()) {
|
||||
return { success: false, error: 'Notifications are not supported on this system' };
|
||||
}
|
||||
service.notify({ title, message, link, actionLabel });
|
||||
service.notify({ title, message, link, actionLabel, secondaryActions });
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ export interface NotifyInput {
|
|||
message: string;
|
||||
link?: string;
|
||||
actionLabel?: string;
|
||||
secondaryActions?: Array<{ label: string; link: string }>;
|
||||
}
|
||||
|
||||
export interface INotificationService {
|
||||
|
|
|
|||
|
|
@ -121,14 +121,22 @@ async function tick(state: NotificationState): Promise<{ state: NotificationStat
|
|||
if (msUntilStart < -NOTIFY_GRACE_MS) continue;
|
||||
|
||||
const summary = event.summary?.trim() || "Untitled meeting";
|
||||
const link = `rowboat://action?type=take-meeting-notes&eventId=${encodeURIComponent(eventId)}`;
|
||||
const eid = encodeURIComponent(eventId);
|
||||
|
||||
try {
|
||||
service.notify({
|
||||
title: "Upcoming meeting",
|
||||
message: `${summary} starts in 1 minute. Click to take notes.`,
|
||||
link,
|
||||
actionLabel: "Take Notes",
|
||||
message: `${summary} starts in 1 minute. Click to join and take notes.`,
|
||||
// Primary (body click + first button): join the meeting AND take notes.
|
||||
link: `rowboat://action?type=join-and-take-meeting-notes&eventId=${eid}`,
|
||||
actionLabel: "Join meeting and take notes",
|
||||
// Behind the chevron: just take notes (no join).
|
||||
secondaryActions: [
|
||||
{
|
||||
label: "Take notes",
|
||||
link: `rowboat://action?type=take-meeting-notes&eventId=${eid}`,
|
||||
},
|
||||
],
|
||||
});
|
||||
console.log(`[CalendarNotify] notified for "${summary}" (${eventId})`);
|
||||
} catch (err) {
|
||||
|
|
|
|||
|
|
@ -302,6 +302,9 @@ const ipcSchemas = {
|
|||
req: z.object({
|
||||
// Pass the raw calendar event JSON through; renderer adapts to its existing flow.
|
||||
event: z.unknown(),
|
||||
// When true, the renderer should also open the meeting URL (Zoom/Meet/etc.)
|
||||
// in addition to triggering the take-notes flow.
|
||||
openMeeting: z.boolean().optional(),
|
||||
}),
|
||||
res: z.null(),
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue