Merge branch 'feat/inda-383-daily-stat' into 'main'
[ProtonMail-WebClient.git] / packages / shared / lib / desktop / desktopTypes.ts
blob6cc2ab36f41ec3d8d79daf13612b91a2c7006da1
1 import { z } from 'zod';
3 import type { HttpsProtonMeDesktopInboxHeartbeatTotalV1SchemaJson } from '@proton/metrics/types/desktop_inbox_heartbeat_total_v1.schema';
4 import type { Environment } from '@proton/shared/lib/interfaces';
6 import type { ColorScheme, ThemeSetting } from '../themes/themes';
7 import { type DailyStatsStored, zDailyStatsReport } from './DailyStats';
8 import { type DefaultProtocol, zDefaultProtocol } from './DefaultProtocol';
9 import type { AppVersion, DesktopVersion } from './DesktopVersion';
11 export type CHANGE_VIEW_TARGET = 'mail' | 'calendar' | 'account';
12 export type ElectronNotification = {
13     title: string;
14     body: string;
15     app: CHANGE_VIEW_TARGET;
16     elementID?: string;
17     labelID?: string;
20 export type ESUserChoice = boolean | null;
22 // This type must be updated in the Electron application as well
23 export type IPCInboxDesktopFeature =
24     | 'ThemeSelection'
25     | 'InAppPayments'
26     | 'EarlyAccess'
27     | 'MultiAccount'
28     | 'LatestVersionCheck'
29     | 'InstallSource'
30     | 'MailtoTelemetry'
31     | 'ESUserChoice'
32     | 'FullTheme'
33     | 'StoreVersion'
34     | 'HeartbeatMetrics'
35     | 'StatsTelemetry';
36 export type IPCInboxGetInfoMessage =
37     | { type: 'theme'; result: ThemeSetting }
38     | { type: 'latestVersion'; result: DesktopVersion | null }
39     | { type: 'installSource'; result: string | null }
40     | { type: 'defaultMailto'; result: DefaultProtocol }
41     | { type: 'colorScheme'; result: ColorScheme }
42     | { type: 'getAllAppVersions'; result: string }
43     | { type: 'dailyStats'; result: DailyStatsStored };
44 export type IPCInboxGetUserInfoMessage = { type: 'esUserChoice'; result: ESUserChoice };
45 export type IPCInboxClientUpdateMessage =
46     | { type: 'updateNotification'; payload: number }
47     | { type: 'userLogin'; payload?: undefined }
48     | { type: 'userLogout'; payload?: undefined }
49     | { type: 'clearAppData'; payload?: undefined }
50     | { type: 'oauthPopupOpened'; payload: 'oauthPopupStarted' | 'oauthPopupFinished' }
51     | { type: 'subscriptionModalOpened'; payload: 'subscriptionModalStarted' | 'subscriptionModalFinished' }
52     | { type: 'openExternal'; payload: string }
53     | { type: 'changeView'; payload: CHANGE_VIEW_TARGET }
54     | { type: 'trialEnd'; payload?: 'trialEnded' | 'resetTrialEnded' | undefined }
55     | { type: 'showNotification'; payload: ElectronNotification }
56     | { type: 'updateLocale'; payload: string }
57     | { type: 'setTheme'; payload: ThemeSetting }
58     | { type: 'earlyAccess'; payload: Environment | undefined }
59     | { type: 'checkDefaultMailtoAndSignal'; payload?: undefined }
60     | { type: 'checkDailyStatsAndSignal'; payload?: undefined }
61     | { type: 'defaultMailtoTelemetryReported'; payload: number }
62     | { type: 'dailyStatsReported'; payload: number }
63     | { type: 'setESUserChoice'; payload: { userID: string; userChoice: boolean } }
64     | { type: 'storeAppVersion'; payload: AppVersion }
65     | { type: 'triggerCrash'; payload?: undefined }
66     | { type: 'metricsListenerChanged'; payload: 'ready' | 'removed' };
67 export type IPCInboxClientUpdateMessageType = IPCInboxClientUpdateMessage['type'];
69 export const IPCInboxHostUpdateMessageSchema = z.discriminatedUnion('type', [
70     z.object({
71         type: z.literal('captureMessage'),
72         payload: z.object({
73             message: z.string(),
74             level: z.union([z.literal('error'), z.literal('warning')]),
75             tags: z.record(z.union([z.string(), z.number()])),
76             extra: z.record(z.union([z.string(), z.number()])),
77         }),
78     }),
79     z.object({
80         type: z.literal('defaultMailtoChecked'),
81         payload: zDefaultProtocol,
82     }),
83     z.object({
84         type: z.literal('dailyStatsChecked'),
85         payload: zDailyStatsReport,
86     }),
87     z.object({
88         type: z.literal('sentHeartbeatMetrics'),
89         payload: z.custom<HttpsProtonMeDesktopInboxHeartbeatTotalV1SchemaJson>(),
90     }),
91 ]);
93 export type IPCInboxHostUpdateMessage = z.infer<typeof IPCInboxHostUpdateMessageSchema>;
94 export type IPCInboxHostUpdateMessageType = IPCInboxHostUpdateMessage['type'];
95 export type IPCInboxHostUpdateMessagePayload = IPCInboxHostUpdateMessage['payload'];
96 export type IPCInboxHostUpdateListener = (payload: IPCInboxHostUpdateMessagePayload) => void;
97 export type IPCInboxHostUpdateListenerRemover = { removeListener: () => void };
99 // THIS NEEDS REFACTOR: inda-refactor-001
100 // The orininal idea for `on` function was that this type will be defined by
101 // generic T extends IPCInboxHostUpdateMessageType, but it makes it messy
102 // because generic doesn't pick one value but also union of all possible types
103 // and therefore payload and callback need to accpet all.
104 export type IPCInboxHostUpdateListenerAdder = (
105     eventType: IPCInboxHostUpdateMessageType,
106     callback: IPCInboxHostUpdateListener
107 ) => IPCInboxHostUpdateListenerRemover;
110  * Electron injects an object in the window object
111  * This object can then be used to communicate from the web app to the desktop app
112  * This type can be used in any file that needs to communicate with the desktop app.
114  * The object can be injected when used in specific clients to avoid adding it globally
115  */
116 export type IPCInboxMessageBroker = {
117     hasFeature?: (feature: IPCInboxDesktopFeature) => boolean;
118     getInfo?: <T extends IPCInboxGetInfoMessage['type']>(
119         type: T
120     ) => Extract<IPCInboxGetInfoMessage, { type: T }>['result'];
121     getUserInfo?: <T extends IPCInboxGetUserInfoMessage['type']>(
122         type: T,
123         userID: string
124     ) => Extract<IPCInboxGetUserInfoMessage, { type: T }>['result'];
125     on?: IPCInboxHostUpdateListenerAdder;
126     send?: <T extends IPCInboxClientUpdateMessageType>(
127         type: T,
128         payload: Extract<IPCInboxClientUpdateMessage, { type: T }>['payload']
129     ) => void;
132 export type PayloadOfHostUpdateType<T extends IPCInboxHostUpdateMessageType> = Extract<
133     IPCInboxHostUpdateMessage,
134     { type: T }
135 >['payload'];
137 export const END_OF_TRIAL_KEY = 'endOfTrial';
139 export interface InboxDesktopFreeTrialDates {
140     trialStartDate?: Date;
141     trialEndDate?: Date;
144 export interface InboxDesktopFreeTrialReminders {
145     first: boolean;
146     second: boolean;
147     third: boolean;