Merge branch 'develop' into renovate/apple-actions-import-codesign-certs-5.x
@ -34,10 +34,11 @@ npm-debug.log
|
||||
|
||||
# exceptions
|
||||
!/bin/copy-dist.ts
|
||||
!/bin/electron-forge/sign-windows.cjs
|
||||
!/bin/cleanupNodeModules.ts
|
||||
|
||||
# temporary exception to make copy-dist inside Docker build not fail
|
||||
# TriliumNextTODO: make copy-dist *not* requiring to copy this file for builds other than electron-forge
|
||||
# TriliumNextTODO: make copy-dist *not* requiring to copy these file for builds other than electron-forge
|
||||
!forge.config.cjs
|
||||
!/bin/tpl
|
||||
!/bin/electron-forge/desktop.ejs
|
||||
!/bin/electron-forge/sign-windows.cjs
|
44
.dprint.json
Normal file
@ -0,0 +1,44 @@
|
||||
{
|
||||
"typescript": {
|
||||
"indentWidth": 4,
|
||||
"quoteStyle": "preferDouble",
|
||||
"semiColons": "prefer",
|
||||
"quoteProps": "asNeeded",
|
||||
"newLineKind": "lf",
|
||||
"lineWidth": 200,
|
||||
"trailingCommas": "never",
|
||||
"arrayPattern.spaceAround": true,
|
||||
"arrayExpression.spaceAround": true
|
||||
},
|
||||
"json": {
|
||||
},
|
||||
"markdown": {
|
||||
},
|
||||
"dockerfile": {
|
||||
},
|
||||
"malva": {
|
||||
},
|
||||
"markup": {
|
||||
},
|
||||
"yaml": {
|
||||
},
|
||||
"excludes": [
|
||||
"**/node_modules",
|
||||
"**/*-lock.json",
|
||||
"*.html",
|
||||
"*.md",
|
||||
"*.yml",
|
||||
"libraries/*",
|
||||
"docs/*",
|
||||
"src/public/app/doc_notes"
|
||||
],
|
||||
"plugins": [
|
||||
"https://plugins.dprint.dev/typescript-0.94.0.wasm",
|
||||
"https://plugins.dprint.dev/json-0.20.0.wasm",
|
||||
"https://plugins.dprint.dev/markdown-0.18.0.wasm",
|
||||
"https://plugins.dprint.dev/dockerfile-0.3.2.wasm",
|
||||
"https://plugins.dprint.dev/g-plane/malva-v0.11.1.wasm",
|
||||
"https://plugins.dprint.dev/g-plane/markup_fmt-v0.19.0.wasm",
|
||||
"https://plugins.dprint.dev/g-plane/pretty_yaml-v0.5.0.wasm"
|
||||
]
|
||||
}
|
2
.github/actions/build-electron/action.yml
vendored
@ -81,7 +81,7 @@ runs:
|
||||
APPLE_ID: ${{ env.APPLE_ID }}
|
||||
APPLE_ID_PASSWORD: ${{ env.APPLE_ID_PASSWORD }}
|
||||
WINDOWS_SIGN_EXECUTABLE: ${{ env.WINDOWS_SIGN_EXECUTABLE }}
|
||||
TRILIUM_ARTIFACT_NAME_HINT: TriliumNextNotes ${{ inputs.os }} ${{ inputs.arch }}
|
||||
TRILIUM_ARTIFACT_NAME_HINT: TriliumNextNotes-${{ github.ref_name }}-${{ inputs.os }}-${{ inputs.arch }}
|
||||
run: |
|
||||
npm run electron-forge:make -- \
|
||||
--arch=${{ inputs.arch }} \
|
||||
|
@ -1,6 +0,0 @@
|
||||
*.html
|
||||
*.md
|
||||
*.yml
|
||||
libraries/*
|
||||
docs/*
|
||||
src/public/app/doc_notes/**/*
|
22
.prettierrc
@ -1,22 +0,0 @@
|
||||
{
|
||||
"printWidth": 200,
|
||||
"tabWidth": 4,
|
||||
"useTabs": false,
|
||||
"semi": true,
|
||||
"singleQuote": false,
|
||||
"quoteProps": "as-needed",
|
||||
"trailingComma": "none",
|
||||
"bracketSpacing": true,
|
||||
"arrowParens": "always",
|
||||
"proseWrap": "preserve",
|
||||
"htmlWhitespaceSensitivity": "css",
|
||||
"endOfLine": "lf",
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.json"],
|
||||
"options": {
|
||||
"tabWidth": 2
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -39,8 +39,11 @@ COPY --from=builder /usr/src/app ./
|
||||
|
||||
RUN sed -i "/electron/d" package.json && \
|
||||
npm ci --omit=dev && \
|
||||
node --experimental-strip-types ./bin/cleanupNodeModules.ts . --skip-prune-dev-deps && \
|
||||
npm cache clean --force && \
|
||||
rm -rf /tmp/node-compile-cache
|
||||
rm -rf \
|
||||
/tmp/node-compile-cache \
|
||||
/usr/src/app/bin/cleanupNodeModules.ts
|
||||
|
||||
# Configure container
|
||||
EXPOSE 8080
|
||||
|
@ -34,8 +34,11 @@ COPY --from=builder /usr/src/app ./
|
||||
|
||||
RUN sed -i "/electron/d" package.json && \
|
||||
npm ci --omit=dev && \
|
||||
node --experimental-strip-types ./bin/cleanupNodeModules.ts . --skip-prune-dev-deps && \
|
||||
npm cache clean --force && \
|
||||
rm -rf /tmp/node-compile-cache
|
||||
rm -rf \
|
||||
/tmp/node-compile-cache \
|
||||
/usr/src/app/bin/cleanupNodeModules.ts
|
||||
|
||||
# Add application user
|
||||
RUN adduser -s /bin/false node; exit 0
|
||||
|
10
README.md
@ -79,10 +79,11 @@ xattr -c "/path/to/Trilium Next.app"
|
||||
|
||||
### Mobile
|
||||
|
||||
To use TriliumNext on a mobile device:
|
||||
To use TriliumNext on a mobile device, you can use a mobile web browser to access the mobile interface of a server installation (see below).
|
||||
|
||||
* Use a mobile web browser to access the mobile interface of a server installation (see below)
|
||||
* Use of a mobile app is not yet supported ([see here](https://github.com/TriliumNext/Notes/issues/72)) to track mobile improvements.
|
||||
If you prefer a native Android app, you can use [TriliumDroid](https://apt.izzysoft.de/fdroid/index/apk/eu.fliegendewurst.triliumdroid). Report bugs and missing features at [their repository](https://github.com/FliegendeWurst/TriliumDroid).
|
||||
|
||||
See issue https://github.com/TriliumNext/Notes/issues/72 for more information on mobile app support.
|
||||
|
||||
### Server
|
||||
|
||||
@ -107,7 +108,8 @@ npm run server:start
|
||||
|
||||
### Documentation
|
||||
|
||||
Head on over to our [Docs repo](https://github.com/TriliumNext/Docs)
|
||||
We are currently transitioning to a new documentation mechanism.
|
||||
Meanwhile you can still view the [archived Docs repository](https://github.com/TriliumNext/Docs).
|
||||
|
||||
## 👏 Shoutouts
|
||||
|
||||
|
@ -25,8 +25,16 @@ NODE_VERSION=22.14.0
|
||||
|
||||
BUILD_DIR="./build"
|
||||
DIST_DIR="./dist"
|
||||
CLEANUP_SCRIPT="./bin/cleanupNodeModules.ts"
|
||||
|
||||
./bin/copy-trilium.sh
|
||||
|
||||
# Trigger the build
|
||||
echo "Build start"
|
||||
npm run build:prepare-dist
|
||||
echo "Build finished"
|
||||
|
||||
# pruning of unnecessary files and devDeps in node_modules
|
||||
node --experimental-strip-types $CLEANUP_SCRIPT $BUILD_DIR
|
||||
|
||||
NODE_FILENAME=node-v${NODE_VERSION}-linux-${ARCH}
|
||||
|
||||
@ -37,7 +45,9 @@ mv $NODE_FILENAME node
|
||||
cd ..
|
||||
|
||||
|
||||
rm -r $BUILD_DIR/node/lib/node_modules/npm \
|
||||
rm -r $BUILD_DIR/node/lib/node_modules/{npm,corepack} \
|
||||
$BUILD_DIR/node/bin/{npm,npx,corepack} \
|
||||
$BUILD_DIR/node/CHANGELOG.md \
|
||||
$BUILD_DIR/node/include/node \
|
||||
$BUILD_DIR/node_modules/electron* \
|
||||
$BUILD_DIR/electron*.{js,map}
|
||||
|
109
bin/cleanupNodeModules.ts
Normal file
@ -0,0 +1,109 @@
|
||||
import fs from "fs-extra";
|
||||
import path from "path";
|
||||
import type { Dirent } from "fs-extra";
|
||||
import { execSync } from "node:child_process";
|
||||
|
||||
/**
|
||||
* Example usage with node >= v22:
|
||||
* node --experimental-strip-types bin/cleanupNodeModules.ts /path/to/build/folder [--skip-prune-dev-deps]
|
||||
* Example usage with tsx:
|
||||
* tsx bin/cleanupNodeModules.ts /path/to/build/folder [--skip-prune-dev-deps]
|
||||
*/
|
||||
function main() {
|
||||
|
||||
if (process.argv.length > 4 || process.argv.length < 3) {
|
||||
console.error("Usage: cleanupNodeModules.ts [path-to-build-folder] [--skip-prune-dev-deps]");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const basePath = process.argv[2];
|
||||
const pruneDevDeps = process.argv[3] !== "--skip-prune-dev-deps";
|
||||
|
||||
if (!fs.existsSync(basePath)) {
|
||||
console.error(`Supplied path '${basePath}' does not exist. Aborting.`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`Starting pruning of node_modules ${!pruneDevDeps ? '(skipping npm pruning)' : ''} in '${basePath}'...`);
|
||||
cleanupNodeModules(basePath, pruneDevDeps);
|
||||
console.log("Successfully pruned node_modules.");
|
||||
}
|
||||
|
||||
function cleanupNodeModules(basePath: string, pruneDevDeps: boolean = true) {
|
||||
|
||||
// This needs to run for the server and Docker build,
|
||||
// but needs to be skipped for electron-forge: its
|
||||
// built-in pruning takes care of it already
|
||||
if (pruneDevDeps) {
|
||||
execSync(`npm ci --omit=dev --prefix ${basePath}`);
|
||||
}
|
||||
|
||||
const nodeModulesDirPath = path.join(basePath, "node_modules");
|
||||
const nodeModulesContent = fs.readdirSync(nodeModulesDirPath, { recursive: true, withFileTypes: true });
|
||||
//const libDir = fs.readdirSync(path.join(basePath, "./libraries"), { recursive: true, withFileTypes: true });
|
||||
|
||||
/**
|
||||
* Delete unnecessary folders
|
||||
*/
|
||||
const filterableDirs = new Set([
|
||||
"demo",
|
||||
"demos",
|
||||
"doc",
|
||||
"docs",
|
||||
"example",
|
||||
"examples",
|
||||
"test",
|
||||
"tests"
|
||||
]);
|
||||
|
||||
nodeModulesContent
|
||||
.filter(el => el.isDirectory() && filterableDirs.has(el.name))
|
||||
.forEach(dir => removeDirent(dir));
|
||||
|
||||
/**
|
||||
* Delete unnecessary files based on file extension
|
||||
* TODO filter out useless (README).md files
|
||||
*/
|
||||
const filterableFileExt = new Set([
|
||||
"ts",
|
||||
"map"
|
||||
]);
|
||||
|
||||
nodeModulesContent
|
||||
// TriliumNextTODO: check if we can improve this naive file ext matching, without introducing any additional dependency
|
||||
.filter(el => el.isFile() && filterableFileExt.has(el.name.split(".").at(-1) || ""))
|
||||
.forEach(dir => removeDirent(dir));
|
||||
|
||||
|
||||
/**
|
||||
* Delete specific unnecessary folders
|
||||
* TODO: check if we want removeSync to throw an error, if path does not exist anymore -> currently it will silently fail
|
||||
*/
|
||||
const extraFoldersDelete = new Set([
|
||||
path.join(nodeModulesDirPath, ".bin"),
|
||||
path.join(nodeModulesDirPath, "@excalidraw", "excalidraw", "dist", "dev"),
|
||||
path.join(nodeModulesDirPath, "boxicons", "svg"),
|
||||
path.join(nodeModulesDirPath, "boxicons", "node_modules"),
|
||||
path.join(nodeModulesDirPath, "boxicons", "src"),
|
||||
path.join(nodeModulesDirPath, "boxicons", "iconjar"),
|
||||
path.join(nodeModulesDirPath, "@jimp", "plugin-print", "fonts"),
|
||||
path.join(nodeModulesDirPath, "jimp", "dist", "browser") // missing "@" in front of jimp is not a typo here
|
||||
]);
|
||||
|
||||
nodeModulesContent
|
||||
.filter(el => el.isDirectory() && extraFoldersDelete.has(path.join(el.parentPath, el.name)))
|
||||
.forEach(dir => removeDirent(dir))
|
||||
}
|
||||
|
||||
|
||||
function removeDirent(el: Dirent) {
|
||||
const elementToDelete = path.join(el.parentPath, el.name);
|
||||
fs.removeSync(elementToDelete);
|
||||
|
||||
if (process.env.VERBOSE) {
|
||||
console.log(`Deleted ${elementToDelete}`);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
main()
|
@ -11,16 +11,10 @@ function log(...args: any[]) {
|
||||
}
|
||||
}
|
||||
|
||||
function copyNodeModuleFileOrFolder(source: string) {
|
||||
const destination = path.join(DEST_DIR, source);
|
||||
log(`Copying ${source} to ${destination}`);
|
||||
fs.ensureDirSync(path.dirname(destination));
|
||||
fs.copySync(source, destination);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
const assetsToCopy = new Set([
|
||||
// copy node_module, to avoid downloading packages a 2nd time during pruning
|
||||
"./node_modules",
|
||||
"./images",
|
||||
"./libraries",
|
||||
@ -33,6 +27,7 @@ try {
|
||||
"./README.md",
|
||||
"./forge.config.cjs",
|
||||
"./bin/tpl/",
|
||||
"./bin/cleanupNodeModules.ts",
|
||||
"./bin/electron-forge/desktop.ejs",
|
||||
"./bin/electron-forge/sign-windows.cjs",
|
||||
"./src/views/",
|
||||
@ -61,50 +56,10 @@ try {
|
||||
fs.copySync(dir, path.join(PUBLIC_DIR, path.basename(dir)));
|
||||
}
|
||||
|
||||
const nodeModulesFile = new Set([
|
||||
"node_modules/react/umd/react.production.min.js",
|
||||
"node_modules/react/umd/react.development.js",
|
||||
"node_modules/react-dom/umd/react-dom.production.min.js",
|
||||
"node_modules/react-dom/umd/react-dom.development.js",
|
||||
"node_modules/katex/dist/katex.min.js",
|
||||
"node_modules/katex/dist/contrib/mhchem.min.js",
|
||||
"node_modules/katex/dist/contrib/auto-render.min.js",
|
||||
"node_modules/@highlightjs/cdn-assets/highlight.min.js",
|
||||
]);
|
||||
|
||||
const nodeModulesFolder = new Set([
|
||||
"node_modules/@excalidraw/excalidraw/dist/prod/fonts/",
|
||||
"node_modules/katex/dist/",
|
||||
"node_modules/dayjs/",
|
||||
"node_modules/boxicons/css/",
|
||||
"node_modules/boxicons/fonts/",
|
||||
"node_modules/jquery/dist/",
|
||||
"node_modules/jquery-hotkeys/",
|
||||
"node_modules/split.js/dist/",
|
||||
"node_modules/i18next/",
|
||||
"node_modules/i18next-http-backend/",
|
||||
"node_modules/vanilla-js-wheel-zoom/dist/",
|
||||
"node_modules/mark.js/dist/",
|
||||
"node_modules/normalize.css/",
|
||||
"node_modules/jquery.fancytree/dist/",
|
||||
"node_modules/autocomplete.js/dist/",
|
||||
"node_modules/codemirror/lib/",
|
||||
"node_modules/codemirror/addon/",
|
||||
"node_modules/codemirror/mode/",
|
||||
"node_modules/codemirror/keymap/",
|
||||
"node_modules/@highlightjs/cdn-assets/languages",
|
||||
"node_modules/@highlightjs/cdn-assets/styles",
|
||||
"node_modules/leaflet/dist"
|
||||
]);
|
||||
|
||||
|
||||
|
||||
for (const nodeModuleItem of [...nodeModulesFile, ...nodeModulesFolder]) {
|
||||
copyNodeModuleFileOrFolder(nodeModuleItem);
|
||||
}
|
||||
console.log("Copying complete!")
|
||||
|
||||
} catch(err) {
|
||||
console.error("Error during copy:", err)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
|
@ -1,44 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e # Fail on any command error
|
||||
shopt -s globstar
|
||||
|
||||
BUILD_DIR="./build"
|
||||
|
||||
if ! [[ $(which npm) ]]; then
|
||||
echo "Missing npm"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Trigger the build
|
||||
echo Build start
|
||||
npm run build:prepare-dist
|
||||
echo Build finished
|
||||
|
||||
# Patch package.json main
|
||||
sed -i 's|./dist/electron-main.js|electron-main.js|g' "$BUILD_DIR/package.json"
|
||||
|
||||
# run in subshell (so we return to original dir)
|
||||
(cd $BUILD_DIR && npm ci --omit=dev)
|
||||
|
||||
if [[ -d "$BUILD_DIR"/node_modules ]]; then
|
||||
# cleanup of useless files in dependencies
|
||||
for d in 'image-q/demo' \
|
||||
'@excalidraw/excalidraw/dist/excalidraw-assets-dev' '@excalidraw/excalidraw/dist/excalidraw.development.js' '@excalidraw/excalidraw/dist/excalidraw-with-preact.development.js' \
|
||||
'mermaid/dist/mermaid.js' \
|
||||
'boxicons/svg' 'boxicons/node_modules/react'/* \
|
||||
'@jimp/plugin-print/fonts' 'jimp/browser' 'jimp/fonts'; do
|
||||
[[ -e "$BUILD_DIR"/node_modules/"$d" ]] && rm -r "$BUILD_DIR"/node_modules/"$d"
|
||||
done
|
||||
|
||||
# delete all tests (there are often large images as test file for jimp etc.)
|
||||
for d in 'test' 'docs' 'demo' 'example'; do
|
||||
find "$BUILD_DIR"/node_modules -name "$d" -exec rm -rf {} +
|
||||
done
|
||||
fi
|
||||
|
||||
find $BUILD_DIR/libraries -name "*.map" -type f -delete
|
||||
find $BUILD_DIR/node_modules -name "*.map" -type f -delete
|
||||
find $BUILD_DIR -name "*.ts" -type f -delete
|
||||
|
||||
unset f d BUILD_DIR
|
30
dump-db/package-lock.json
generated
@ -10,7 +10,7 @@
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"better-sqlite3": "^11.1.2",
|
||||
"mime-types": "^2.1.34",
|
||||
"mime-types": "^3.0.0",
|
||||
"sanitize-filename": "^1.6.3",
|
||||
"tsx": "^4.19.3",
|
||||
"yargs": "^17.3.1"
|
||||
@ -762,19 +762,19 @@
|
||||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"version": "1.54.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
|
||||
"integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
|
||||
"integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
"mime-db": "^1.54.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
@ -1594,16 +1594,16 @@
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
|
||||
"version": "1.54.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
|
||||
"integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
|
||||
"integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
|
||||
"requires": {
|
||||
"mime-db": "1.52.0"
|
||||
"mime-db": "^1.54.0"
|
||||
}
|
||||
},
|
||||
"mimic-response": {
|
||||
|
@ -18,7 +18,7 @@
|
||||
"homepage": "https://github.com/TriliumNext/Notes/blob/master/dump-db/README.md",
|
||||
"dependencies": {
|
||||
"better-sqlite3": "^11.1.2",
|
||||
"mime-types": "^2.1.34",
|
||||
"mime-types": "^3.0.0",
|
||||
"sanitize-filename": "^1.6.3",
|
||||
"tsx": "^4.19.3",
|
||||
"yargs": "^17.3.1"
|
||||
|
@ -1,5 +1,6 @@
|
||||
const path = require("path");
|
||||
const fs = require("fs-extra");
|
||||
const { execSync } = require("child_process");
|
||||
|
||||
const APP_NAME = "TriliumNext Notes";
|
||||
const BIN_PATH = path.normalize("./bin/electron-forge");
|
||||
@ -39,6 +40,22 @@ module.exports = {
|
||||
"translations/",
|
||||
"node_modules/@highlightjs/cdn-assets/styles"
|
||||
],
|
||||
afterPrune: [
|
||||
(buildPath, _electronVersion, _platform, _arch, callback) => {
|
||||
// buildPath is a temporary directory that electron-packager creates - it's in the form of
|
||||
// /tmp/electron-packager/tmp-SjJl0s/resources/app
|
||||
try {
|
||||
const cleanupNodeModulesScript = path.join(buildPath, "bin", "cleanupNodeModules.ts");
|
||||
// we don't have access to any devDeps like 'tsx' here, so use the built-in '--experimental-strip-types' flag instead
|
||||
const command = `node --experimental-strip-types ${cleanupNodeModulesScript} "${buildPath}" --skip-prune-dev-deps`;
|
||||
// execSync throws, if above returns any non-zero exit code
|
||||
execSync(command);
|
||||
callback()
|
||||
} catch(err) {
|
||||
callback(err)
|
||||
}
|
||||
}
|
||||
],
|
||||
afterComplete: [
|
||||
(buildPath, _electronVersion, platform, _arch, callback) => {
|
||||
// Only move resources on non-macOS platforms
|
||||
|
BIN
images/app-icons/tray/new-windowTemplate-inverted.png
Normal file
After Width: | Height: | Size: 348 B |
BIN
images/app-icons/tray/new-windowTemplate-inverted@1.25x.png
Normal file
After Width: | Height: | Size: 427 B |
BIN
images/app-icons/tray/new-windowTemplate-inverted@1.5x.png
Normal file
After Width: | Height: | Size: 514 B |
BIN
images/app-icons/tray/new-windowTemplate-inverted@2x.png
Normal file
After Width: | Height: | Size: 649 B |
BIN
images/app-icons/tray/new-windowTemplate.png
Normal file
After Width: | Height: | Size: 331 B |
BIN
images/app-icons/tray/new-windowTemplate@1.25x.png
Normal file
After Width: | Height: | Size: 409 B |
BIN
images/app-icons/tray/new-windowTemplate@1.5x.png
Normal file
After Width: | Height: | Size: 481 B |
BIN
images/app-icons/tray/new-windowTemplate@2x.png
Normal file
After Width: | Height: | Size: 626 B |
337
package-lock.json
generated
@ -68,8 +68,8 @@
|
||||
"leaflet-gpx": "2.1.2",
|
||||
"mark.js": "8.11.1",
|
||||
"marked": "15.0.7",
|
||||
"mermaid": "11.5.0",
|
||||
"mime-types": "2.1.35",
|
||||
"mermaid": "11.6.0",
|
||||
"mime-types": "3.0.1",
|
||||
"multer": "1.4.5-lts.2",
|
||||
"normalize-strings": "1.1.1",
|
||||
"normalize.css": "8.0.1",
|
||||
@ -164,7 +164,8 @@
|
||||
"bootstrap": "5.3.3",
|
||||
"cross-env": "7.0.3",
|
||||
"css-loader": "7.1.2",
|
||||
"electron": "35.0.3",
|
||||
"dprint": "0.49.1",
|
||||
"electron": "35.1.2",
|
||||
"eslint": "9.23.0",
|
||||
"esm": "3.2.25",
|
||||
"globals": "16.0.0",
|
||||
@ -175,10 +176,8 @@
|
||||
"lorem-ipsum": "2.0.8",
|
||||
"mind-elixir": "4.4.3",
|
||||
"mini-css-extract-plugin": "2.9.2",
|
||||
"node-abi": "4.2.0",
|
||||
"nodemon": "3.1.9",
|
||||
"postcss-loader": "8.1.1",
|
||||
"prettier": "3.5.3",
|
||||
"rcedit": "4.0.1",
|
||||
"rimraf": "6.0.1",
|
||||
"sass": "1.86.0",
|
||||
@ -568,6 +567,132 @@
|
||||
"node": ">=14.17.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dprint/darwin-arm64": {
|
||||
"version": "0.49.1",
|
||||
"resolved": "https://registry.npmjs.org/@dprint/darwin-arm64/-/darwin-arm64-0.49.1.tgz",
|
||||
"integrity": "sha512-ib6KcJWo/M5RJWXOQKhP664FG1hAvG7nrbkh+j8n+oXdzmbyDdXTP+zW+aM3/sIQUkGaZky1xy1j2VeScMEEHQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@dprint/darwin-x64": {
|
||||
"version": "0.49.1",
|
||||
"resolved": "https://registry.npmjs.org/@dprint/darwin-x64/-/darwin-x64-0.49.1.tgz",
|
||||
"integrity": "sha512-vIVgnYxV7YYa1d6Uyz707RbgB9rwefGPam+rzaueFNPQjdOxPOTQDuMEJDS+Z3BlI00MfeoupIfIUGsXoM4dpQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@dprint/linux-arm64-glibc": {
|
||||
"version": "0.49.1",
|
||||
"resolved": "https://registry.npmjs.org/@dprint/linux-arm64-glibc/-/linux-arm64-glibc-0.49.1.tgz",
|
||||
"integrity": "sha512-ZeIh6qMPWLBBifDtU0XadpK36b4WoaTqCOt0rWKfoTjq1RAt78EgqETWp43Dbr6et/HvTgYdoWF0ZNEu2FJFFA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@dprint/linux-arm64-musl": {
|
||||
"version": "0.49.1",
|
||||
"resolved": "https://registry.npmjs.org/@dprint/linux-arm64-musl/-/linux-arm64-musl-0.49.1.tgz",
|
||||
"integrity": "sha512-/nuRyx+TykN6MqhlSCRs/t3o1XXlikiwTc9emWdzMeLGllYvJrcht9gRJ1/q1SqwCFhzgnD9H7roxxfji1tc+Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@dprint/linux-riscv64-glibc": {
|
||||
"version": "0.49.1",
|
||||
"resolved": "https://registry.npmjs.org/@dprint/linux-riscv64-glibc/-/linux-riscv64-glibc-0.49.1.tgz",
|
||||
"integrity": "sha512-RHBqrnvGO+xW4Oh0QuToBqWtkXMcfjqa1TqbBFF03yopFzZA2oRKX83PhjTWgd/IglaOns0BgmaLJy/JBSxOfQ==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@dprint/linux-x64-glibc": {
|
||||
"version": "0.49.1",
|
||||
"resolved": "https://registry.npmjs.org/@dprint/linux-x64-glibc/-/linux-x64-glibc-0.49.1.tgz",
|
||||
"integrity": "sha512-MjFE894mIQXOKBencuakKyzAI4KcDe/p0Y9lRp9YSw/FneR4QWH9VBH90h8fRxcIlWMArjFFJJAtsBnn5qgxeg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@dprint/linux-x64-musl": {
|
||||
"version": "0.49.1",
|
||||
"resolved": "https://registry.npmjs.org/@dprint/linux-x64-musl/-/linux-x64-musl-0.49.1.tgz",
|
||||
"integrity": "sha512-CvGBWOksHgrL1uzYqtPFvZz0+E82BzgoCIEHJeuYaveEn37qWZS5jqoCm/vz6BfoivE1dVuyyOT78Begj9KxkQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@dprint/win32-arm64": {
|
||||
"version": "0.49.1",
|
||||
"resolved": "https://registry.npmjs.org/@dprint/win32-arm64/-/win32-arm64-0.49.1.tgz",
|
||||
"integrity": "sha512-gQa4s82lMcXjfdxjWBQun6IJlXdPZZaIj2/2cqXWVEOYPKxAZ/JvGzt2pPG+i73h9KHjNLIV8M9ckqEH3oHufg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@dprint/win32-x64": {
|
||||
"version": "0.49.1",
|
||||
"resolved": "https://registry.npmjs.org/@dprint/win32-x64/-/win32-x64-0.49.1.tgz",
|
||||
"integrity": "sha512-nPU6+hoVze5JJlgET7woYWElBw0IUaB/9XKTaglknQuUUfsmD75D9pkgJTxdIxl9Bg/i5O7c9wb3Nj4XNiTIfw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@electron-forge/cli": {
|
||||
"version": "7.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@electron-forge/cli/-/cli-7.8.0.tgz",
|
||||
@ -3977,12 +4102,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@mermaid-js/parser": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.3.0.tgz",
|
||||
"integrity": "sha512-HsvL6zgE5sUPGgkIDlmAWR1HTNHz2Iy11BAWPTa4Jjabkpguy4Ze2gzfLrg6pdRuBvFwgUYyxiaNqZwrEEXepA==",
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.4.0.tgz",
|
||||
"integrity": "sha512-wla8XOWvQAwuqy+gxiZqY+c7FokraOTHRWMsbB4AgRx9Sy7zKslNyejy7E+a77qHfey5GXw/ik3IXv/NHMJgaA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"langium": "3.0.0"
|
||||
"langium": "3.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@mind-elixir/node-menu": {
|
||||
@ -6846,6 +6971,27 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/accepts/node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/accepts/node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/accepts/node_modules/negotiator": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
|
||||
@ -10087,6 +10233,28 @@
|
||||
"url": "https://github.com/fb55/domutils?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/dprint": {
|
||||
"version": "0.49.1",
|
||||
"resolved": "https://registry.npmjs.org/dprint/-/dprint-0.49.1.tgz",
|
||||
"integrity": "sha512-pO9XH79SyXybj2Vhc9ITZMEI8cJkdlQQRoD8oEfPH6Jjpp/7WX5kIgECVd3DBOjjAdCSiW6R47v3gJBx/qZVkw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"dprint": "bin.js"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@dprint/darwin-arm64": "0.49.1",
|
||||
"@dprint/darwin-x64": "0.49.1",
|
||||
"@dprint/linux-arm64-glibc": "0.49.1",
|
||||
"@dprint/linux-arm64-musl": "0.49.1",
|
||||
"@dprint/linux-riscv64-glibc": "0.49.1",
|
||||
"@dprint/linux-x64-glibc": "0.49.1",
|
||||
"@dprint/linux-x64-musl": "0.49.1",
|
||||
"@dprint/win32-arm64": "0.49.1",
|
||||
"@dprint/win32-x64": "0.49.1"
|
||||
}
|
||||
},
|
||||
"node_modules/draggabilly": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/draggabilly/-/draggabilly-3.0.0.tgz",
|
||||
@ -10152,9 +10320,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/electron": {
|
||||
"version": "35.0.3",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-35.0.3.tgz",
|
||||
"integrity": "sha512-kjQAYEWXSr2TyK19IZoF85dzFIBaYuX7Yp/C+34b5Y/jmI2z270CGie+RjmEGMMitsy0G8YJKftukhYMuWlK6g==",
|
||||
"version": "35.1.2",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-35.1.2.tgz",
|
||||
"integrity": "sha512-ipYSDZEV3+PpHfJ8/oWlpMCvxwutX6xLvBz2HRPgEzSFzgLmGO7YXTjEow4DhDtCpGE+b95NTGoJaRAVQi5n7A==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@ -12299,6 +12467,27 @@
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/form-data/node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/form-data/node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/formidable": {
|
||||
"version": "3.5.2",
|
||||
"resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.2.tgz",
|
||||
@ -14419,9 +14608,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/langium": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/langium/-/langium-3.0.0.tgz",
|
||||
"integrity": "sha512-+Ez9EoiByeoTu/2BXmEaZ06iPNXM6thWJp02KfBO/raSMyCJ4jw7AkWWa+zBCTm0+Tw1Fj9FOxdqSskyN5nAwg==",
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/langium/-/langium-3.3.1.tgz",
|
||||
"integrity": "sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"chevrotain": "~11.0.3",
|
||||
@ -15105,14 +15294,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/mermaid": {
|
||||
"version": "11.5.0",
|
||||
"resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.5.0.tgz",
|
||||
"integrity": "sha512-IYhyukID3zzDj1EihKiN1lp+PXNImoJ3Iyz73qeDAgnus4BNGsJV1n471P4PyeGxPVONerZxignwGxGTSwZnlg==",
|
||||
"version": "11.6.0",
|
||||
"resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.6.0.tgz",
|
||||
"integrity": "sha512-PE8hGUy1LDlWIHWBP05SFdqUHGmRcCcK4IzpOKPE35eOw+G9zZgcnMpyunJVUEOgb//KBORPjysKndw8bFLuRg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@braintree/sanitize-url": "^7.0.4",
|
||||
"@iconify/utils": "^2.1.33",
|
||||
"@mermaid-js/parser": "^0.3.0",
|
||||
"@mermaid-js/parser": "^0.4.0",
|
||||
"@types/d3": "^7.4.3",
|
||||
"cytoscape": "^3.29.3",
|
||||
"cytoscape-cose-bilkent": "^4.1.0",
|
||||
@ -15632,21 +15821,21 @@
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
|
||||
"integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
"mime-db": "^1.54.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types/node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"version": "1.54.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
|
||||
"integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
@ -15977,19 +16166,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/node-abi": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-4.2.0.tgz",
|
||||
"integrity": "sha512-admQxilhDcmFJbUl4LQzGu+QyEijW9rctKRH2P7LNavAvln1bdK9OcujM3yi2KysKI41dxTrDtp6QfGEZeCbkg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"semver": "^7.6.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/node-addon-api": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
|
||||
@ -17400,22 +17576,6 @@
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz",
|
||||
"integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"prettier": "bin/prettier.cjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/proc-log": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/proc-log/-/proc-log-2.0.1.tgz",
|
||||
@ -20602,6 +20762,27 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/type-is/node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/type-is/node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/typedarray": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
||||
@ -21533,6 +21714,29 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/webpack-dev-middleware/node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/webpack-dev-middleware/node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/webpack-merge": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz",
|
||||
@ -21558,6 +21762,29 @@
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/webpack/node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/webpack/node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/webworkify": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/webworkify/-/webworkify-1.5.0.tgz",
|
||||
|
20
package.json
@ -38,10 +38,9 @@
|
||||
"electron:switch": "electron-rebuild",
|
||||
"docs:edit": "cross-env NODE_OPTIONS=\"--import tsx\" TRILIUM_DATA_DIR=./data-docs TRILIUM_ENV=dev TRILIUM_PORT=37741 electron ./electron-docs-main.ts .",
|
||||
"docs:edit-nix": "electron-rebuild --version 33.3.1 && cross-env NODE_OPTIONS=\"--import tsx\" TRILIUM_DATA_DIR=./data-docs TRILIUM_PORT=37741 TRILIUM_ENV=dev nix-shell -p electron_33 --run \"electron ./electron-docs-main.ts .\"",
|
||||
"electron-forge:prepare": "npm run build:prepare-dist",
|
||||
"electron-forge:start": "npm run electron-forge:prepare && cd ./build && electron-forge start",
|
||||
"electron-forge:make": "npm run electron-forge:prepare && cross-env DEBUG=electron-windows-installer:* electron-forge make ./build",
|
||||
"electron-forge:package": "npm run electron-forge:prepare && cd ./build && electron-forge package",
|
||||
"electron-forge:start": "npm run build:prepare-dist && cd ./build && electron-forge start",
|
||||
"electron-forge:make": "npm run build:prepare-dist && cross-env DEBUG=electron-windows-installer:* electron-forge make ./build",
|
||||
"electron-forge:package": "npm run build:prepare-dist && cd ./build && electron-forge package",
|
||||
"docs:build-backend": "rimraf ./docs/backend_api && typedoc ./docs/backend_api src/becca/entities/*.ts src/services/backend_script_api.ts src/services/sql.ts",
|
||||
"docs:build-frontend": "rimraf ./docs/frontend_api && jsdoc -c jsdoc-conf.json -d ./docs/frontend_api src/public/app/entities/*.js src/public/app/services/frontend_script_api.js src/public/app/widgets/basic_widget.js src/public/app/widgets/note_context_aware_widget.js src/public/app/widgets/right_panel_widget.js",
|
||||
"docs:build": "npm run docs:build-backend && npm run docs:build-frontend",
|
||||
@ -59,8 +58,8 @@
|
||||
"test:integration-mem-db": "cross-env TRILIUM_INTEGRATION_TEST=memory TRILIUM_PORT=8082 TRILIUM_DATA_DIR=./integration-tests/db nodemon src/main.ts",
|
||||
"test:integration-mem-db-dev": "cross-env TRILIUM_INTEGRATION_TEST=memory TRILIUM_PORT=8082 TRILIUM_ENV=dev TRILIUM_DATA_DIR=./integration-tests/db nodemon src/main.ts",
|
||||
"dev:watch-dist": "tsx ./bin/watch-dist.ts",
|
||||
"dev:prettier-check": "prettier . --check",
|
||||
"dev:prettier-fix": "prettier . --write",
|
||||
"dev:format-check": "dprint check",
|
||||
"dev:format-fix": "dprint fmt",
|
||||
"dev:linter-check": "eslint .",
|
||||
"dev:linter-fix": "eslint . --fix",
|
||||
"chore:update-build-info": "tsx bin/update-build-info.ts",
|
||||
@ -128,8 +127,8 @@
|
||||
"leaflet-gpx": "2.1.2",
|
||||
"mark.js": "8.11.1",
|
||||
"marked": "15.0.7",
|
||||
"mermaid": "11.5.0",
|
||||
"mime-types": "2.1.35",
|
||||
"mermaid": "11.6.0",
|
||||
"mime-types": "3.0.1",
|
||||
"multer": "1.4.5-lts.2",
|
||||
"normalize-strings": "1.1.1",
|
||||
"normalize.css": "8.0.1",
|
||||
@ -221,7 +220,8 @@
|
||||
"bootstrap": "5.3.3",
|
||||
"cross-env": "7.0.3",
|
||||
"css-loader": "7.1.2",
|
||||
"electron": "35.0.3",
|
||||
"dprint": "0.49.1",
|
||||
"electron": "35.1.2",
|
||||
"eslint": "9.23.0",
|
||||
"esm": "3.2.25",
|
||||
"globals": "16.0.0",
|
||||
@ -232,10 +232,8 @@
|
||||
"lorem-ipsum": "2.0.8",
|
||||
"mind-elixir": "4.4.3",
|
||||
"mini-css-extract-plugin": "2.9.2",
|
||||
"node-abi": "4.2.0",
|
||||
"nodemon": "3.1.9",
|
||||
"postcss-loader": "8.1.1",
|
||||
"prettier": "3.5.3",
|
||||
"rcedit": "4.0.1",
|
||||
"rimraf": "6.0.1",
|
||||
"sass": "1.86.0",
|
||||
|
@ -47,6 +47,11 @@ const TPL = `
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* Workaround for #1327 */
|
||||
body.desktop.electron .note-detail-editable-text {
|
||||
letter-spacing: -0.01px;
|
||||
}
|
||||
|
||||
body.mobile .note-detail-editable-text {
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
@ -307,6 +307,7 @@ button kbd {
|
||||
background-color: var(--menu-background-color) !important;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
--bs-dropdown-zindex: 999;
|
||||
}
|
||||
|
||||
body.desktop .dropdown-menu {
|
||||
|
@ -191,9 +191,9 @@
|
||||
--right-pane-item-hover-color: white;
|
||||
|
||||
--scrollbar-thumb-color: #fdfdfd5c;
|
||||
--scrollbar-thumb-color-hover: #ffffff7d;
|
||||
--scrollbar-thumb-hover-color: #ffffff7d;
|
||||
--scrollbar-background-color: transparent;
|
||||
--scrollbar-border-color: unset; /* Deprecated */
|
||||
--scrollbar-background-color: unset; /* Deprecated */
|
||||
|
||||
--link-color: lightskyblue;
|
||||
|
||||
|
@ -190,9 +190,9 @@
|
||||
--right-pane-item-hover-color: inherit;
|
||||
|
||||
--scrollbar-thumb-color: #0000005c;
|
||||
--scrollbar-thumb-color-hover: #00000066;
|
||||
--scrollbar-thumb-hover-color: #00000066;
|
||||
--scrollbar-background-color: transparent;
|
||||
--scrollbar-border-color: unset; /* Deprecated */
|
||||
--scrollbar-background-color: unset; /* Deprecated */
|
||||
|
||||
--link-color: blue;
|
||||
|
||||
|
@ -95,8 +95,8 @@
|
||||
font-size: 0.9rem !important;
|
||||
}
|
||||
|
||||
.dropdown-menu::-webkit-scrollbar-track {
|
||||
background: var(--menu-background-color);
|
||||
.dropdown-menu {
|
||||
--scrollbar-background-color: var(--menu-background-color);
|
||||
}
|
||||
|
||||
body.mobile .dropdown-menu {
|
||||
|
@ -668,12 +668,16 @@ input[type="range"] {
|
||||
:root {
|
||||
--scrollbar-thickness: 10px;
|
||||
--scrollbar-thumb-thickness: 3px;
|
||||
--scrollbar-thumb-hover-thickness: 8px;
|
||||
--scrollbar-thumb-hover-thickness: 6px;
|
||||
--scrollbar-start-end-gap: 8px;
|
||||
}
|
||||
|
||||
/* Scrollbar's body */
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background-color: var(--scrollbar-background-color);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar:vertical {
|
||||
width: var(--scrollbar-thickness) !important;
|
||||
}
|
||||
@ -707,10 +711,12 @@ input[type="range"] {
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
--s-thumb-thickness: var(--scrollbar-thumb-hover-thickness);
|
||||
--s-thumb-color: var(--scrollbar-thumb-color-hover);
|
||||
--s-thumb-color: var(--scrollbar-thumb-hover-color);
|
||||
}
|
||||
|
||||
/* Scrollbar's increment/decrement buttons (repurposed as a scrollbar start/end gap) */
|
||||
/* Scrollbar's increment/decrement buttons (repurposed as a scrollbar start/end gap).
|
||||
* This gap is useful also to avoid breaking the rounded corners of a container when a
|
||||
* custom scrollbar background color is used. */
|
||||
|
||||
::-webkit-scrollbar-button:vertical {
|
||||
height: var(--scrollbar-start-end-gap);
|
||||
@ -724,10 +730,19 @@ input[type="range"] {
|
||||
* Firefox scrollbars
|
||||
*
|
||||
* Unsupported features: --scrollbar-thumb-thickness, --scrollbar-thumb-hover-thickness,
|
||||
* --scrollbar-start-end-gap, --scrollbar-thumb-color-hover.
|
||||
* --scrollbar-start-end-gap, --scrollbar-thumb-hover-color.
|
||||
*/
|
||||
|
||||
:root {
|
||||
scrollbar-color: var(--scrollbar-thumb-color) transparent;
|
||||
scrollbar-width: var(--scrollbar-thickness);
|
||||
}
|
||||
|
||||
@supports selector(::-webkit-scrollbar) {
|
||||
/* Prevent the scrollbar-color and scrollbar-width properties to override the custom styles
|
||||
* defined using ::-webkit-scrollbar. */
|
||||
:root {
|
||||
scrollbar-color: unset;
|
||||
scrollbar-width: unset;
|
||||
}
|
||||
}
|
@ -42,14 +42,9 @@ html .note-detail-editable-text :not(figure, .include-note, hr):first-child {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.ck-content pre code::-webkit-scrollbar {
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
.ck-content pre code::-webkit-scrollbar-thumb {
|
||||
height: 4px;
|
||||
border: none !important;
|
||||
background: gray !important;
|
||||
.ck-content pre code {
|
||||
--scrollbar-thumb-color: gray;
|
||||
--scrollbar-thumb-hover-color: gray;
|
||||
}
|
||||
|
||||
.ck-content pre code::-webkit-scrollbar-track,
|
||||
|
@ -46,7 +46,7 @@ body.background-effects.platform-win32 {
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body.background-effects.platform-win32 #launcher-pane {
|
||||
body.background-effects.platform-win32 {
|
||||
--launcher-pane-horiz-border-color: rgba(0, 0, 0, 0.5);
|
||||
--launcher-pane-horiz-background-color: rgba(255, 255, 255, 0.09);
|
||||
}
|
||||
@ -897,6 +897,21 @@ body.layout-horizontal .tab-row-container {
|
||||
padding-top: calc((var(--tab-bar-height) - var(--tab-height)));
|
||||
}
|
||||
|
||||
/* Define extra drag areas for Electron windows */
|
||||
body.layout-horizontal .tab-row-container,
|
||||
body.layout-vertical .tab-row-widget,
|
||||
body.layout-vertical #left-pane .quick-search {
|
||||
-webkit-app-region: drag;
|
||||
}
|
||||
|
||||
/* Limit the drag area for the previous elements to include just to the element itself
|
||||
and not its descendants also */
|
||||
body.layout-horizontal .tab-row-container > *,
|
||||
body.layout-vertical .tab-row-widget > *,
|
||||
body.layout-vertical #left-pane .quick-search > * {
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
|
||||
body.layout-horizontal .tab-row-widget-container {
|
||||
margin-top: 0;
|
||||
position: relative;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Menu, Tray } from "electron";
|
||||
import { Menu, Tray, BrowserWindow } from "electron";
|
||||
import path from "path";
|
||||
import windowService from "./window.js";
|
||||
import optionService from "./options.js";
|
||||
@ -17,7 +17,7 @@ import cls from "./cls.js";
|
||||
let tray: Tray;
|
||||
// `mainWindow.isVisible` doesn't work with `mainWindow.show` and `mainWindow.hide` - it returns `false` when the window
|
||||
// is minimized
|
||||
let isVisible = true;
|
||||
let windowVisibilityMap: Record<number, boolean> = {};; // Dictionary for storing window ID and its visibility status
|
||||
|
||||
function getTrayIconPath() {
|
||||
let name: string;
|
||||
@ -37,53 +37,93 @@ function getIconPath(name: string) {
|
||||
return path.join(path.dirname(fileURLToPath(import.meta.url)), "../..", "images", "app-icons", "tray", `${name}Template${suffix}.png`);
|
||||
}
|
||||
|
||||
function registerVisibilityListener() {
|
||||
const mainWindow = windowService.getMainWindow();
|
||||
if (!mainWindow) {
|
||||
function registerVisibilityListener(window: BrowserWindow) {
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
|
||||
// They need to be registered before the tray updater is registered
|
||||
mainWindow.on("show", () => {
|
||||
isVisible = true;
|
||||
window.on("show", () => {
|
||||
windowVisibilityMap[window.id] = true;
|
||||
updateTrayMenu();
|
||||
});
|
||||
mainWindow.on("hide", () => {
|
||||
isVisible = false;
|
||||
window.on("hide", () => {
|
||||
windowVisibilityMap[window.id] = false;
|
||||
updateTrayMenu();
|
||||
});
|
||||
|
||||
mainWindow.on("minimize", updateTrayMenu);
|
||||
mainWindow.on("maximize", updateTrayMenu);
|
||||
if (!isMac) {
|
||||
// macOS uses template icons which work great on dark & light themes.
|
||||
nativeTheme.on("updated", updateTrayMenu);
|
||||
}
|
||||
ipcMain.on("reload-tray", updateTrayMenu);
|
||||
i18next.on("languageChanged", updateTrayMenu);
|
||||
window.on("minimize", updateTrayMenu);
|
||||
window.on("maximize", updateTrayMenu);
|
||||
}
|
||||
|
||||
function updateTrayMenu() {
|
||||
const mainWindow = windowService.getMainWindow();
|
||||
if (!mainWindow) {
|
||||
function getWindowTitle(window: BrowserWindow | null) {
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
const title = window.getTitle();
|
||||
const titleWithoutAppName = title.replace(/\s-\s[^-]+$/, ''); // Remove the name of the app
|
||||
|
||||
function ensureVisible() {
|
||||
if (mainWindow) {
|
||||
mainWindow.show();
|
||||
mainWindow.focus();
|
||||
// Limit title maximum length to 17
|
||||
if (titleWithoutAppName.length > 20) {
|
||||
return titleWithoutAppName.substring(0, 17) + '...';
|
||||
}
|
||||
|
||||
return titleWithoutAppName;
|
||||
}
|
||||
|
||||
function updateWindowVisibilityMap(allWindows: BrowserWindow[]) {
|
||||
const currentWindowIds: number[] = allWindows.map(window => window.id);
|
||||
|
||||
// Deleting closed windows from windowVisibilityMap
|
||||
for (const [id, visibility] of Object.entries(windowVisibilityMap)) {
|
||||
const windowId = Number(id);
|
||||
if (!currentWindowIds.includes(windowId)) {
|
||||
delete windowVisibilityMap[windowId];
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate through allWindows to make sure the ID of each window exists in windowVisibilityMap
|
||||
allWindows.forEach(window => {
|
||||
const windowId = window.id;
|
||||
if (!(windowId in windowVisibilityMap)) {
|
||||
// If it does not exist, it is the newly created window
|
||||
windowVisibilityMap[windowId] = true;
|
||||
registerVisibilityListener(window);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function updateTrayMenu() {
|
||||
const lastFocusedWindow = windowService.getLastFocusedWindow();
|
||||
const allWindows = windowService.getAllWindows();
|
||||
updateWindowVisibilityMap(allWindows);
|
||||
|
||||
function ensureVisible(win: BrowserWindow) {
|
||||
if (win) {
|
||||
win.show();
|
||||
win.focus();
|
||||
}
|
||||
}
|
||||
|
||||
function openNewWindow() {
|
||||
if (lastFocusedWindow){
|
||||
lastFocusedWindow.webContents.send("globalShortcut", "openNewWindow");
|
||||
}
|
||||
}
|
||||
|
||||
function triggerKeyboardAction(actionName: KeyboardActionNames) {
|
||||
mainWindow?.webContents.send("globalShortcut", actionName);
|
||||
ensureVisible();
|
||||
if (lastFocusedWindow){
|
||||
lastFocusedWindow.webContents.send("globalShortcut", actionName);
|
||||
ensureVisible(lastFocusedWindow);
|
||||
}
|
||||
}
|
||||
|
||||
function openInSameTab(note: BNote | BRecentNote) {
|
||||
mainWindow?.webContents.send("openInSameTab", note.noteId);
|
||||
ensureVisible();
|
||||
if (lastFocusedWindow){
|
||||
lastFocusedWindow.webContents.send("openInSameTab", note.noteId);
|
||||
ensureVisible(lastFocusedWindow);
|
||||
}
|
||||
}
|
||||
|
||||
function buildBookmarksMenu() {
|
||||
@ -144,20 +184,44 @@ function updateTrayMenu() {
|
||||
return menuItems;
|
||||
}
|
||||
|
||||
const contextMenu = Menu.buildFromTemplate([
|
||||
{
|
||||
label: t("tray.show-windows"),
|
||||
const windowVisibilityMenuItems: Electron.MenuItemConstructorOptions[] = [];
|
||||
|
||||
// Only call getWindowTitle if windowVisibilityMap has more than one window
|
||||
const showTitle = Object.keys(windowVisibilityMap).length > 1;
|
||||
|
||||
for (const idStr in windowVisibilityMap) {
|
||||
const id = parseInt(idStr, 10); // Get the ID of the window and make sure it is a number
|
||||
const isVisible = windowVisibilityMap[id];
|
||||
const win = allWindows.find(w => w.id === id);
|
||||
if (!win) {
|
||||
continue;
|
||||
}
|
||||
windowVisibilityMenuItems.push({
|
||||
label: showTitle ? `${t("tray.show-windows")}: ${getWindowTitle(win)}` : t("tray.show-windows"),
|
||||
type: "checkbox",
|
||||
checked: isVisible,
|
||||
click: () => {
|
||||
if (isVisible) {
|
||||
mainWindow.hide();
|
||||
win.hide();
|
||||
windowVisibilityMap[id] = false;
|
||||
} else {
|
||||
ensureVisible();
|
||||
ensureVisible(win);
|
||||
windowVisibilityMap[id] = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const contextMenu = Menu.buildFromTemplate([
|
||||
...windowVisibilityMenuItems,
|
||||
{ type: "separator" },
|
||||
{
|
||||
label: t("tray.open_new_window"),
|
||||
type: "normal",
|
||||
icon: getIconPath("new-window"),
|
||||
click: () => openNewWindow()
|
||||
},
|
||||
{
|
||||
label: t("tray.new-note"),
|
||||
type: "normal",
|
||||
@ -188,7 +252,10 @@ function updateTrayMenu() {
|
||||
type: "normal",
|
||||
icon: getIconPath("close"),
|
||||
click: () => {
|
||||
mainWindow.close();
|
||||
const windows = BrowserWindow.getAllWindows();
|
||||
windows.forEach(window => {
|
||||
window.close();
|
||||
});
|
||||
}
|
||||
}
|
||||
]);
|
||||
@ -197,16 +264,18 @@ function updateTrayMenu() {
|
||||
}
|
||||
|
||||
function changeVisibility() {
|
||||
const window = windowService.getMainWindow();
|
||||
if (!window) {
|
||||
const lastFocusedWindow = windowService.getLastFocusedWindow();
|
||||
|
||||
if (!lastFocusedWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isVisible) {
|
||||
window.hide();
|
||||
// If the window is visible, hide it
|
||||
if (windowVisibilityMap[lastFocusedWindow.id]) {
|
||||
lastFocusedWindow.hide();
|
||||
} else {
|
||||
window.show();
|
||||
window.focus();
|
||||
lastFocusedWindow.show();
|
||||
lastFocusedWindow.focus();
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,9 +290,15 @@ function createTray() {
|
||||
tray.on("click", changeVisibility);
|
||||
updateTrayMenu();
|
||||
|
||||
registerVisibilityListener();
|
||||
if (!isMac) {
|
||||
// macOS uses template icons which work great on dark & light themes.
|
||||
nativeTheme.on("updated", updateTrayMenu);
|
||||
}
|
||||
ipcMain.on("reload-tray", updateTrayMenu);
|
||||
i18next.on("languageChanged", updateTrayMenu);
|
||||
}
|
||||
|
||||
export default {
|
||||
createTray
|
||||
createTray,
|
||||
updateTrayMenu
|
||||
};
|
||||
|
@ -11,6 +11,7 @@ import remoteMain from "@electron/remote/main/index.js";
|
||||
import { BrowserWindow, shell, type App, type BrowserWindowConstructorOptions, type WebContents } from "electron";
|
||||
import { dialog, ipcMain } from "electron";
|
||||
import { formatDownloadTitle, isDev, isMac, isWindows } from "./utils.js";
|
||||
import tray from "./tray.js";
|
||||
|
||||
import { fileURLToPath } from "url";
|
||||
import { dirname } from "path";
|
||||
@ -19,6 +20,26 @@ import { t } from "i18next";
|
||||
// Prevent the window being garbage collected
|
||||
let mainWindow: BrowserWindow | null;
|
||||
let setupWindow: BrowserWindow | null;
|
||||
let allWindows: BrowserWindow[] = []; // // Used to store all windows, sorted by the order of focus.
|
||||
|
||||
function trackWindowFocus(win: BrowserWindow) {
|
||||
// We need to get the last focused window from allWindows. If the last window is closed, we return the previous window.
|
||||
// Therefore, we need to push the window into the allWindows array every time it gets focused.
|
||||
win.on("focus", () => {
|
||||
allWindows = allWindows.filter(w => !w.isDestroyed() && w !== win);
|
||||
allWindows.push(win);
|
||||
if (!optionService.getOptionBool("disableTray")) {
|
||||
tray.updateTrayMenu();
|
||||
}
|
||||
});
|
||||
|
||||
win.on("closed", () => {
|
||||
allWindows = allWindows.filter(w => !w.isDestroyed());
|
||||
if (!optionService.getOptionBool("disableTray")) {
|
||||
tray.updateTrayMenu();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function createExtraWindow(extraWindowHash: string) {
|
||||
const spellcheckEnabled = optionService.getOptionBool("spellCheckEnabled");
|
||||
@ -42,6 +63,8 @@ async function createExtraWindow(extraWindowHash: string) {
|
||||
win.loadURL(`http://127.0.0.1:${port}/?extraWindow=1${extraWindowHash}`);
|
||||
|
||||
configureWebContents(win.webContents, spellcheckEnabled);
|
||||
|
||||
trackWindowFocus(win);
|
||||
}
|
||||
|
||||
ipcMain.on("create-extra-window", (event, arg) => {
|
||||
@ -154,18 +177,21 @@ async function createMainWindow(app: App) {
|
||||
configureWebContents(mainWindow.webContents, spellcheckEnabled);
|
||||
|
||||
app.on("second-instance", (event, commandLine) => {
|
||||
const lastFocusedWindow = getLastFocusedWindow();
|
||||
if (commandLine.includes("--new-window")) {
|
||||
createExtraWindow("");
|
||||
} else if (mainWindow) {
|
||||
} else if (lastFocusedWindow) {
|
||||
// Someone tried to run a second instance, we should focus our window.
|
||||
// see www.ts "requestSingleInstanceLock" for the rest of this logic with explanation
|
||||
if (mainWindow.isMinimized()) {
|
||||
mainWindow.restore();
|
||||
if (lastFocusedWindow.isMinimized()) {
|
||||
lastFocusedWindow.restore();
|
||||
}
|
||||
|
||||
mainWindow.focus();
|
||||
lastFocusedWindow.show();
|
||||
lastFocusedWindow.focus();
|
||||
}
|
||||
});
|
||||
|
||||
trackWindowFocus(mainWindow);
|
||||
}
|
||||
|
||||
function getWindowExtraOpts() {
|
||||
@ -296,10 +322,20 @@ function getMainWindow() {
|
||||
return mainWindow;
|
||||
}
|
||||
|
||||
function getLastFocusedWindow() {
|
||||
return allWindows.length > 0 ? allWindows[allWindows.length - 1] : null;
|
||||
}
|
||||
|
||||
function getAllWindows(){
|
||||
return allWindows;
|
||||
}
|
||||
|
||||
export default {
|
||||
createMainWindow,
|
||||
createSetupWindow,
|
||||
closeSetupWindow,
|
||||
registerGlobalShortcuts,
|
||||
getMainWindow
|
||||
getMainWindow,
|
||||
getLastFocusedWindow,
|
||||
getAllWindows
|
||||
};
|
||||
|
@ -271,7 +271,8 @@
|
||||
"bookmarks": "书签",
|
||||
"today": "打开今天的日记笔记",
|
||||
"new-note": "新建笔记",
|
||||
"show-windows": "显示窗口"
|
||||
"show-windows": "显示窗口",
|
||||
"open_new_window": "打开新窗口"
|
||||
},
|
||||
"migration": {
|
||||
"old_version": "由您当前版本的直接迁移不被支持。请先升级到最新的 v0.60.4 然后再到这个版本。",
|
||||
|
@ -272,7 +272,8 @@
|
||||
"bookmarks": "Bookmarks",
|
||||
"today": "Open today's journal note",
|
||||
"new-note": "New note",
|
||||
"show-windows": "Show windows"
|
||||
"show-windows": "Show windows",
|
||||
"open_new_window": "Open new window"
|
||||
},
|
||||
"migration": {
|
||||
"old_version": "Direct migration from your current version is not supported. Please upgrade to the latest v0.60.4 first and only then to this version.",
|
||||
|