-
+
+ {isRecordedSession
+ ?
+ :
}
- {session.title || "Untitled"}
+ {linkedEvent.data?.name || session.title || "Untitled"}
-
- {showTime && (
-
- {format(getStartDate(), "h:mm a")} - {format(getEndDate(), "h:mm a")}
-
- )}
-
- {session.title || "Untitled"}
-
+
+ {linkedEvent.data?.name || session.title || "Untitled"}
+
- {format(getStartDate(), "MMM d, h:mm a")}
- {" - "}
- {format(getStartDate(), "yyyy-MM-dd")
- !== format(getEndDate(), "yyyy-MM-dd")
- ? format(getEndDate(), "MMM d, h:mm a")
- : format(getEndDate(), "h:mm a")}
+ {shouldShowRange
+ ? (
+ <>
+ {format(getStartDate(), "MMM d, h:mm a")}
+ {" - "}
+ {format(getStartDate(), "yyyy-MM-dd")
+ !== format(getEndDate(), "yyyy-MM-dd")
+ ? format(getEndDate(), "MMM d, h:mm a")
+ : format(getEndDate(), "h:mm a")}
+ >
+ )
+ : (
+ <>
+ Created: {format(getStartDate(), "MMM d, h:mm a")}
+ >
+ )}
{participantsPreview && participantsPreview.length > 0 && (
-
+
{participantsPreview.join(", ")}
)}
-
+ {isRecordedSession
+ ?
+ :
}
+
+ {linkedEvent.data?.name || session.title || "Untitled"}
+
+
);
diff --git a/apps/desktop/src/locales/en/messages.po b/apps/desktop/src/locales/en/messages.po
index 20523a2348..6ca5479c0b 100644
--- a/apps/desktop/src/locales/en/messages.po
+++ b/apps/desktop/src/locales/en/messages.po
@@ -368,7 +368,7 @@ msgid "Apple"
msgstr "Apple"
#: src/components/toolbar/buttons/delete-note-button.tsx:43
-#: src/components/left-sidebar/notes-list.tsx:268
+#: src/components/left-sidebar/notes-list.tsx:266
msgid "Are you sure you want to delete this note?"
msgstr "Are you sure you want to delete this note?"
@@ -528,7 +528,7 @@ msgstr "Create agenda"
msgid "Create new note"
msgstr "Create new note"
-#: src/components/workspace-calendar/event-card.tsx:166
+#: src/components/workspace-calendar/event-card.tsx:144
msgid "Create Note"
msgstr "Create Note"
@@ -558,7 +558,7 @@ msgstr "Custom Vocabulary"
#: src/components/settings/views/template.tsx:215
#: src/components/settings/views/team.tsx:165
-#: src/components/left-sidebar/notes-list.tsx:335
+#: src/components/left-sidebar/notes-list.tsx:333
msgid "Delete"
msgstr "Delete"
@@ -724,7 +724,7 @@ msgstr "Help us improve Hyprnote by sharing anonymous usage data"
msgid "Help us tailor your Hyprnote experience"
msgstr "Help us tailor your Hyprnote experience"
-#: src/components/left-sidebar/events-list.tsx:305
+#: src/components/left-sidebar/events-list.tsx:302
#~ msgid "Hide Event"
#~ msgstr "Hide Event"
@@ -805,7 +805,6 @@ msgstr "Loading events..."
msgid "Loading templates..."
msgstr "Loading templates..."
-#: src/components/workspace-calendar/event-card.tsx:163
#: src/components/settings/components/calendar/calendar-selector.tsx:95
msgid "Loading..."
msgstr "Loading..."
@@ -867,8 +866,8 @@ msgstr "My Templates"
msgid "New note"
msgstr "New note"
-#: src/components/left-sidebar/notes-list.tsx:312
-#: src/components/left-sidebar/events-list.tsx:181
+#: src/components/left-sidebar/notes-list.tsx:310
+#: src/components/left-sidebar/events-list.tsx:178
msgid "New window"
msgstr "New window"
@@ -912,7 +911,7 @@ msgstr "No Template (Default)"
msgid "No templates yet"
msgstr "No templates yet"
-#: src/components/left-sidebar/events-list.tsx:95
+#: src/components/left-sidebar/events-list.tsx:94
msgid "No upcoming events"
msgstr "No upcoming events"
@@ -941,23 +940,23 @@ msgstr "Official Templates"
#~ msgstr "Ooh! Suggestion!"
#: src/components/left-sidebar/top-area/calendar-button.tsx:26
-msgid "Open calendar view"
-msgstr "Open calendar view"
+#~ msgid "Open calendar view"
+#~ msgstr "Open calendar view"
#: src/components/left-sidebar/top-area/finder-button.tsx:26
-#~ msgid "Open finder view"
-#~ msgstr "Open finder view"
+msgid "Open finder view"
+msgstr "Open finder view"
#: src/components/toolbar/buttons/new-window-button.tsx:35
-#: src/components/left-sidebar/search-list.tsx:319
-#: src/components/left-sidebar/search-list.tsx:396
+#: src/components/left-sidebar/search-list.tsx:298
+#: src/components/left-sidebar/search-list.tsx:368
msgid "Open in new window"
msgstr "Open in new window"
#: src/components/workspace-calendar/note-card.tsx:123
#: src/components/workspace-calendar/event-card.tsx:153
-msgid "Open Note"
-msgstr "Open Note"
+#~ msgid "Open Note"
+#~ msgstr "Open Note"
#: src/components/settings/views/integrations.tsx:255
msgid "Optional base folder path within your Obsidian vault."
@@ -1206,7 +1205,7 @@ msgstr "This is a short description of your company."
msgid "This is the name of the company you work for."
msgstr "This is the name of the company you work for."
-#: src/components/toolbar/bars/calendar-toolbar.tsx:67
+#: src/components/finder/views/calendar-view.tsx:64
msgid "Today"
msgstr "Today"
@@ -1250,7 +1249,7 @@ msgstr "Untitled"
msgid "Untitled Template"
msgstr "Untitled Template"
-#: src/components/left-sidebar/events-list.tsx:62
+#: src/components/left-sidebar/events-list.tsx:61
msgid "Upcoming"
msgstr "Upcoming"
@@ -1282,11 +1281,11 @@ msgstr "username"
msgid "Vault Name"
msgstr "Vault Name"
-#: src/components/left-sidebar/notes-list.tsx:323
+#: src/components/left-sidebar/notes-list.tsx:321
msgid "View calendar"
msgstr "View calendar"
-#: src/components/left-sidebar/events-list.tsx:193
+#: src/components/left-sidebar/events-list.tsx:190
#: src/components/editor-area/note-header/chips/event-chip.tsx:246
msgid "View in calendar"
msgstr "View in calendar"
diff --git a/apps/desktop/src/locales/ko/messages.po b/apps/desktop/src/locales/ko/messages.po
index 234668df1c..af8640fb57 100644
--- a/apps/desktop/src/locales/ko/messages.po
+++ b/apps/desktop/src/locales/ko/messages.po
@@ -368,7 +368,7 @@ msgid "Apple"
msgstr ""
#: src/components/toolbar/buttons/delete-note-button.tsx:43
-#: src/components/left-sidebar/notes-list.tsx:268
+#: src/components/left-sidebar/notes-list.tsx:266
msgid "Are you sure you want to delete this note?"
msgstr ""
@@ -528,7 +528,7 @@ msgstr ""
msgid "Create new note"
msgstr ""
-#: src/components/workspace-calendar/event-card.tsx:166
+#: src/components/workspace-calendar/event-card.tsx:144
msgid "Create Note"
msgstr ""
@@ -558,7 +558,7 @@ msgstr ""
#: src/components/settings/views/template.tsx:215
#: src/components/settings/views/team.tsx:165
-#: src/components/left-sidebar/notes-list.tsx:335
+#: src/components/left-sidebar/notes-list.tsx:333
msgid "Delete"
msgstr ""
@@ -724,7 +724,7 @@ msgstr ""
msgid "Help us tailor your Hyprnote experience"
msgstr ""
-#: src/components/left-sidebar/events-list.tsx:305
+#: src/components/left-sidebar/events-list.tsx:302
#~ msgid "Hide Event"
#~ msgstr ""
@@ -805,7 +805,6 @@ msgstr ""
msgid "Loading templates..."
msgstr ""
-#: src/components/workspace-calendar/event-card.tsx:163
#: src/components/settings/components/calendar/calendar-selector.tsx:95
msgid "Loading..."
msgstr ""
@@ -867,8 +866,8 @@ msgstr ""
msgid "New note"
msgstr ""
-#: src/components/left-sidebar/notes-list.tsx:312
-#: src/components/left-sidebar/events-list.tsx:181
+#: src/components/left-sidebar/notes-list.tsx:310
+#: src/components/left-sidebar/events-list.tsx:178
msgid "New window"
msgstr ""
@@ -912,7 +911,7 @@ msgstr ""
msgid "No templates yet"
msgstr ""
-#: src/components/left-sidebar/events-list.tsx:95
+#: src/components/left-sidebar/events-list.tsx:94
msgid "No upcoming events"
msgstr ""
@@ -941,23 +940,23 @@ msgstr ""
#~ msgstr ""
#: src/components/left-sidebar/top-area/calendar-button.tsx:26
-msgid "Open calendar view"
-msgstr ""
+#~ msgid "Open calendar view"
+#~ msgstr ""
#: src/components/left-sidebar/top-area/finder-button.tsx:26
-#~ msgid "Open finder view"
-#~ msgstr ""
+msgid "Open finder view"
+msgstr ""
#: src/components/toolbar/buttons/new-window-button.tsx:35
-#: src/components/left-sidebar/search-list.tsx:319
-#: src/components/left-sidebar/search-list.tsx:396
+#: src/components/left-sidebar/search-list.tsx:298
+#: src/components/left-sidebar/search-list.tsx:368
msgid "Open in new window"
msgstr ""
#: src/components/workspace-calendar/note-card.tsx:123
#: src/components/workspace-calendar/event-card.tsx:153
-msgid "Open Note"
-msgstr ""
+#~ msgid "Open Note"
+#~ msgstr ""
#: src/components/settings/views/integrations.tsx:255
msgid "Optional base folder path within your Obsidian vault."
@@ -1206,7 +1205,7 @@ msgstr ""
msgid "This is the name of the company you work for."
msgstr ""
-#: src/components/toolbar/bars/calendar-toolbar.tsx:67
+#: src/components/finder/views/calendar-view.tsx:64
msgid "Today"
msgstr ""
@@ -1250,7 +1249,7 @@ msgstr ""
msgid "Untitled Template"
msgstr ""
-#: src/components/left-sidebar/events-list.tsx:62
+#: src/components/left-sidebar/events-list.tsx:61
msgid "Upcoming"
msgstr ""
@@ -1282,11 +1281,11 @@ msgstr ""
msgid "Vault Name"
msgstr ""
-#: src/components/left-sidebar/notes-list.tsx:323
+#: src/components/left-sidebar/notes-list.tsx:321
msgid "View calendar"
msgstr ""
-#: src/components/left-sidebar/events-list.tsx:193
+#: src/components/left-sidebar/events-list.tsx:190
#: src/components/editor-area/note-header/chips/event-chip.tsx:246
msgid "View in calendar"
msgstr ""
diff --git a/apps/desktop/src/routeTree.gen.ts b/apps/desktop/src/routeTree.gen.ts
index ee1e7a603e..2389b77444 100644
--- a/apps/desktop/src/routeTree.gen.ts
+++ b/apps/desktop/src/routeTree.gen.ts
@@ -15,8 +15,8 @@ import { Route as AppIndexRouteImport } from './routes/app.index'
import { Route as AppSettingsRouteImport } from './routes/app.settings'
import { Route as AppPlansRouteImport } from './routes/app.plans'
import { Route as AppNewRouteImport } from './routes/app.new'
+import { Route as AppFinderRouteImport } from './routes/app.finder'
import { Route as AppControlRouteImport } from './routes/app.control'
-import { Route as AppCalendarRouteImport } from './routes/app.calendar'
import { Route as AppOrganizationIdRouteImport } from './routes/app.organization.$id'
import { Route as AppNoteIdRouteImport } from './routes/app.note.$id'
import { Route as AppHumanIdRouteImport } from './routes/app.human.$id'
@@ -52,16 +52,16 @@ const AppNewRoute = AppNewRouteImport.update({
path: '/new',
getParentRoute: () => AppRoute,
} as any)
+const AppFinderRoute = AppFinderRouteImport.update({
+ id: '/finder',
+ path: '/finder',
+ getParentRoute: () => AppRoute,
+} as any)
const AppControlRoute = AppControlRouteImport.update({
id: '/control',
path: '/control',
getParentRoute: () => AppRoute,
} as any)
-const AppCalendarRoute = AppCalendarRouteImport.update({
- id: '/calendar',
- path: '/calendar',
- getParentRoute: () => AppRoute,
-} as any)
const AppOrganizationIdRoute = AppOrganizationIdRouteImport.update({
id: '/organization/$id',
path: '/organization/$id',
@@ -86,8 +86,8 @@ const AppNoteEventIdRoute = AppNoteEventIdRouteImport.update({
export interface FileRoutesByFullPath {
'/app': typeof AppRouteWithChildren
'/video': typeof VideoRoute
- '/app/calendar': typeof AppCalendarRoute
'/app/control': typeof AppControlRoute
+ '/app/finder': typeof AppFinderRoute
'/app/new': typeof AppNewRoute
'/app/plans': typeof AppPlansRoute
'/app/settings': typeof AppSettingsRoute
@@ -99,8 +99,8 @@ export interface FileRoutesByFullPath {
}
export interface FileRoutesByTo {
'/video': typeof VideoRoute
- '/app/calendar': typeof AppCalendarRoute
'/app/control': typeof AppControlRoute
+ '/app/finder': typeof AppFinderRoute
'/app/new': typeof AppNewRoute
'/app/plans': typeof AppPlansRoute
'/app/settings': typeof AppSettingsRoute
@@ -114,8 +114,8 @@ export interface FileRoutesById {
__root__: typeof rootRouteImport
'/app': typeof AppRouteWithChildren
'/video': typeof VideoRoute
- '/app/calendar': typeof AppCalendarRoute
'/app/control': typeof AppControlRoute
+ '/app/finder': typeof AppFinderRoute
'/app/new': typeof AppNewRoute
'/app/plans': typeof AppPlansRoute
'/app/settings': typeof AppSettingsRoute
@@ -130,8 +130,8 @@ export interface FileRouteTypes {
fullPaths:
| '/app'
| '/video'
- | '/app/calendar'
| '/app/control'
+ | '/app/finder'
| '/app/new'
| '/app/plans'
| '/app/settings'
@@ -143,8 +143,8 @@ export interface FileRouteTypes {
fileRoutesByTo: FileRoutesByTo
to:
| '/video'
- | '/app/calendar'
| '/app/control'
+ | '/app/finder'
| '/app/new'
| '/app/plans'
| '/app/settings'
@@ -157,8 +157,8 @@ export interface FileRouteTypes {
| '__root__'
| '/app'
| '/video'
- | '/app/calendar'
| '/app/control'
+ | '/app/finder'
| '/app/new'
| '/app/plans'
| '/app/settings'
@@ -218,6 +218,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AppNewRouteImport
parentRoute: typeof AppRoute
}
+ '/app/finder': {
+ id: '/app/finder'
+ path: '/finder'
+ fullPath: '/app/finder'
+ preLoaderRoute: typeof AppFinderRouteImport
+ parentRoute: typeof AppRoute
+ }
'/app/control': {
id: '/app/control'
path: '/control'
@@ -225,13 +232,6 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AppControlRouteImport
parentRoute: typeof AppRoute
}
- '/app/calendar': {
- id: '/app/calendar'
- path: '/calendar'
- fullPath: '/app/calendar'
- preLoaderRoute: typeof AppCalendarRouteImport
- parentRoute: typeof AppRoute
- }
'/app/organization/$id': {
id: '/app/organization/$id'
path: '/organization/$id'
@@ -264,8 +264,8 @@ declare module '@tanstack/react-router' {
}
interface AppRouteChildren {
- AppCalendarRoute: typeof AppCalendarRoute
AppControlRoute: typeof AppControlRoute
+ AppFinderRoute: typeof AppFinderRoute
AppNewRoute: typeof AppNewRoute
AppPlansRoute: typeof AppPlansRoute
AppSettingsRoute: typeof AppSettingsRoute
@@ -277,8 +277,8 @@ interface AppRouteChildren {
}
const AppRouteChildren: AppRouteChildren = {
- AppCalendarRoute: AppCalendarRoute,
AppControlRoute: AppControlRoute,
+ AppFinderRoute: AppFinderRoute,
AppNewRoute: AppNewRoute,
AppPlansRoute: AppPlansRoute,
AppSettingsRoute: AppSettingsRoute,
diff --git a/apps/desktop/src/routes/app.calendar.tsx b/apps/desktop/src/routes/app.calendar.tsx
deleted file mode 100644
index 6c5897a999..0000000000
--- a/apps/desktop/src/routes/app.calendar.tsx
+++ /dev/null
@@ -1,69 +0,0 @@
-import { createFileRoute } from "@tanstack/react-router";
-import { zodValidator } from "@tanstack/zod-adapter";
-import { endOfMonth, startOfMonth } from "date-fns";
-import { z } from "zod";
-
-import WorkspaceCalendar from "@/components/workspace-calendar";
-import { commands as dbCommands } from "@hypr/plugin-db";
-
-const schema = z.object({
- date: z.string().optional(),
- sessionId: z.string().optional(),
-});
-
-export const Route = createFileRoute("/app/calendar")({
- component: Component,
- validateSearch: zodValidator(schema),
- loaderDeps: ({ search }) => ({ search }),
- loader: async ({ context: { queryClient, userId }, deps: { search } }) => {
- const eventPromise = search.sessionId
- ? queryClient.fetchQuery({
- queryKey: ["event-session", search.sessionId],
- queryFn: () => dbCommands.sessionGetEvent(search.sessionId!),
- })
- : Promise.resolve(null);
-
- const event = await eventPromise;
-
- const date = event?.start_date
- ? new Date(event.start_date)
- : search.date
- ? new Date(search.date)
- : new Date();
-
- const [start, end] = [startOfMonth(date), endOfMonth(date)].map((v) => v.toISOString());
-
- const sessionsPromise = queryClient.fetchQuery({
- queryKey: ["sessions", start, end],
- queryFn: () =>
- dbCommands.listSessions({
- type: "dateRange",
- user_id: userId,
- start,
- end,
- limit: 100,
- }),
- });
-
- const eventsPromise = queryClient.fetchQuery({
- queryKey: ["events", start, end],
- queryFn: () =>
- dbCommands.listEvents({
- type: "dateRange",
- user_id: userId,
- start,
- end,
- limit: 100,
- }),
- });
-
- const [sessions, events] = await Promise.all([sessionsPromise, eventsPromise]);
- return { sessions, events, date };
- },
-});
-
-function Component() {
- const { sessions, events, date } = Route.useLoaderData();
-
- return
;
-}
diff --git a/apps/desktop/src/routes/app.finder.tsx b/apps/desktop/src/routes/app.finder.tsx
new file mode 100644
index 0000000000..a209fac416
--- /dev/null
+++ b/apps/desktop/src/routes/app.finder.tsx
@@ -0,0 +1,234 @@
+import { createFileRoute } from "@tanstack/react-router";
+import { zodValidator } from "@tanstack/zod-adapter";
+import { endOfMonth, startOfMonth } from "date-fns";
+import { z } from "zod";
+
+import { ViewSelector } from "@/components/finder/view-selector";
+import { CalendarView, ContactView, FolderView, TableView } from "@/components/finder/views";
+import { commands as dbCommands } from "@hypr/plugin-db";
+import { cn } from "@hypr/ui/lib/utils";
+
+const schema = z.object({
+ view: z.enum(["folder", "calendar", "table", "contact"]).default("calendar"),
+ date: z.string().optional(),
+ sessionId: z.string().optional(),
+ personId: z.string().optional(),
+ orgId: z.string().optional(),
+});
+
+export const Route = createFileRoute("/app/finder")({
+ component: FinderView,
+ validateSearch: zodValidator(schema),
+ loaderDeps: ({ search }) => ({ search }),
+ loader: async ({ context: { queryClient, userId }, deps: { search } }) => {
+ const currentDate = search.date ? new Date(search.date) : new Date();
+
+ const baseData = {
+ view: search.view,
+ date: currentDate,
+ };
+
+ if (search.view === "calendar") {
+ const eventPromise = search.sessionId
+ ? queryClient.fetchQuery({
+ queryKey: ["event-session", search.sessionId],
+ queryFn: () => dbCommands.sessionGetEvent(search.sessionId!),
+ })
+ : Promise.resolve(null);
+
+ const event = await eventPromise;
+
+ const date = event?.start_date
+ ? new Date(event.start_date)
+ : search.date
+ ? new Date(search.date)
+ : new Date();
+
+ const [start, end] = [startOfMonth(date), endOfMonth(date)].map((v) => v.toISOString());
+
+ const sessionsPromise = queryClient.fetchQuery({
+ queryKey: ["sessions", start, end],
+ queryFn: () =>
+ dbCommands.listSessions({
+ type: "dateRange",
+ user_id: userId,
+ start,
+ end,
+ limit: 100,
+ }),
+ });
+
+ const eventsPromise = queryClient.fetchQuery({
+ queryKey: ["calendar-events", start, end],
+ queryFn: () =>
+ dbCommands.listEvents({
+ type: "dateRange",
+ user_id: userId,
+ start,
+ end,
+ limit: 100,
+ }),
+ });
+
+ const [sessions, rawEvents] = await Promise.all([
+ sessionsPromise,
+ eventsPromise,
+ ]);
+
+ // Deduplicate events by tracking_id to handle any sync issues
+ // Keep the most recent event (by database id) for each tracking_id
+ const eventsByTrackingId = new Map
();
+ rawEvents.forEach(event => {
+ const existing = eventsByTrackingId.get(event.tracking_id);
+ if (!existing || event.id > existing.id) {
+ eventsByTrackingId.set(event.tracking_id, event);
+ }
+ });
+ const events = Array.from(eventsByTrackingId.values());
+
+ return {
+ ...baseData,
+ date,
+ sessions,
+ events,
+ };
+ }
+
+ if (search.view === "table") {
+ const currentDate = search.date ? new Date(search.date) : new Date();
+ const [start, end] = [startOfMonth(currentDate), endOfMonth(currentDate)].map((v) => v.toISOString());
+
+ const sessionsPromise = queryClient.fetchQuery({
+ queryKey: ["sessions-table", start, end],
+ queryFn: () =>
+ dbCommands.listSessions({
+ type: "dateRange",
+ user_id: userId,
+ start,
+ end,
+ limit: 100,
+ }),
+ });
+
+ const eventsPromise = queryClient.fetchQuery({
+ queryKey: ["events-table", start, end],
+ queryFn: () =>
+ dbCommands.listEvents({
+ type: "dateRange",
+ user_id: userId,
+ start,
+ end,
+ limit: 100,
+ }),
+ });
+
+ const [sessions, rawEvents] = await Promise.all([
+ sessionsPromise,
+ eventsPromise,
+ ]);
+
+ // Deduplicate events by tracking_id to handle any sync issues
+ // Keep the most recent event (by database id) for each tracking_id
+ const eventsByTrackingId = new Map();
+ rawEvents.forEach(event => {
+ const existing = eventsByTrackingId.get(event.tracking_id);
+ if (!existing || event.id > existing.id) {
+ eventsByTrackingId.set(event.tracking_id, event);
+ }
+ });
+ const events = Array.from(eventsByTrackingId.values());
+
+ return {
+ ...baseData,
+ sessions,
+ events,
+ };
+ }
+
+ if (search.view === "folder") {
+ return baseData;
+ }
+
+ if (search.view === "contact") {
+ return baseData;
+ }
+
+ return baseData;
+ },
+});
+
+export type ViewType = "folder" | "calendar" | "table" | "contact";
+
+interface LoaderData {
+ view: ViewType;
+ date: Date;
+ sessions?: any[];
+ events?: any[];
+}
+
+function FinderView() {
+ const { view, date, sessions, events } = Route.useLoaderData() as LoaderData;
+ const navigate = Route.useNavigate();
+ const { userId } = Route.useRouteContext();
+ const searchParams = Route.useSearch();
+
+ const handleViewChange = (newView: ViewType) => {
+ navigate({
+ search: (prev) => ({
+ ...prev,
+ view: newView,
+ }),
+ replace: true,
+ });
+ };
+
+ const handleNavigate = (params: { date: string }) => {
+ navigate({
+ search: (prev) => ({
+ ...prev,
+ ...params,
+ }),
+ replace: true,
+ });
+ };
+
+ return (
+
+
+
+
+
+
+ {view === "folder" && (
+
+ )}
+ {view === "calendar" && sessions && events && (
+
+ )}
+ {view === "table" && sessions && events && (
+
+ )}
+ {view === "contact" && (
+
+ )}
+
+
+ );
+}
diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts
index 177f16dea6..bd29bb6c60 100644
--- a/packages/utils/src/index.ts
+++ b/packages/utils/src/index.ts
@@ -1,6 +1,5 @@
export * from "./ai";
export * from "./datetime";
export * from "./fetch";
-export * from "./navigation";
export * from "./organization";
export * from "./string";
diff --git a/packages/utils/src/navigation.ts b/packages/utils/src/navigation.ts
deleted file mode 100644
index cc871ffd74..0000000000
--- a/packages/utils/src/navigation.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import { commands as windowsCommands } from "@hypr/plugin-windows";
-import type { HyprWindow } from "@hypr/plugin-windows";
-
-/**
- * Safely navigate to a URL in a specific window type
- * This ensures the window is visible before attempting navigation
- * to prevent potential crashes in the URL scheme handler
- */
-export const safeNavigate = async (
- window: HyprWindow,
- url: string,
- maxAttempts = 50,
-): Promise => {
- // First ensure the window is shown
- await windowsCommands.windowShow(window);
-
- // Then check visibility before navigating
- let attempts = 0;
-
- const checkAndNavigate = async (): Promise => {
- try {
- const isVisible = await windowsCommands.windowIsVisible(window);
-
- if (isVisible) {
- await windowsCommands.windowEmitNavigate(window, url);
- return;
- } else if (attempts < maxAttempts) {
- attempts++;
- // If not visible yet, check again after a short delay
- setTimeout(checkAndNavigate, 100);
- } else {
- console.error("Max attempts reached waiting for window visibility");
- }
- } catch (err) {
- console.error("Error during safe navigation:", err);
- }
- };
-
- // Start checking after a short initial delay
- setTimeout(checkAndNavigate, 200);
-};
diff --git a/plugins/apple-calendar/src/sync.rs b/plugins/apple-calendar/src/sync.rs
index 9f7499e2be..79f79e909f 100644
--- a/plugins/apple-calendar/src/sync.rs
+++ b/plugins/apple-calendar/src/sync.rs
@@ -124,6 +124,9 @@ async fn _sync_events(
) -> Result {
let mut state = EventSyncState::default();
+ // Track system events that have been handled to prevent duplicates
+ let mut handled_system_event_ids = std::collections::HashSet::::new();
+
// Collect all system events for rescheduled event detection
let all_system_events: Vec<&hypr_calendar_interface::Event> =
system_events_per_selected_calendar
@@ -158,6 +161,9 @@ async fn _sync_events(
google_event_url: db_event.google_event_url.clone(),
};
state.to_update.push(updated_event);
+
+ // Mark this system event as handled
+ handled_system_event_ids.insert(matching_event.id.clone());
continue;
}
@@ -179,6 +185,9 @@ async fn _sync_events(
google_event_url: db_event.google_event_url.clone(),
};
state.to_update.push(updated_event);
+
+ // Mark this rescheduled system event as handled to prevent duplicate creation
+ handled_system_event_ids.insert(rescheduled_event.id.clone());
continue;
}
diff --git a/plugins/windows/js/bindings.gen.ts b/plugins/windows/js/bindings.gen.ts
index da93ff0acc..9373783a0f 100644
--- a/plugins/windows/js/bindings.gen.ts
+++ b/plugins/windows/js/bindings.gen.ts
@@ -70,7 +70,7 @@ windowDestroyed: "plugin:windows:window-destroyed"
/** user-defined types **/
-export type HyprWindow = { type: "main" } | { type: "note"; value: string } | { type: "human"; value: string } | { type: "organization"; value: string } | { type: "calendar" } | { type: "settings" } | { type: "video"; value: string } | { type: "plans" } | { type: "control" }
+export type HyprWindow = { type: "main" } | { type: "note"; value: string } | { type: "human"; value: string } | { type: "organization"; value: string } | { type: "finder" } | { type: "settings" } | { type: "video"; value: string } | { type: "plans" } | { type: "control" }
export type KnownPosition = "left-half" | "right-half" | "center"
export type MainWindowState = { left_sidebar_expanded: boolean | null; right_panel_expanded: boolean | null }
export type Navigate = { path: string }
diff --git a/plugins/windows/src/ext.rs b/plugins/windows/src/ext.rs
index 126c9969da..14532fae2a 100644
--- a/plugins/windows/src/ext.rs
+++ b/plugins/windows/src/ext.rs
@@ -18,8 +18,8 @@ pub enum HyprWindow {
Human(String),
#[serde(rename = "organization")]
Organization(String),
- #[serde(rename = "calendar")]
- Calendar,
+ #[serde(rename = "finder")]
+ Finder,
#[serde(rename = "settings")]
Settings,
#[serde(rename = "video")]
@@ -37,7 +37,7 @@ impl std::fmt::Display for HyprWindow {
Self::Note(id) => write!(f, "note-{}", id),
Self::Human(id) => write!(f, "human-{}", id),
Self::Organization(id) => write!(f, "organization-{}", id),
- Self::Calendar => write!(f, "calendar"),
+ Self::Finder => write!(f, "finder"),
Self::Settings => write!(f, "settings"),
Self::Video(id) => write!(f, "video-{}", id),
Self::Plans => write!(f, "plans"),
@@ -52,7 +52,7 @@ impl std::str::FromStr for HyprWindow {
fn from_str(s: &str) -> Result {
match s {
"main" => return Ok(Self::Main),
- "calendar" => return Ok(Self::Calendar),
+ "finder" => return Ok(Self::Finder),
"settings" => return Ok(Self::Settings),
_ => {}
}
@@ -143,7 +143,7 @@ impl HyprWindow {
Self::Note(_) => "Note".into(),
Self::Human(_) => "Human".into(),
Self::Organization(_) => "Organization".into(),
- Self::Calendar => "Calendar".into(),
+ Self::Finder => "Finder".into(),
Self::Settings => "Settings".into(),
Self::Video(_) => "Video".into(),
Self::Plans => "Plans".into(),
@@ -316,10 +316,10 @@ impl HyprWindow {
.min_inner_size(480.0, 360.0)
.center()
.build()?,
- Self::Calendar => self
- .window_builder(app, "/app/calendar")
- .inner_size(640.0, 532.0)
- .min_inner_size(640.0, 532.0)
+ Self::Finder => self
+ .window_builder(app, "/app/finder")
+ .inner_size(900.0, 650.0)
+ .min_inner_size(800.0, 600.0)
.build()?,
Self::Settings => self
.window_builder(app, "/app/settings")