Skip to content

Commit

Permalink
update to version 1.0.2 (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
andirsun authored May 10, 2024
1 parent 9ffd99c commit 5201fab
Show file tree
Hide file tree
Showing 18 changed files with 439 additions and 200 deletions.
8 changes: 0 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
# Proton Desktop for Linux arm64 (unofficial)

Proton Desktop is an [Electron](https://electronjs.org)-based project that offers a native desktop experience for Proton Mail and Proton Calendar.

This repo is a mirror of official proton mail desktop app hosted in: https://github.com/ProtonMail/inbox-desktop

I am offering the Linux arm64 rpm version of the app so distros like Fedora Asahi and others are able to use the app until proton team release arm64 version for linux out of the box.

<p align="center">
<img src="assets/icons/icon.png" width="256" height="256">
</p>
27 changes: 22 additions & 5 deletions forge.config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// eslint-disable-next-line @typescript-eslint/no-var-requires
require("dotenv").config();

import { AutoUnpackNativesPlugin } from "@electron-forge/plugin-auto-unpack-natives";
Expand All @@ -9,6 +10,7 @@ import { getAppTransportSecuity, getExtraResource, getIco, getIcon, getName, isB
import { FuseV1Options, FuseVersion } from "@electron/fuses";
import { mainConfig } from "./webpack.main.config";
import { rendererConfig } from "./webpack.renderer.config";
import pkg from "./package.json";

let currentArch = "";
const config: ForgeConfig = {
Expand All @@ -27,6 +29,8 @@ const config: ForgeConfig = {
name: getName(),
executableName: getName(),
extraResource: getExtraResource(),
appVersion: pkg.version,
appCopyright: pkg.config.copyright,
// Required for macOS mailto protocol
protocols: [
{
Expand All @@ -36,7 +40,7 @@ const config: ForgeConfig = {
],
// Change category type of the application on macOS
appCategoryType: "public.app-category.productivity",
appBundleId: "ch.protonmail.desktop",
appBundleId: pkg.config.appBundleId,
osxSign: {},
osxNotarize: {
appleId: process.env.APPLE_ID!,
Expand Down Expand Up @@ -91,8 +95,21 @@ const config: ForgeConfig = {
options: {
bin: getName(),
icon: `${__dirname}/assets/linux/${getIcon()}.svg`,
homepage: "https://proton.me/",
categories: ["Utility"],
homepage: pkg.author.url,
categories: ["Network", "Email"],
mimeType: ["x-scheme-handler/mailto"],
},
},
},
{
name: "@electron-forge/maker-deb",
config: {
options: {
bin: getName(),
icon: `${__dirname}/assets/linux/${getIcon()}.svg`,
maintainer: pkg.author.name,
homepage: pkg.author.url,
categories: ["Network", "Email"],
mimeType: ["x-scheme-handler/mailto"],
},
},
Expand All @@ -109,8 +126,8 @@ const config: ForgeConfig = {
config: {
prerelase: isBetaRelease,
repository: {
owner: "ProtonMail",
name: "inbox-desktop",
owner: pkg.config.githubUser,
name: pkg.config.githubRepo,
},
},
},
Expand Down
21 changes: 15 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
{
"name": "proton-mail",
"productName": "Proton Mail",
"version": "1.0.1",
"version": "1.0.2",
"icon": "assets/icons/icon.png",
"description": "Proton official desktop application for Proton Mail and Proton Calendar",
"license": "GPL-3.0",
"author": {
"name": "Proton",
"url": "https://proton.me",
"email": "[email protected]"
},
"config": {
"appBundleId": "ch.protonmail.desktop",
"appUserModelId": "com.squirrel.proton_mail.ProtonMail",
"copyright": "Copyright (c) 2024, Proton AG <[email protected]>",
"githubUser": "ProtonMail",
"githubRepo": "inbox-desktop"
},
"main": ".webpack/main",
"scripts": {
"start": "electron-forge start",
Expand All @@ -19,11 +32,6 @@
"negativity": "electronegativity -i ./src",
"create-uninstaller": "appify ./src/macos/uninstall.sh './src/macos/Proton Mail Uninstaller.app' ./assets/icons/uninstaller.png"
},
"keywords": [],
"author": {
"name": "Proton"
},
"license": "MIT",
"devDependencies": {
"@doyensec/electronegativity": "^1.10.3",
"@electron-forge/cli": "^7.3.0",
Expand All @@ -37,6 +45,7 @@
"@electron-forge/plugin-webpack": "^7.3.0",
"@electron-forge/publisher-github": "^7.3.0",
"@electron/fuses": "^1.7.0",
"@types/node": "^20",
"@typescript-eslint/eslint-plugin": "^7.1.0",
"@typescript-eslint/parser": "^7.1.0",
"@vercel/webpack-asset-relocator-loader": "1.7.3",
Expand Down
3 changes: 3 additions & 0 deletions src/global.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
declare global {
// eslint-disable-next-line no-var
var oauthProcess: boolean;
// eslint-disable-next-line no-var
var subscriptionProcess: boolean;
}

export {};
26 changes: 14 additions & 12 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
updateView,
viewCreationAppStartup,
} from "./utils/view/viewManagement";
import pkg from "../package.json";

if (require("electron-squirrel-startup")) {
app.quit();
Expand All @@ -42,6 +43,10 @@ app.enableSandbox();
// Config initialization
saveAppID();

if (!app.isPackaged) {
app.commandLine.appendSwitch("ignore-certificate-errors");
}

// Log initialization
Logger.initialize({ preload: true });
Logger.info("App start is mac:", isMac, "is windows:", isWindows, "isLinux:", isLinux);
Expand All @@ -62,7 +67,7 @@ if (app.isDefaultProtocolClient("mailto")) {
Logger.info("App is not default mailto client");
}

app.setAppUserModelId("com.squirrel.proton_mail.ProtonMail");
app.setAppUserModelId(pkg.config.appUserModelId);

const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {
Expand All @@ -79,7 +84,7 @@ if (!gotTheLock) {
mainWindow.focus();
}

handleMailToUrls(commandLine.pop());
handleMailToUrls(commandLine?.pop() || "");
});

app.whenReady().then(() => {
Expand Down Expand Up @@ -176,14 +181,13 @@ app.on("web-contents-created", (_ev, contents) => {

// This is used to redirect users to the external browser for internal upgrade modals
if (isHostAccount(url) && isUpgradeURL(url)) {
shell.openExternal(url);
return preventDefault(ev);
return;
}

const sessionID = getSessionID(url);
const calendarView = getCalendarView();
const calendarSession = getSessionID(calendarView.webContents.getURL());
if (isHostMail(url) && sessionID && !calendarSession && !isNaN(sessionID as unknown as any)) {
const calendarSessionID = getSessionID(calendarView.webContents.getURL());
if (isHostMail(url) && sessionID && !calendarSessionID) {
Logger.info("Refresh calendar session", sessionID);
reloadCalendarWithSession(sessionID);
}
Expand All @@ -193,13 +197,8 @@ app.on("web-contents-created", (_ev, contents) => {

contents.on("will-navigate", (details) => {
Logger.info("will-navigate");
if (!isHostAllowed(details.url) && !global.oauthProcess) {
return preventDefault(details);
}

// This is used to redirect users to the external browser for upsell modals
if (isHostAccount(details.url) && isUpgradeURL(details.url)) {
shell.openExternal(details.url);
if (!isHostAllowed(details.url) && !global.oauthProcess && !global.subscriptionProcess) {
return preventDefault(details);
}

Expand Down Expand Up @@ -234,6 +233,9 @@ app.on("web-contents-created", (_ev, contents) => {
} else if (global.oauthProcess) {
Logger.info("Open OAuth link in app");
return { action: "allow" };
} else if (global.subscriptionProcess) {
Logger.info("Open Subscription link in modal");
return { action: "allow" };
} else {
Logger.info("Open link in browser");
shell.openExternal(url);
Expand Down
31 changes: 25 additions & 6 deletions src/ipc/ipcConstants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { ThemeSetting } from "../utils/themes";
import { TrialStatus } from "../store/trialStore";

export const DESKTOP_FEATURES = {
InAppPayments: true,
ThemeSelection: true,
} as const;

export type VIEW_TARGET = "mail" | "calendar" | "account";
export type ElectronNotification = {
title: string;
Expand All @@ -9,15 +15,28 @@ export type ElectronNotification = {
labelID?: string;
};

export type IPCMessage =
export type IPCHasFeatureMessage = {
feature: keyof typeof DESKTOP_FEATURES;
status: boolean;
};

export type IPCGetInfoMessage = { type: "theme"; result: ThemeSetting };

export type IPCClientUpdateMessage =
| { type: "updateNotification"; payload: number }
| { type: "userLogout"; payload: undefined }
| { type: "clearAppData"; payload: undefined }
| { type: "userLogout"; payload?: undefined }
| { type: "clearAppData"; payload?: undefined }
| { type: "oauthPopupOpened"; payload: "oauthPopupStarted" | "oauthPopupFinished" }
| { type: "subscriptionModalOpened"; payload: "subscriptionModalStarted" | "subscriptionModalFinished" }
| { type: "openExternal"; payload: string }
| { type: "trialEnd"; payload: TrialStatus }
| { type: "changeView"; payload: VIEW_TARGET }
| { type: "showNotification"; payload: ElectronNotification };
| { type: "showNotification"; payload: ElectronNotification }
| { type: "updateLocale"; payload: string }
| { type: "setTheme"; payload: ThemeSetting };

export type IPCMessageType = IPCMessage["type"];
export type IPCMessagePayload<T extends IPCMessageType> = Extract<IPCMessage, { type: T }>["payload"];
export type IPCClientUpdateMessageType = IPCClientUpdateMessage["type"];
export type IPCClientUpdateMessagePayload<T extends IPCClientUpdateMessageType> = Extract<
IPCClientUpdateMessage,
{ type: T }
>["payload"];
99 changes: 72 additions & 27 deletions src/ipc/main.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,83 @@
import { ipcMain, shell } from "electron";
import { IpcMainEvent, ipcMain, shell } from "electron";
import { saveTrialStatus } from "../store/trialStore";
import { clearStorage } from "../utils/helpers";
import { setTrialEnded, updateView } from "../utils/view/viewManagement";
import { refreshHiddenViews, setTrialEnded, updateView } from "../utils/view/viewManagement";
import { handleIPCBadge, resetBadge, showNotification } from "./notification";
import Logger from "electron-log";
import { DESKTOP_FEATURES, IPCClientUpdateMessage, IPCGetInfoMessage } from "./ipcConstants";
import { getTheme, setTheme } from "../utils/themes";

function isValidClientUpdateMessage(message: unknown): message is IPCClientUpdateMessage {
return Boolean(message && typeof message === "object" && "type" in message && "payload" in message);
}

export const handleIPCCalls = () => {
ipcMain.on("updateNotification", (_e, count: number) => {
handleIPCBadge(count);
});
ipcMain.on("userLogout", () => {
clearStorage(true, 500);
resetBadge();
});
ipcMain.on("clearAppData", () => {
clearStorage(true, 500);
resetBadge();
ipcMain.on("hasFeature", (event: IpcMainEvent, message: keyof typeof DESKTOP_FEATURES) => {
event.returnValue = !!DESKTOP_FEATURES[message];
});
ipcMain.on("oauthPopupOpened", (_e, payload) => {
global.oauthProcess = payload === "oauthPopupStarted";
});
ipcMain.on("openExternal", (_e, url) => {
shell.openExternal(url);
});
ipcMain.on("trialEnd", (_e, payload) => {
saveTrialStatus(payload);

if (payload === "trialEnded") {
setTrialEnded();
ipcMain.on("getInfo", (event: IpcMainEvent, message: IPCGetInfoMessage["type"]) => {
switch (message) {
case "theme":
event.returnValue = getTheme();
break;
default:
Logger.error(`Invalid getInfo message: ${message}`);
break;
}
});
ipcMain.on("changeView", (_e, target) => {
updateView(target);
});
ipcMain.on("showNotification", (_e, payload) => {
showNotification(payload);

ipcMain.on("clientUpdate", (_e, message: unknown) => {
if (!isValidClientUpdateMessage(message)) {
Logger.error(`Invalid clientUpdate message: ${message}`);
return;
}

const { type, payload } = message;

switch (type) {
case "updateNotification":
handleIPCBadge(payload);
break;
case "userLogout":
clearStorage(true, 500);
resetBadge();
break;
case "clearAppData":
clearStorage(true, 500);
resetBadge();
break;
case "oauthPopupOpened":
global.oauthProcess = payload === "oauthPopupStarted";
break;
case "subscriptionModalOpened":
global.subscriptionProcess = payload === "subscriptionModalStarted";
break;
case "openExternal":
shell.openExternal(payload);
break;
case "trialEnd":
saveTrialStatus(payload);

if (payload === "trialEnded") {
setTrialEnded();
}
break;
case "changeView":
updateView(payload);
break;
case "showNotification":
showNotification(payload);
break;
case "updateLocale":
refreshHiddenViews();
break;
case "setTheme":
setTheme(payload);
break;
default:
Logger.error(`unknown message type: ${type}`);
break;
}
});
};
Loading

0 comments on commit 5201fab

Please sign in to comment.