diff --git a/src/action/NotificationActions.tsx b/src/action/NotificationActions.tsx
index ab97c97..1f4385e 100644
--- a/src/action/NotificationActions.tsx
+++ b/src/action/NotificationActions.tsx
@@ -24,6 +24,7 @@ export function NotificationActions({ notification, detailsTarget, mutate }: Not
return getNotificationHtmlUrl(notification);
}, [notification]);
+ console.log("notification_html_url", notification_html_url, notification);
return (
diff --git a/src/index.tsx b/src/index.tsx
index e4df547..12e2392 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -1,5 +1,5 @@
+import { GoogleMailNotificationListItem } from "./integrations/google-mail/listitem/GoogleMailNotificationListItem";
import { Action, ActionPanel, Detail, List, getPreferenceValues, openExtensionPreferences } from "@raycast/api";
-import { GoogleMailNotificationListItem } from "./integrations/google-mail/GoogleMailNotificationListItem";
import { GithubNotificationListItem } from "./integrations/github/listitem/GithubNotificationListItem";
import { LinearNotificationListItem } from "./integrations/linear/listitem/LinearNotificationListItem";
import { TodoistNotificationListItem } from "./integrations/todoist/TodoistNotificationListItem";
diff --git a/src/integrations/google-mail/GoogleMailNotificationListItem.tsx b/src/integrations/google-mail/GoogleMailNotificationListItem.tsx
deleted file mode 100644
index d039c1b..0000000
--- a/src/integrations/google-mail/GoogleMailNotificationListItem.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import { NotificationActions } from "../../action/NotificationActions";
-import { NotificationListItemProps } from "../../notification";
-import { Detail, List, environment } from "@raycast/api";
-import { useMemo } from "react";
-
-export function GoogleMailNotificationListItem({ notification, mutate }: NotificationListItemProps) {
- const icon = useMemo(() => {
- if (environment.appearance === "dark") {
- return "google-mail-logo-light.svg";
- }
- return "google-mail-logo-dark.svg";
- }, [environment]);
-
- return (
- }
- mutate={mutate}
- />
- }
- />
- );
-}
diff --git a/src/integrations/google-mail/listitem/GoogleMailNotificationListItem.tsx b/src/integrations/google-mail/listitem/GoogleMailNotificationListItem.tsx
new file mode 100644
index 0000000..208fc7e
--- /dev/null
+++ b/src/integrations/google-mail/listitem/GoogleMailNotificationListItem.tsx
@@ -0,0 +1,24 @@
+import { GoogleMailThreadListItem } from "./GoogleMailThreadListItem";
+import { NotificationListItemProps } from "../../../notification";
+import { environment } from "@raycast/api";
+import { useMemo } from "react";
+
+export function GoogleMailNotificationListItem({ notification, mutate }: NotificationListItemProps) {
+ const icon = useMemo(() => {
+ if (environment.appearance === "dark") {
+ return "google-mail-logo-light.svg";
+ }
+ return "google-mail-logo-dark.svg";
+ }, [environment]);
+
+ if (notification.metadata.type !== "GoogleMail") return null;
+
+ return (
+
+ );
+}
diff --git a/src/integrations/google-mail/listitem/GoogleMailThreadListItem.tsx b/src/integrations/google-mail/listitem/GoogleMailThreadListItem.tsx
new file mode 100644
index 0000000..392526f
--- /dev/null
+++ b/src/integrations/google-mail/listitem/GoogleMailThreadListItem.tsx
@@ -0,0 +1,65 @@
+import { GoogleMailThreadPreview } from "../preview/GoogleMailThreadPreview";
+import { NotificationActions } from "../../../action/NotificationActions";
+//import { getLinearUserAccessory } from "../accessories";
+import { Notification } from "../../../notification";
+import { Icon, Color, List } from "@raycast/api";
+import { MutatePromise } from "@raycast/utils";
+import { GoogleMailThread } from "../types";
+import { Page } from "../../../types";
+
+interface GoogleMailThreadListItemProps {
+ icon: string;
+ notification: Notification;
+ googleMailThread: GoogleMailThread;
+ mutate: MutatePromise | undefined>;
+}
+
+export function GoogleMailThreadListItem({
+ icon,
+ notification,
+ googleMailThread,
+ mutate,
+}: GoogleMailThreadListItemProps) {
+ const isStarred = googleMailThread.messages.some((message) => message.labelIds?.includes("STARRED"));
+ const isImportant = googleMailThread.messages.some((message) => message.labelIds?.includes("IMPORTANT"));
+ const fromAddress = googleMailThread.messages[0].payload.headers.find((header) => header.name === "From")?.value;
+ const subtitle = fromAddress;
+
+ const accessories: List.Item.Accessory[] = [
+ {
+ date: new Date(notification.updated_at),
+ tooltip: `Updated at ${notification.updated_at}`,
+ },
+ ];
+
+ if (isStarred) {
+ accessories.unshift({
+ icon: { source: Icon.Star, tintColor: Color.Yellow },
+ tooltip: "Starred",
+ });
+ }
+
+ if (isImportant) {
+ accessories.unshift({
+ icon: { source: Icon.Exclamationmark, tintColor: Color.Red },
+ tooltip: "Important",
+ });
+ }
+
+ return (
+ }
+ mutate={mutate}
+ />
+ }
+ />
+ );
+}
diff --git a/src/integrations/google-mail/preview/GoogleMailThreadPreview.tsx b/src/integrations/google-mail/preview/GoogleMailThreadPreview.tsx
new file mode 100644
index 0000000..f0edec9
--- /dev/null
+++ b/src/integrations/google-mail/preview/GoogleMailThreadPreview.tsx
@@ -0,0 +1,26 @@
+import { Notification, getNotificationHtmlUrl } from "../../../notification";
+import { Detail, ActionPanel, Action } from "@raycast/api";
+import { GoogleMailThread } from "../types";
+import { useMemo } from "react";
+
+interface GoogleMailThreadPreviewProps {
+ notification: Notification;
+ googleMailThread: GoogleMailThread;
+}
+
+export function GoogleMailThreadPreview({ notification }: GoogleMailThreadPreviewProps) {
+ const notification_html_url = useMemo(() => {
+ return getNotificationHtmlUrl(notification);
+ }, [notification]);
+
+ return (
+
+
+
+ }
+ />
+ );
+}
diff --git a/src/integrations/google-mail/types.ts b/src/integrations/google-mail/types.ts
new file mode 100644
index 0000000..5b319b2
--- /dev/null
+++ b/src/integrations/google-mail/types.ts
@@ -0,0 +1,27 @@
+export interface GoogleMailThread {
+ id: string;
+ user_email_address: string;
+ history_id: string;
+ messages: Array;
+}
+
+export interface GoogleMailMessage {
+ id: string;
+ threadId: string;
+ labelIds?: Array;
+ snippet: string;
+ payload: GoogleMailMessagePayload;
+ sizeEstimate: number;
+ historyId: string;
+ internalDate: Date;
+}
+
+export interface GoogleMailMessagePayload {
+ mimeType: string;
+ headers: Array;
+}
+
+export interface GoogleMailMessageHeader {
+ name: string;
+ value: string;
+}
diff --git a/src/integrations/linear/listitem/LinearIssueNotificationListItem.tsx b/src/integrations/linear/listitem/LinearIssueNotificationListItem.tsx
index 5fbc3b9..c2302ea 100644
--- a/src/integrations/linear/listitem/LinearIssueNotificationListItem.tsx
+++ b/src/integrations/linear/listitem/LinearIssueNotificationListItem.tsx
@@ -1,11 +1,12 @@
+import { LinearWorkflowStateType, LinearIssueNotification, LinearWorkflowState } from "../types";
import { NotificationActions } from "../../../action/NotificationActions";
import { LinearIssuePreview } from "../preview/LinearIssuePreview";
import { getLinearUserAccessory } from "../accessories";
import { Notification } from "../../../notification";
-import { LinearIssueNotification } from "../types";
import { MutatePromise } from "@raycast/utils";
import { Page } from "../../../types";
import { List } from "@raycast/api";
+import { match } from "ts-pattern";
interface LinearIssueNotificationListItemProps {
icon: string;
@@ -53,36 +54,18 @@ export function LinearIssueNotificationListItem({
}
export function getLinearIssueStateAccessory(state: LinearWorkflowState): List.Item.Accessory {
- switch (state.type) {
- case "Triage":
- return {
- icon: { source: "linear-issue-triage.svg", tintColor: state.color },
- tooltip: state.name,
- };
- case "Backlog":
- return {
- icon: { source: "linear-issue-backlog.svg", tintColor: state.color },
- tooltip: state.name,
- };
- case "Unstarted":
- return {
- icon: { source: "linear-issue-unstarted.svg", tintColor: state.color },
- tooltip: state.name,
- };
- case "Started":
- return {
- icon: { source: "linear-issue-started.svg", tintColor: state.color },
- tooltip: state.name,
- };
- case "Completed":
- return {
- icon: { source: "linear-issue-completed.svg", tintColor: state.color },
- tooltip: state.name,
- };
- case "Canceled":
- return {
- icon: { source: "linear-issue-canceled.svg", tintColor: state.color },
- tooltip: state.name,
- };
- }
+ return {
+ icon: {
+ source: match(state)
+ .with({ type: LinearWorkflowStateType.Triage }, () => "linear-issue-triage.svg")
+ .with({ type: LinearWorkflowStateType.Backlog }, () => "linear-issue-backlog.svg")
+ .with({ type: LinearWorkflowStateType.Unstarted }, () => "linear-issue-unstarted.svg")
+ .with({ type: LinearWorkflowStateType.Started }, () => "linear-issue-started.svg")
+ .with({ type: LinearWorkflowStateType.Completed }, () => "linear-issue-completed.svg")
+ .with({ type: LinearWorkflowStateType.Canceled }, () => "linear-issue-canceled.svg")
+ .exhaustive(),
+ tintColor: state.color,
+ },
+ tooltip: state.name,
+ };
}
diff --git a/src/integrations/linear/listitem/LinearNotificationListItem.tsx b/src/integrations/linear/listitem/LinearNotificationListItem.tsx
index 6a1aebb..2a01f19 100644
--- a/src/integrations/linear/listitem/LinearNotificationListItem.tsx
+++ b/src/integrations/linear/listitem/LinearNotificationListItem.tsx
@@ -29,7 +29,7 @@ export function LinearNotificationListItem({ notification, mutate }: Notificatio
);
diff --git a/src/integrations/linear/listitem/LinearProjectNotificationListItem.tsx b/src/integrations/linear/listitem/LinearProjectNotificationListItem.tsx
index 304871b..a78d0c0 100644
--- a/src/integrations/linear/listitem/LinearProjectNotificationListItem.tsx
+++ b/src/integrations/linear/listitem/LinearProjectNotificationListItem.tsx
@@ -43,7 +43,7 @@ export function LinearProjectNotificationListItem({
+
}
mutate={mutate}
/>
diff --git a/src/integrations/linear/types.ts b/src/integrations/linear/types.ts
index 14f1591..ed242c5 100644
--- a/src/integrations/linear/types.ts
+++ b/src/integrations/linear/types.ts
@@ -1,3 +1,7 @@
+export type LinearNotification =
+ | { type: "IssueNotification"; content: LinearIssueNotification }
+ | { type: "ProjectNotification"; content: LinearProjectNotification };
+
export interface LinearIssueNotification {
id: string;
type: string;
diff --git a/src/notification.ts b/src/notification.ts
index 05e219a..5e7fc11 100644
--- a/src/notification.ts
+++ b/src/notification.ts
@@ -1,4 +1,6 @@
import { GithubDiscussion, GithubPullRequest } from "./integrations/github/types";
+import { GoogleMailThread } from "./integrations/google-mail/types";
+import { LinearNotification } from "./integrations/linear/types";
import { MutatePromise } from "@raycast/utils";
import { match, P } from "ts-pattern";
import { Page } from "./types";
@@ -18,11 +20,14 @@ export interface Notification {
details?: NotificationDetails;
}
-export type NotificationMetadata = {
- type: "Github" | "Linear" | "GoogleMail" | "Todoist";
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- content: any;
-};
+export type NotificationMetadata =
+ | {
+ type: "Github" | "Todoist";
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ content: any;
+ }
+ | { type: "Linear"; content: LinearNotification }
+ | { type: "GoogleMail"; content: GoogleMailThread };
export type NotificationDetails =
| { type: "GithubPullRequest"; content: GithubPullRequest }
@@ -43,8 +48,8 @@ export type NotificationListItemProps = {
export function getNotificationHtmlUrl(notification: Notification) {
return match(notification)
.with(
- { details: { type: P.union("GithubPullRequest", "GithubDiscussion") } },
- () => notification.details.content.url,
+ { details: { type: P.union("GithubPullRequest", "GithubDiscussion"), content: P.select() } },
+ (notificationDetails) => notificationDetails.url,
)
.with(
{ metadata: { type: "Linear", content: { type: "IssueNotification", content: P.select() } } },
@@ -54,6 +59,13 @@ export function getNotificationHtmlUrl(notification: Notification) {
{ metadata: { type: "Linear", content: { type: "ProjectNotification", content: P.select() } } },
(linearProjectNotification) => linearProjectNotification.project.url,
)
+ .with(
+ { metadata: { type: "GoogleMail", content: P.select() } },
+ (googleMailThread) =>
+ `https://mail.google.com/mail/u/${googleMailThread.user_email_address}/#inbox/${googleMailThread.id}`,
+ )
+ .with({ metadata: { type: "Todoist", content: P.select() } }, () => "")
+ .with({ metadata: { type: "Github" } }, () => "https://github.com")
.exhaustive();
}