mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-23 23:19:40 +01:00
desktop: improve integration with operating system
This commit is contained in:
committed by
Abdullah Atta
parent
4805e54ef3
commit
f7a0938c38
66
apps/web/desktop/autolaunch.ts
Normal file
66
apps/web/desktop/autolaunch.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
This file is part of the Notesnook project (https://notesnook.com/)
|
||||
|
||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import { app } from "electron";
|
||||
import { existsSync, mkdirSync, rmSync, writeFileSync } from "fs";
|
||||
import path from "path";
|
||||
|
||||
const LINUX_DESKTOP_ENTRY = (hidden: boolean) => `[Desktop Entry]
|
||||
Type=Application
|
||||
Version=${app.getVersion()}
|
||||
Name=${app.getName()}
|
||||
Comment=${app.getName()} startup script
|
||||
Exec=${process.execPath}${hidden ? " --hidden" : ""}
|
||||
StartupNotify=false
|
||||
Terminal=false`;
|
||||
|
||||
const LINUX_AUTOSTART_DIRECTORY_PATH = path.join(
|
||||
app.getPath("home"),
|
||||
".config",
|
||||
"autostart"
|
||||
);
|
||||
|
||||
export class AutoLaunch {
|
||||
static enable(hidden: boolean) {
|
||||
if (process.platform === "linux") {
|
||||
mkdirSync(LINUX_AUTOSTART_DIRECTORY_PATH, { recursive: true });
|
||||
writeFileSync(
|
||||
path.join(
|
||||
LINUX_AUTOSTART_DIRECTORY_PATH,
|
||||
`${app.getName().toLowerCase()}.desktop`
|
||||
),
|
||||
LINUX_DESKTOP_ENTRY(hidden)
|
||||
);
|
||||
} else {
|
||||
app.setLoginItemSettings({ openAtLogin: true, openAsHidden: hidden });
|
||||
}
|
||||
}
|
||||
|
||||
static disable() {
|
||||
if (process.platform === "linux") {
|
||||
const desktopFilePath = path.join(
|
||||
LINUX_AUTOSTART_DIRECTORY_PATH,
|
||||
`${app.getName().toLowerCase()}.desktop`
|
||||
);
|
||||
if (!existsSync(desktopFilePath)) return;
|
||||
rmSync(desktopFilePath);
|
||||
} else {
|
||||
app.setLoginItemSettings({ openAtLogin: false, openAsHidden: false });
|
||||
}
|
||||
}
|
||||
}
|
||||
35
apps/web/desktop/config/desktopIntegration.js
Normal file
35
apps/web/desktop/config/desktopIntegration.js
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
This file is part of the Notesnook project (https://notesnook.com/)
|
||||
|
||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { JSONStorage } from "../jsonstorage";
|
||||
|
||||
function getDesktopIntegration() {
|
||||
return JSONStorage.get("desktopSettings", {
|
||||
autoStart: false,
|
||||
startMinimized: false,
|
||||
minimizeToSystemTray: false,
|
||||
closeToSystemTray: false
|
||||
});
|
||||
}
|
||||
|
||||
function setDesktopIntegration(settings) {
|
||||
return JSONStorage.set("desktopSettings", settings);
|
||||
}
|
||||
|
||||
export { getDesktopIntegration, setDesktopIntegration };
|
||||
@@ -19,10 +19,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/* global MAC_APP_STORE, RELEASE */
|
||||
|
||||
import "isomorphic-fetch";
|
||||
import { app, BrowserWindow, nativeTheme, shell } from "electron";
|
||||
import { join } from "path";
|
||||
import { platform } from "os";
|
||||
import { isDevelopment } from "./utils";
|
||||
import { app, BrowserWindow, Menu, nativeTheme, shell, Tray } from "electron";
|
||||
import { APP_ICON_PATH, isDevelopment } from "./utils";
|
||||
import { registerProtocol, PROTOCOL_URL } from "./protocol";
|
||||
import { configureAutoUpdater } from "./autoupdate";
|
||||
import { getBackgroundColor, getTheme, setTheme } from "./config/theme";
|
||||
@@ -36,6 +34,10 @@ import "./ipc/index.js";
|
||||
import getPrivacyMode from "./ipc/calls/getPrivacyMode";
|
||||
import setPrivacyMode from "./ipc/actions/setPrivacyMode";
|
||||
import { getIsSpellCheckerEnabled } from "./config/spellChecker";
|
||||
import yargs from "yargs";
|
||||
import { hideBin } from "yargs/helpers";
|
||||
import { getDesktopIntegration } from "./config/desktopIntegration";
|
||||
import { AutoLaunch } from "./autolaunch";
|
||||
|
||||
if (!RELEASE) {
|
||||
require("electron-reloader")(module);
|
||||
@@ -51,20 +53,21 @@ if (process.platform === "win32") {
|
||||
app.setAppUserModelId(app.name);
|
||||
}
|
||||
|
||||
var mainWindowState;
|
||||
async function createWindow() {
|
||||
const mainWindowState = new WindowState({});
|
||||
mainWindowState = new WindowState({});
|
||||
setTheme(getTheme());
|
||||
|
||||
const mainWindow = new BrowserWindow({
|
||||
x: mainWindowState.x,
|
||||
y: mainWindowState.y,
|
||||
width: mainWindowState.width,
|
||||
height: mainWindowState.height,
|
||||
fullscreen: mainWindowState.isFullScreen,
|
||||
|
||||
backgroundColor: getBackgroundColor(),
|
||||
autoHideMenuBar: true,
|
||||
icon: join(
|
||||
__dirname,
|
||||
platform() === "win32" ? "app.ico" : "favicon-72x72.png"
|
||||
),
|
||||
icon: APP_ICON_PATH,
|
||||
webPreferences: {
|
||||
zoomFactor: getZoomFactor(),
|
||||
devTools: true, // isDev,
|
||||
@@ -76,10 +79,14 @@ async function createWindow() {
|
||||
preload: __dirname + "/preload.js"
|
||||
}
|
||||
});
|
||||
|
||||
mainWindow.setAutoHideMenuBar(true);
|
||||
mainWindowState.manage(mainWindow);
|
||||
globalThis.window = mainWindow;
|
||||
setupMenu();
|
||||
setupJumplist();
|
||||
setupTray();
|
||||
setupDesktopIntegration();
|
||||
|
||||
if (isDevelopment())
|
||||
mainWindow.webContents.openDevTools({ mode: "right", activate: true });
|
||||
@@ -88,10 +95,9 @@ async function createWindow() {
|
||||
setPrivacyMode({ privacyMode: getPrivacyMode() });
|
||||
}
|
||||
|
||||
const cliOptions = await parseCli();
|
||||
try {
|
||||
await mainWindow.loadURL(
|
||||
isDevelopment() ? "http://localhost:3000" : PROTOCOL_URL
|
||||
);
|
||||
await mainWindow.loadURL(`${createURL(cliOptions)}`);
|
||||
} catch (e) {
|
||||
logger.error(e);
|
||||
}
|
||||
@@ -134,3 +140,179 @@ app.on("activate", () => {
|
||||
createWindow();
|
||||
}
|
||||
});
|
||||
|
||||
function createURL(options) {
|
||||
const url = new URL(isDevelopment() ? "http://localhost:3000" : PROTOCOL_URL);
|
||||
|
||||
if (options.note === true) url.hash = "/notes/create/1";
|
||||
else if (options.notebook === true) url.hash = "/notebooks/create";
|
||||
else if (options.reminder === true) url.hash = "/reminders/create";
|
||||
else if (typeof options.note === "string")
|
||||
url.hash = `/notes/${options.note}/edit`;
|
||||
else if (typeof options.notebook === "string")
|
||||
url.hash = `/notebooks/${options.notebook}`;
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
async function parseCli() {
|
||||
const result = {
|
||||
note: false,
|
||||
notebook: false,
|
||||
reminder: false
|
||||
};
|
||||
await yargs(hideBin(process.argv))
|
||||
.command("new", "Create a new item", (yargs) => {
|
||||
return yargs
|
||||
.command("note", "Create a new note", {}, () => (result.note = true))
|
||||
.command(
|
||||
"notebook",
|
||||
"Create a new notebook",
|
||||
{},
|
||||
() => (result.notebook = true)
|
||||
)
|
||||
.command(
|
||||
"reminder",
|
||||
"Add a new reminder",
|
||||
{},
|
||||
() => (result.reminder = true)
|
||||
);
|
||||
})
|
||||
.command("open", "Open a specific item", (yargs) => {
|
||||
return yargs
|
||||
.command(
|
||||
"note",
|
||||
"Open a note",
|
||||
{ id: { string: true, description: "Id of the note" } },
|
||||
(args) => (result.note = args.id)
|
||||
)
|
||||
.command(
|
||||
"notebook",
|
||||
"Open a notebook",
|
||||
{ id: { string: true, description: "Id of the notebook" } },
|
||||
(args) => (result.notebook = args.id)
|
||||
)
|
||||
.command(
|
||||
"topic",
|
||||
"Open a topic",
|
||||
{
|
||||
id: { string: true, description: "Id of the topic" },
|
||||
notebookId: { string: true, description: "Id of the notebook" }
|
||||
},
|
||||
(args) => (result.notebook = `${args.notebookId}/${args.id}`)
|
||||
);
|
||||
})
|
||||
.parse();
|
||||
return result;
|
||||
}
|
||||
|
||||
function setupJumplist() {
|
||||
if (process.platform === "win32") {
|
||||
app.setJumpList([
|
||||
{ type: "frequent" },
|
||||
{
|
||||
type: "tasks",
|
||||
items: [
|
||||
{
|
||||
program: process.execPath,
|
||||
iconPath: process.execPath,
|
||||
args: "new note",
|
||||
description: "Create a new note",
|
||||
title: "New note",
|
||||
type: "task"
|
||||
},
|
||||
{
|
||||
program: process.execPath,
|
||||
iconPath: process.execPath,
|
||||
args: "new notebook",
|
||||
description: "Create a new notebook",
|
||||
title: "New notebook",
|
||||
type: "task"
|
||||
},
|
||||
{
|
||||
program: process.execPath,
|
||||
iconPath: process.execPath,
|
||||
args: "new reminder",
|
||||
description: "Add a new reminder",
|
||||
title: "New reminder",
|
||||
type: "task"
|
||||
}
|
||||
]
|
||||
}
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
function setupTray() {
|
||||
const tray = new Tray(APP_ICON_PATH);
|
||||
|
||||
const contextMenu = Menu.buildFromTemplate([
|
||||
{
|
||||
label: "Show Notesnook",
|
||||
type: "normal",
|
||||
icon: APP_ICON_PATH,
|
||||
click: showApp
|
||||
},
|
||||
{ type: "separator" },
|
||||
{
|
||||
label: "New note",
|
||||
type: "normal",
|
||||
click: () => {
|
||||
showApp();
|
||||
sendMessageToRenderer(EVENTS.createItem, { itemType: "note" });
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "New notebook",
|
||||
type: "normal",
|
||||
click: () => {
|
||||
showApp();
|
||||
sendMessageToRenderer(EVENTS.createItem, { itemType: "notebook" });
|
||||
}
|
||||
},
|
||||
{ type: "separator" },
|
||||
{
|
||||
label: "Quit Notesnook",
|
||||
type: "normal",
|
||||
click: () => {
|
||||
app.exit(0);
|
||||
}
|
||||
}
|
||||
]);
|
||||
tray.on("double-click", showApp);
|
||||
tray.on("click", showApp);
|
||||
tray.setToolTip("Notesnook");
|
||||
tray.setContextMenu(contextMenu);
|
||||
}
|
||||
|
||||
function showApp() {
|
||||
if (globalThis.window.isMinimized()) {
|
||||
if (mainWindowState.isMaximized) {
|
||||
globalThis.window.maximize();
|
||||
} else globalThis.window.restore();
|
||||
}
|
||||
globalThis.window.show();
|
||||
globalThis.window.focus();
|
||||
globalThis.window.moveTop();
|
||||
globalThis.window.webContents.focus();
|
||||
}
|
||||
|
||||
function setupDesktopIntegration() {
|
||||
const desktopIntegration = getDesktopIntegration();
|
||||
|
||||
if (desktopIntegration.autoStart) {
|
||||
AutoLaunch.enable(desktopIntegration.startMinimized);
|
||||
}
|
||||
|
||||
globalThis.window.on("close", (e) => {
|
||||
if (getDesktopIntegration().closeToSystemTray) {
|
||||
e.preventDefault();
|
||||
globalThis.window.minimize();
|
||||
globalThis.window.hide();
|
||||
}
|
||||
});
|
||||
|
||||
globalThis.window.on("minimize", () => {
|
||||
if (getDesktopIntegration().minimizeToSystemTray) globalThis.window.hide();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -24,5 +24,6 @@ export const EVENTS = {
|
||||
updateDownloadCompleted: "updateDownloadCompleted",
|
||||
updateNotAvailable: "updateNotAvailable",
|
||||
themeChanged: "themeChanged",
|
||||
notificationClicked: "notificationClicked"
|
||||
notificationClicked: "notificationClicked",
|
||||
createItem: "createItem"
|
||||
};
|
||||
|
||||
@@ -29,6 +29,7 @@ import showNotification from "./showNotification";
|
||||
import bringToFront from "./bringToFront";
|
||||
import setSpellCheckerLanguages from "./setSpellCheckerLanguages";
|
||||
import toggleSpellChecker from "./toggleSpellChecker";
|
||||
import setDesktopIntegration from "./setDesktopIntegration";
|
||||
|
||||
const actions = {
|
||||
changeAppTheme,
|
||||
@@ -42,7 +43,8 @@ const actions = {
|
||||
showNotification,
|
||||
bringToFront,
|
||||
setSpellCheckerLanguages,
|
||||
toggleSpellChecker
|
||||
toggleSpellChecker,
|
||||
setDesktopIntegration,
|
||||
};
|
||||
|
||||
export function getAction(actionName) {
|
||||
|
||||
33
apps/web/desktop/ipc/actions/setDesktopIntegration.js
Normal file
33
apps/web/desktop/ipc/actions/setDesktopIntegration.js
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
This file is part of the Notesnook project (https://notesnook.com/)
|
||||
|
||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { AutoLaunch } from "../../autolaunch";
|
||||
import { setDesktopIntegration } from "../../config/desktopIntegration";
|
||||
|
||||
export default (args) => {
|
||||
if (!globalThis.window) return;
|
||||
|
||||
if (args.autoStart) {
|
||||
AutoLaunch.enable(args.startMinimized);
|
||||
} else {
|
||||
AutoLaunch.disable();
|
||||
}
|
||||
|
||||
setDesktopIntegration(args);
|
||||
};
|
||||
24
apps/web/desktop/ipc/calls/getDesktopIntegration.js
Normal file
24
apps/web/desktop/ipc/calls/getDesktopIntegration.js
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
This file is part of the Notesnook project (https://notesnook.com/)
|
||||
|
||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { getDesktopIntegration } from "../../config/desktopIntegration";
|
||||
|
||||
export default function () {
|
||||
return getDesktopIntegration();
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import getPrivacyMode from "./getPrivacyMode";
|
||||
import selectDirectory from "./selectDirectory";
|
||||
import { gunzip, gzip } from "./gzip";
|
||||
import getSpellChecker from "./getSpellChecker";
|
||||
import getDesktopIntegration from "./getDesktopIntegration";
|
||||
|
||||
const calls = {
|
||||
getZoomFactor,
|
||||
@@ -29,7 +30,8 @@ const calls = {
|
||||
selectDirectory,
|
||||
gunzip,
|
||||
gzip,
|
||||
getSpellChecker
|
||||
getSpellChecker,
|
||||
getDesktopIntegration,
|
||||
};
|
||||
|
||||
export const getCall = function getAction(callName) {
|
||||
|
||||
@@ -25,12 +25,12 @@ const directory = app.getPath("userData");
|
||||
const filename = "config.json";
|
||||
const filePath = join(directory, filename);
|
||||
class JSONStorage {
|
||||
static get(key, def) {
|
||||
static get<T>(key: string, def?: T): T {
|
||||
const json = this.readJson();
|
||||
return json[key] === undefined ? def : json[key];
|
||||
}
|
||||
|
||||
static set(key, value) {
|
||||
static set(key: string, value: unknown) {
|
||||
const json = this.readJson();
|
||||
json[key] = value;
|
||||
this.writeJson(json);
|
||||
@@ -40,10 +40,7 @@ class JSONStorage {
|
||||
this.writeJson({});
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
static readJson() {
|
||||
private static readJson() {
|
||||
try {
|
||||
const json = readFileSync(filePath, "utf-8");
|
||||
return JSON.parse(json);
|
||||
@@ -53,10 +50,7 @@ class JSONStorage {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
static writeJson(json) {
|
||||
private static writeJson(json: Record<string, unknown>) {
|
||||
try {
|
||||
writeFileSync(filePath, JSON.stringify(json));
|
||||
} catch (e) {
|
||||
73
apps/web/desktop/package-lock.json
generated
73
apps/web/desktop/package-lock.json
generated
@@ -10,7 +10,8 @@
|
||||
"dependencies": {
|
||||
"diary": "^0.3.1",
|
||||
"electron-updater": "^5.3.0",
|
||||
"isomorphic-fetch": "^3.0.0"
|
||||
"isomorphic-fetch": "^3.0.0",
|
||||
"yargs": "^17.6.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node-fetch": "^2.6.2",
|
||||
@@ -514,7 +515,6 @@
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
@@ -523,7 +523,6 @@
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1"
|
||||
},
|
||||
@@ -1073,7 +1072,6 @@
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
|
||||
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"string-width": "^4.2.0",
|
||||
"strip-ansi": "^6.0.1",
|
||||
@@ -1096,7 +1094,6 @@
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
},
|
||||
@@ -1107,8 +1104,7 @@
|
||||
"node_modules/color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
},
|
||||
"node_modules/colors": {
|
||||
"version": "1.0.3",
|
||||
@@ -1801,8 +1797,7 @@
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||
"dev": true
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
|
||||
},
|
||||
"node_modules/encodeurl": {
|
||||
"version": "1.0.2",
|
||||
@@ -2209,7 +2204,6 @@
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
|
||||
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
@@ -2434,7 +2428,6 @@
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "6.* || 8.* || >= 10.*"
|
||||
}
|
||||
@@ -2846,7 +2839,6 @@
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
@@ -3591,7 +3583,6 @@
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@@ -3835,7 +3826,6 @@
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
@@ -3849,7 +3839,6 @@
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.1"
|
||||
},
|
||||
@@ -4140,7 +4129,6 @@
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.0.0",
|
||||
"string-width": "^4.1.0",
|
||||
@@ -4172,7 +4160,6 @@
|
||||
"version": "5.0.8",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
@@ -4183,10 +4170,9 @@
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
},
|
||||
"node_modules/yargs": {
|
||||
"version": "17.6.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.0.tgz",
|
||||
"integrity": "sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==",
|
||||
"dev": true,
|
||||
"version": "17.6.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz",
|
||||
"integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==",
|
||||
"dependencies": {
|
||||
"cliui": "^8.0.1",
|
||||
"escalade": "^3.1.1",
|
||||
@@ -4194,7 +4180,7 @@
|
||||
"require-directory": "^2.1.1",
|
||||
"string-width": "^4.2.3",
|
||||
"y18n": "^5.0.5",
|
||||
"yargs-parser": "^21.0.0"
|
||||
"yargs-parser": "^21.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
@@ -4204,7 +4190,6 @@
|
||||
"version": "21.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
|
||||
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
@@ -4624,14 +4609,12 @@
|
||||
"ansi-regex": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
@@ -5055,7 +5038,6 @@
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
|
||||
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"string-width": "^4.2.0",
|
||||
"strip-ansi": "^6.0.1",
|
||||
@@ -5075,7 +5057,6 @@
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
@@ -5083,8 +5064,7 @@
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
},
|
||||
"colors": {
|
||||
"version": "1.0.3",
|
||||
@@ -5642,8 +5622,7 @@
|
||||
"emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||
"dev": true
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
|
||||
},
|
||||
"encodeurl": {
|
||||
"version": "1.0.2",
|
||||
@@ -5856,8 +5835,7 @@
|
||||
"escalade": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
|
||||
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw=="
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "4.0.0",
|
||||
@@ -6024,8 +6002,7 @@
|
||||
"get-caller-file": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
|
||||
},
|
||||
"get-intrinsic": {
|
||||
"version": "1.1.2",
|
||||
@@ -6328,8 +6305,7 @@
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
|
||||
},
|
||||
"is-glob": {
|
||||
"version": "4.0.1",
|
||||
@@ -6887,8 +6863,7 @@
|
||||
"require-directory": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
|
||||
"dev": true
|
||||
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.20.0",
|
||||
@@ -7091,7 +7066,6 @@
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
@@ -7102,7 +7076,6 @@
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^5.0.1"
|
||||
}
|
||||
@@ -7342,7 +7315,6 @@
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.0.0",
|
||||
"string-width": "^4.1.0",
|
||||
@@ -7364,8 +7336,7 @@
|
||||
"y18n": {
|
||||
"version": "5.0.8",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="
|
||||
},
|
||||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
@@ -7373,10 +7344,9 @@
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
},
|
||||
"yargs": {
|
||||
"version": "17.6.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.0.tgz",
|
||||
"integrity": "sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==",
|
||||
"dev": true,
|
||||
"version": "17.6.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz",
|
||||
"integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==",
|
||||
"requires": {
|
||||
"cliui": "^8.0.1",
|
||||
"escalade": "^3.1.1",
|
||||
@@ -7384,14 +7354,13 @@
|
||||
"require-directory": "^2.1.1",
|
||||
"string-width": "^4.2.3",
|
||||
"y18n": "^5.0.5",
|
||||
"yargs-parser": "^21.0.0"
|
||||
"yargs-parser": "^21.1.1"
|
||||
}
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "21.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
|
||||
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="
|
||||
},
|
||||
"yauzl": {
|
||||
"version": "2.10.0",
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
"dependencies": {
|
||||
"diary": "^0.3.1",
|
||||
"electron-updater": "^5.3.0",
|
||||
"isomorphic-fetch": "^3.0.0"
|
||||
"isomorphic-fetch": "^3.0.0",
|
||||
"yargs": "^17.6.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node-fetch": "^2.6.2",
|
||||
|
||||
@@ -61,6 +61,11 @@ contextBridge.exposeInMainWorld("config", {
|
||||
return ipcRenderer.invoke("fromRenderer", {
|
||||
type: "getSpellChecker"
|
||||
});
|
||||
},
|
||||
desktopIntegration: () => {
|
||||
return ipcRenderer.invoke("fromRenderer", {
|
||||
type: "getDesktopIntegration"
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -21,6 +21,11 @@ import { app } from "electron";
|
||||
import { join } from "path";
|
||||
import { statSync } from "fs";
|
||||
|
||||
const APP_ICON_PATH = join(
|
||||
__dirname,
|
||||
process.platform === "win32" ? "app.ico" : "favicon-72x72.png"
|
||||
);
|
||||
|
||||
function isDevelopment() {
|
||||
if (typeof electron === "string") {
|
||||
throw new TypeError("Not running in an Electron environment!");
|
||||
@@ -47,4 +52,4 @@ function getPath(filePath) {
|
||||
}
|
||||
}
|
||||
|
||||
export { getPath, isDevelopment };
|
||||
export { getPath, isDevelopment, APP_ICON_PATH };
|
||||
|
||||
@@ -29,6 +29,7 @@ import { introduceFeatures, showUpgradeReminderDialogs } from "./common";
|
||||
import { AppEventManager, AppEvents } from "./common/app-events";
|
||||
import { db } from "./common/db";
|
||||
import { EV, EVENTS } from "@notesnook/core/common";
|
||||
import { EVENTS as DESKTOP_APP_EVENTS } from "@notesnook/desktop/events";
|
||||
import { registerKeyMap } from "./common/key-map";
|
||||
import { isUserPremium } from "./hooks/use-is-user-premium";
|
||||
import useAnnouncements from "./hooks/use-announcements";
|
||||
@@ -45,6 +46,7 @@ import { updateStatus, removeStatus, getStatus } from "./hooks/use-status";
|
||||
import { showToast } from "./utils/toast";
|
||||
import { interruptedOnboarding } from "./components/dialogs/onboarding-dialog";
|
||||
import { WebExtensionRelay } from "./utils/web-extension-relay";
|
||||
import { hashNavigate } from "./navigation";
|
||||
|
||||
const relay = new WebExtensionRelay();
|
||||
|
||||
@@ -197,6 +199,22 @@ export default function AppEffects({ setShow }) {
|
||||
setTheme(isSystemThemeDark ? "dark" : "light");
|
||||
}, [isSystemThemeDark, followSystemTheme, setTheme]);
|
||||
|
||||
useEffect(() => {
|
||||
AppEventManager.subscribe(DESKTOP_APP_EVENTS.createItem, ({ itemType }) => {
|
||||
switch (itemType) {
|
||||
case "note":
|
||||
hashNavigate("/notes/create", { addNonce: true, replace: true });
|
||||
break;
|
||||
case "notebook":
|
||||
hashNavigate("/notebooks/create", { replace: true });
|
||||
break;
|
||||
case "reminder":
|
||||
hashNavigate("/reminders/create", { replace: true });
|
||||
break;
|
||||
}
|
||||
});
|
||||
}, []);
|
||||
|
||||
return <React.Fragment />;
|
||||
}
|
||||
|
||||
|
||||
26
apps/web/src/commands/set-desktop-integration.ts
Normal file
26
apps/web/src/commands/set-desktop-integration.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
This file is part of the Notesnook project (https://notesnook.com/)
|
||||
|
||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { invokeCommand } from "./index";
|
||||
|
||||
export default function setDesktopIntegration(
|
||||
settings: DesktopIntegrationSettings
|
||||
) {
|
||||
invokeCommand("setDesktopIntegration", settings);
|
||||
}
|
||||
@@ -47,19 +47,19 @@ export const CREATE_BUTTON_MAP = {
|
||||
},
|
||||
notebooks: {
|
||||
title: "Create a notebook",
|
||||
onClick: () => hashNavigate("/notebooks/create")
|
||||
onClick: () => hashNavigate("/notebooks/create", { replace: true })
|
||||
},
|
||||
topics: {
|
||||
title: "Create a topic",
|
||||
onClick: () => hashNavigate(`/topics/create`)
|
||||
onClick: () => hashNavigate(`/topics/create`, { replace: true })
|
||||
},
|
||||
tags: {
|
||||
title: "Create a tag",
|
||||
onClick: () => hashNavigate(`/tags/create`)
|
||||
onClick: () => hashNavigate(`/tags/create`, { replace: true })
|
||||
},
|
||||
reminders: {
|
||||
title: "Add a reminder",
|
||||
onClick: () => hashNavigate(`/reminders/create`)
|
||||
onClick: () => hashNavigate(`/reminders/create`, { replace: true })
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
9
apps/web/src/global.d.ts
vendored
9
apps/web/src/global.d.ts
vendored
@@ -23,9 +23,18 @@ type SpellCheckerOptions = {
|
||||
enabledLanguages: Language[];
|
||||
enabled: boolean;
|
||||
};
|
||||
|
||||
type DesktopIntegrationSettings = {
|
||||
autoStart: boolean;
|
||||
startMinimized: boolean;
|
||||
minimizeToSystemTray: boolean;
|
||||
closeToSystemTray: boolean;
|
||||
};
|
||||
|
||||
declare interface Window {
|
||||
config: {
|
||||
static spellChecker(): Promise<SpellCheckerOptions>;
|
||||
static desktopIntegration(): Promise<DesktopIntegrationSettings>;
|
||||
};
|
||||
native: {
|
||||
static gzip({
|
||||
|
||||
50
apps/web/src/hooks/use-desktop-integration.ts
Normal file
50
apps/web/src/hooks/use-desktop-integration.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
This file is part of the Notesnook project (https://notesnook.com/)
|
||||
|
||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import setDesktopIntegration from "../commands/set-desktop-integration";
|
||||
|
||||
export default function useDesktopIntegration() {
|
||||
const [settings, changeSettings] = useState<DesktopIntegrationSettings>();
|
||||
|
||||
const setupDesktopIntegration = useCallback(async () => {
|
||||
const settings = await window.config.desktopIntegration();
|
||||
changeSettings(settings);
|
||||
return settings;
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!window.config) return;
|
||||
(async function () {
|
||||
await setupDesktopIntegration();
|
||||
})();
|
||||
}, [setupDesktopIntegration]);
|
||||
|
||||
const set = useCallback(
|
||||
async (_settings: Partial<DesktopIntegrationSettings>) => {
|
||||
if (!settings) return;
|
||||
|
||||
setDesktopIntegration({ ...settings, ..._settings });
|
||||
await setupDesktopIntegration();
|
||||
},
|
||||
[settings, setupDesktopIntegration]
|
||||
);
|
||||
|
||||
return [settings, set] as const;
|
||||
}
|
||||
@@ -77,6 +77,7 @@ import { scheduleBackups } from "../common/reminders";
|
||||
import usePrivacyMode from "../hooks/use-privacy-mode";
|
||||
import { useTelemetry } from "../hooks/use-telemetry";
|
||||
import useSpellChecker from "../hooks/use-spell-checker";
|
||||
import useDesktopIntegration from "../hooks/use-desktop-integration";
|
||||
|
||||
function subscriptionStatusToString(user) {
|
||||
const status = user?.subscription?.type;
|
||||
@@ -147,6 +148,7 @@ function Settings() {
|
||||
privacy: false,
|
||||
developer: false,
|
||||
notifications: false,
|
||||
desktop: false,
|
||||
other: true
|
||||
});
|
||||
const isVaultCreated = useAppStore((store) => store.isVaultCreated);
|
||||
@@ -196,6 +198,8 @@ function Settings() {
|
||||
const [privacyMode, setPrivacyMode] = usePrivacyMode();
|
||||
const [showReminderNotifications, setShowReminderNotifications] =
|
||||
usePersistentState("reminderNotifications", true);
|
||||
const [desktopIntegration, changeDesktopIntegration] =
|
||||
useDesktopIntegration();
|
||||
const [corsProxy, setCorsProxy] = usePersistentState(
|
||||
"corsProxy",
|
||||
"https://cors.notesnook.com"
|
||||
@@ -534,6 +538,61 @@ function Settings() {
|
||||
</>
|
||||
)}
|
||||
|
||||
{isDesktop() && (
|
||||
<>
|
||||
<Header
|
||||
title="Desktop integration"
|
||||
isOpen={groups.desktop}
|
||||
onClick={() => {
|
||||
setGroups((g) => ({ ...g, desktop: !g.desktop }));
|
||||
}}
|
||||
/>
|
||||
{groups.desktop && (
|
||||
<>
|
||||
<Toggle
|
||||
title="Auto start on system startup"
|
||||
onToggled={() => {
|
||||
changeDesktopIntegration({
|
||||
autoStart: !desktopIntegration.autoStart
|
||||
});
|
||||
}}
|
||||
isToggled={desktopIntegration.autoStart}
|
||||
/>
|
||||
{desktopIntegration.autoStart && (
|
||||
<Toggle
|
||||
title="Start minimized"
|
||||
onToggled={() => {
|
||||
changeDesktopIntegration({
|
||||
startMinimized: !desktopIntegration.startMinimized
|
||||
});
|
||||
}}
|
||||
isToggled={desktopIntegration.startMinimized}
|
||||
/>
|
||||
)}
|
||||
<Toggle
|
||||
title="Minimize to system tray"
|
||||
onToggled={() => {
|
||||
changeDesktopIntegration({
|
||||
minimizeToSystemTray:
|
||||
!desktopIntegration.minimizeToSystemTray
|
||||
});
|
||||
}}
|
||||
isToggled={desktopIntegration.minimizeToSystemTray}
|
||||
/>
|
||||
<Toggle
|
||||
title="Close to system tray"
|
||||
onToggled={() => {
|
||||
changeDesktopIntegration({
|
||||
closeToSystemTray: !desktopIntegration.closeToSystemTray
|
||||
});
|
||||
}}
|
||||
isToggled={desktopIntegration.closeToSystemTray}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
<Header
|
||||
title="Editor settings"
|
||||
isOpen={groups.editor}
|
||||
|
||||
Reference in New Issue
Block a user