diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 000000000..57680f9dc
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,3 @@
+# Set line endings of shell scripts to LF, even on Windows, otherwise execution
+# within Docker fails.
+*.sh text eol=lf
diff --git a/.github/workflows/auth-lint.yml b/.github/workflows/auth-lint.yml
index fff7fb75f..1b45a2d32 100644
--- a/.github/workflows/auth-lint.yml
+++ b/.github/workflows/auth-lint.yml
@@ -1,11 +1,9 @@
name: "Lint (auth)"
on:
- # Run on every push to branches (this also covers pull requests)
+ # Run on every push to a branch other than main that changes auth/
push:
- # See: [Note: Specify branch when specifying a path filter]
- branches: ["**"]
- # Only run if something changes in these paths
+ branches-ignore: [main]
paths:
- "auth/**"
- ".github/workflows/auth-lint.yml"
diff --git a/.github/workflows/mobile-lint.yml b/.github/workflows/mobile-lint.yml
index c2e54d38a..7b5e5fbed 100644
--- a/.github/workflows/mobile-lint.yml
+++ b/.github/workflows/mobile-lint.yml
@@ -1,11 +1,9 @@
name: "Lint (mobile)"
on:
- # Run on every push (this also covers pull requests)
+ # Run on every push to a branch other than main that changes mobile/
push:
- # See: [Note: Specify branch when specifying a path filter]
- branches: ["**"]
- # Only run if something changes in these paths
+ branches-ignore: [main]
paths:
- "mobile/**"
- ".github/workflows/mobile-lint.yml"
diff --git a/.github/workflows/server-lint.yml b/.github/workflows/server-lint.yml
index e23036a6e..c051d0290 100644
--- a/.github/workflows/server-lint.yml
+++ b/.github/workflows/server-lint.yml
@@ -1,11 +1,9 @@
name: "Lint (server)"
on:
- # Run on every push (this also covers pull requests)
+ # Run on every push to a branch other than main that changes server/
push:
- # See: [Note: Specify branch when specifying a path filter]
- branches: ["**"]
- # Only run if something changes in these paths
+ branches-ignore: [main]
paths:
- "server/**"
- ".github/workflows/server-lint.yml"
diff --git a/.github/workflows/web-lint.yml b/.github/workflows/web-lint.yml
index a905069f6..7f5d27002 100644
--- a/.github/workflows/web-lint.yml
+++ b/.github/workflows/web-lint.yml
@@ -1,20 +1,9 @@
name: "Lint (web)"
on:
- # Run on every push (this also covers pull requests)
+ # Run on every push to a branch other than main that changes web/
push:
- # [Note: Specify branch when specifying a path filter]
- #
- # Path filters are ignored for tag pushes, which causes this workflow to
- # always run when we push a tag. Defining an explicit branch solves the
- # issue. From GitHub's docs:
- #
- # > if you define both branches/branches-ignore and paths/paths-ignore,
- # > the workflow will only run when both filters are satisfied.
- #
- # https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions
- branches: ["**"]
- # Only run if something changes in these paths
+ branches-ignore: [main]
paths:
- "web/**"
- ".github/workflows/web-lint.yml"
diff --git a/.github/workflows/web-preview.yml b/.github/workflows/web-preview.yml
new file mode 100644
index 000000000..4e86d9a81
--- /dev/null
+++ b/.github/workflows/web-preview.yml
@@ -0,0 +1,52 @@
+name: "Preview (web)"
+
+on:
+ workflow_dispatch:
+ inputs:
+ app:
+ description: "App to build and deploy"
+ type: choice
+ required: true
+ default: "photos"
+ options:
+ - "accounts"
+ - "auth"
+ - "cast"
+ - "photos"
+
+jobs:
+ deploy:
+ runs-on: ubuntu-latest
+
+ defaults:
+ run:
+ working-directory: web
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ with:
+ submodules: recursive
+
+ - name: Setup node and enable yarn caching
+ uses: actions/setup-node@v4
+ with:
+ node-version: 20
+ cache: "yarn"
+ cache-dependency-path: "docs/yarn.lock"
+
+ - name: Install dependencies
+ run: yarn install
+
+ - name: Build ${{ inputs.app }}
+ run: yarn build:${{ inputs.app }}
+
+ - name: Publish ${{ inputs.app }} to preview
+ uses: cloudflare/pages-action@1
+ with:
+ accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
+ apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
+ projectName: ente
+ branch: preview
+ directory: web/apps/${{ inputs.app }}/out
+ wranglerVersion: "3"
diff --git a/.gitmodules b/.gitmodules
index a3a52e7be..36834f2cd 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -9,10 +9,6 @@
[submodule "auth/assets/simple-icons"]
path = auth/assets/simple-icons
url = https://github.com/simple-icons/simple-icons.git
-[submodule "desktop/thirdparty/next-electron-server"]
- path = desktop/thirdparty/next-electron-server
- url = https://github.com/ente-io/next-electron-server.git
- branch = desktop
[submodule "mobile/thirdparty/flutter"]
path = mobile/thirdparty/flutter
url = https://github.com/flutter/flutter.git
diff --git a/desktop/.github/workflows/build.yml b/desktop/.github/workflows/build.yml
index c43dfcfdf..acd744c05 100644
--- a/desktop/.github/workflows/build.yml
+++ b/desktop/.github/workflows/build.yml
@@ -52,7 +52,4 @@ jobs:
# macOS notarization API key
API_KEY_ID: ${{ secrets.api_key_id }}
API_KEY_ISSUER_ID: ${{ secrets.api_key_issuer_id}}
- # setry crash reporting token
- SENTRY_AUTH_TOKEN: ${{secrets.sentry_auth_token}}
- NEXT_PUBLIC_DISABLE_SENTRY: ${{secrets.next_public_disable_sentry}}
USE_HARD_LINKS: false
diff --git a/desktop/.gitignore b/desktop/.gitignore
index b01288f0a..9b7e0cc60 100644
--- a/desktop/.gitignore
+++ b/desktop/.gitignore
@@ -11,10 +11,11 @@ node_modules/
.env
.env.*.local
-# Generated code during build
-# - tsc transpiles src/**/*.ts and emits the generated JS into build/app
-# - The out dir from the photos web app is symlinked to build/out
-build/
+# tsc transpiles src/**/*.ts and emits the generated JS into app
+app/
+
+# out is a symlink to the photos web app's dir
+out
# electron-builder
dist/
diff --git a/desktop/.prettierignore b/desktop/.prettierignore
deleted file mode 100644
index c2ed1358c..000000000
--- a/desktop/.prettierignore
+++ /dev/null
@@ -1 +0,0 @@
-thirdparty/
diff --git a/desktop/CHANGELOG.md b/desktop/CHANGELOG.md
index 0a1602b94..73aae2397 100644
--- a/desktop/CHANGELOG.md
+++ b/desktop/CHANGELOG.md
@@ -4,128 +4,128 @@
### New
-- Option to select file download location.
-- Add support for searching popular cities
-- Sorted duplicates in desecending order of size
-- Add Counter to upload section
-- Display full name and collection name on hover on dedupe screen photos
+- Option to select file download location.
+- Add support for searching popular cities
+- Sorted duplicates in desecending order of size
+- Add Counter to upload section
+- Display full name and collection name on hover on dedupe screen photos
### Bug Fixes
-- Fix add to album padding issue
-- Fix double uncategorized album issue
-- Hide Hidden collection files from all section
+- Fix add to album padding issue
+- Fix double uncategorized album issue
+- Hide Hidden collection files from all section
## v1.6.62
### New
-- Integrated onnx clip runner
+- Integrated onnx clip runner
### Bug Fixes
-- Fixes login button requiring double click issue
-- Fixes Collection sort state not preserved issue
-- Fixes continuous export causing app crash
-- Improves ML related copies for better distinction from clip
-- Added Better favicon for light mode
-- Fixed face indexing issues
-- Fixed thumbnail load issue
+- Fixes login button requiring double click issue
+- Fixes Collection sort state not preserved issue
+- Fixes continuous export causing app crash
+- Improves ML related copies for better distinction from clip
+- Added Better favicon for light mode
+- Fixed face indexing issues
+- Fixed thumbnail load issue
## v1.6.60
### Bug Fixes
-- Fix Thumbnail Orientation issue
-- Fix ML logging issue
+- Fix Thumbnail Orientation issue
+- Fix ML logging issue
## v1.6.59
### New
-- Added arm64 builds for linux
+- Added arm64 builds for linux
### Bug Fixes
-- Fix Editor file not loading issue
-- Fix ML results missing thumbnail issue
+- Fix Editor file not loading issue
+- Fix ML results missing thumbnail issue
## v1.6.58
### Bug Fixes
-- Fix File load issue
+- Fix File load issue
## v1.6.57
### New Features
-- Added encrypted Disk caching for files
-- Added option to customize cache folder location
+- Added encrypted Disk caching for files
+- Added option to customize cache folder location
### Bug Fixes
-- Fixed caching issue,causing multiple download of file during ml sync
+- Fixed caching issue,causing multiple download of file during ml sync
## v1.6.55
### Bug Fixes
-- Added manage family portal option if add-on is active
-- Fixed filename date parsing issue
-- Fixed storage limit ui glitch
-- Fixed dedupe page layout issue
-- Fixed ElectronAPI refactoring issue
-- Fixed Search related issues
+- Added manage family portal option if add-on is active
+- Fixed filename date parsing issue
+- Fixed storage limit ui glitch
+- Fixed dedupe page layout issue
+- Fixed ElectronAPI refactoring issue
+- Fixed Search related issues
## v1.6.54
### New Features
-- Added support for HEIC and raw image in photo editor
+- Added support for HEIC and raw image in photo editor
### Bug Fixes
-- Fixed 16bit HDR HEIC images support
-- Fixed blocked login due safe storage issue
-- Fixed Search related issues
-- Fixed issue of watch folder not cleared on logout
-- other under the hood ui/ux improvements
+- Fixed 16bit HDR HEIC images support
+- Fixed blocked login due safe storage issue
+- Fixed Search related issues
+- Fixed issue of watch folder not cleared on logout
+- other under the hood ui/ux improvements
## v1.6.53
### Bug Fixes
-- Fixed watch folder disabled issue
-- Fixed BF Add on related issues
-- Fixed clip sync issue and added better logging
-- Fixed mov file upload
-- Fixed clip extraction related issue
+- Fixed watch folder disabled issue
+- Fixed BF Add on related issues
+- Fixed clip sync issue and added better logging
+- Fixed mov file upload
+- Fixed clip extraction related issue
## v1.6.52
### New Features
-- Added Clip Desktop on windows
+- Added Clip Desktop on windows
### Bug Fixes
-- fixed google json matching issue
-- other under-the-hood changes to improve performance and bug fixes
+- fixed google json matching issue
+- other under-the-hood changes to improve performance and bug fixes
## v1.6.50
### New Features
-- Added Clip desktop
+- Added Clip desktop
### Bug Fixes
-- Fixed desktop downloaded file had extra dot in the name
-- Cleanup error messages
-- fix the motion photo clustering issue
-- Add option to disable cf proxy locally
-- other under-the-hood changes to improve UX
+- Fixed desktop downloaded file had extra dot in the name
+- Cleanup error messages
+- fix the motion photo clustering issue
+- Add option to disable cf proxy locally
+- other under-the-hood changes to improve UX
## v1.6.49
@@ -137,54 +137,54 @@ Check out our [blog](https://ente.io/blog/introducing-web-desktop-photo-editor/)
### Bug Fixes
-- Fixed misaligned icons in photo-viewer
-- Fixed issue with Motion photo upload
-- Fixed issue with Live-photo upload
-- other minor ux improvement
+- Fixed misaligned icons in photo-viewer
+- Fixed issue with Motion photo upload
+- Fixed issue with Live-photo upload
+- other minor ux improvement
## v1.6.46
### Bug Fixes
-- Fixes OOM crashes during file upload [#1379](https://github.com/ente-io/photos-web/pull/1379)
+- Fixes OOM crashes during file upload [#1379](https://github.com/ente-io/photos-web/pull/1379)
## v1.6.45
### Bug Fixes
-- Fixed app keeps reloading issue [#235](https://github.com/ente-io/photos-desktop/pull/235)
-- Fixed dng and arw preview issue [#1378](https://github.com/ente-io/photos-web/pull/1378)
-- Added view crash report option (help menu) for user to share electron crash report locally
+- Fixed app keeps reloading issue [#235](https://github.com/ente-io/photos-desktop/pull/235)
+- Fixed dng and arw preview issue [#1378](https://github.com/ente-io/photos-web/pull/1378)
+- Added view crash report option (help menu) for user to share electron crash report locally
## v1.6.44
-- Upgraded electron to get latest security patches and other improvements.
+- Upgraded electron to get latest security patches and other improvements.
## v1.6.43
### Added
-- #### Check for update and changelog option
+- #### Check for update and changelog option
Added options to check for update manually and a view changelog via the app menubar
-- #### Opt out of crash reporting
+- #### Opt out of crash reporting
Added option to out of a crash reporting, it can accessed from the settings -> preferences -> disable crash reporting
-- #### Type search
+- #### Type search
Added new search option to search files based on file type i.e, image, video, live-photo.
-- #### Manual Convert Button
+- #### Manual Convert Button
In case the video is not playable, Now there is a convert button which can be used to trigger conversion of the video to supported format.
-- #### File Download Progress
+- #### File Download Progress
The file loader now also shows the exact percentage download progress, instead of just a simple loader.
-- #### Bug fixes & other enhancements
+- #### Bug fixes & other enhancements
We have squashed a few pesky bugs that were reported by our community
@@ -192,21 +192,21 @@ Check out our [blog](https://ente.io/blog/introducing-web-desktop-photo-editor/)
### Added
-- #### Hidden albums
+- #### Hidden albums
You can now hide albums, just like individual memories.
-- #### Email verification
+- #### Email verification
We have now made email verification optional, so you can sign in with just your email address and password, without waiting for a verification code.
You can opt in / out of email verification from Settings > Security.
-- #### Download Album
+- #### Download Album
You can now chose the download location for downloading albums. Along with that we have also added progress bar for album download.
-- #### Bug fixes & other enhancements
+- #### Bug fixes & other enhancements
We have squashed a few pesky bugs that were reported by our community
diff --git a/desktop/README.md b/desktop/README.md
index 9d637de04..da74b133f 100644
--- a/desktop/README.md
+++ b/desktop/README.md
@@ -10,40 +10,28 @@ To know more about Ente, see [our main README](../README.md) or visit
## Building from source
-> [!CAUTION]
->
-> We moved a few things around when switching to a monorepo recently, and the
-> desktop app is not currently building with these instructions below. Hang
-> tight, we're on it, and will fix soon.
-
-Fetch submodules
-
-```sh
-git submodule update --init --recursive
-```
-
Install dependencies
```sh
yarn install
```
-Run the app
+Run in development mode (with hot reload)
```sh
yarn dev
```
-To recompile automatically using electron-reload, run this in a separate
-terminal:
+> [!CAUTION]
+>
+> `yarn dev` is currently not working (we'll fix soon). If you just want to
+> build from source and use the generated binary, use `yarn build`.
-```bash
-yarn watch
-```
-
-`yarn dev` is handy during development, but if you wish, you can also create a
-binary for your platform by using
+Or create a binary for your platform
```sh
yarn build
```
+
+That's the gist of it. For more development related documentation, see
+[docs](docs/README.md).
diff --git a/desktop/resources/entitlements.mac.plist b/desktop/build/entitlements.mac.plist
similarity index 100%
rename from desktop/resources/entitlements.mac.plist
rename to desktop/build/entitlements.mac.plist
diff --git a/desktop/resources/error.html b/desktop/build/error.html
similarity index 98%
rename from desktop/resources/error.html
rename to desktop/build/error.html
index 3291f7789..cf1ea149d 100644
--- a/desktop/resources/error.html
+++ b/desktop/build/error.html
@@ -1,4 +1,4 @@
-
+
diff --git a/desktop/resources/ggmlclip-linux b/desktop/build/ggmlclip-linux
similarity index 100%
rename from desktop/resources/ggmlclip-linux
rename to desktop/build/ggmlclip-linux
diff --git a/desktop/resources/ggmlclip-mac b/desktop/build/ggmlclip-mac
similarity index 100%
rename from desktop/resources/ggmlclip-mac
rename to desktop/build/ggmlclip-mac
diff --git a/desktop/resources/ggmlclip-windows.exe b/desktop/build/ggmlclip-windows.exe
similarity index 100%
rename from desktop/resources/ggmlclip-windows.exe
rename to desktop/build/ggmlclip-windows.exe
diff --git a/desktop/resources/icon.icns b/desktop/build/icon.icns
similarity index 100%
rename from desktop/resources/icon.icns
rename to desktop/build/icon.icns
diff --git a/desktop/resources/icon.png b/desktop/build/icon.png
similarity index 100%
rename from desktop/resources/icon.png
rename to desktop/build/icon.png
diff --git a/desktop/resources/image-magick b/desktop/build/image-magick
similarity index 100%
rename from desktop/resources/image-magick
rename to desktop/build/image-magick
diff --git a/desktop/resources/msvcp140d.dll b/desktop/build/msvcp140d.dll
similarity index 100%
rename from desktop/resources/msvcp140d.dll
rename to desktop/build/msvcp140d.dll
diff --git a/desktop/resources/splash.html b/desktop/build/splash.html
similarity index 99%
rename from desktop/resources/splash.html
rename to desktop/build/splash.html
index 7d4a195e5..199c31601 100644
--- a/desktop/resources/splash.html
+++ b/desktop/build/splash.html
@@ -1,4 +1,4 @@
-
+
diff --git a/desktop/resources/taskbar-icon-Template.png b/desktop/build/taskbar-icon-Template.png
similarity index 100%
rename from desktop/resources/taskbar-icon-Template.png
rename to desktop/build/taskbar-icon-Template.png
diff --git a/desktop/resources/taskbar-icon-Template@2x.png b/desktop/build/taskbar-icon-Template@2x.png
similarity index 100%
rename from desktop/resources/taskbar-icon-Template@2x.png
rename to desktop/build/taskbar-icon-Template@2x.png
diff --git a/desktop/resources/taskbar-icon-Template@3x.png b/desktop/build/taskbar-icon-Template@3x.png
similarity index 100%
rename from desktop/resources/taskbar-icon-Template@3x.png
rename to desktop/build/taskbar-icon-Template@3x.png
diff --git a/desktop/resources/taskbar-icon.png b/desktop/build/taskbar-icon.png
similarity index 100%
rename from desktop/resources/taskbar-icon.png
rename to desktop/build/taskbar-icon.png
diff --git a/desktop/resources/taskbar-icon@2x.png b/desktop/build/taskbar-icon@2x.png
similarity index 100%
rename from desktop/resources/taskbar-icon@2x.png
rename to desktop/build/taskbar-icon@2x.png
diff --git a/desktop/resources/taskbar-icon@3x.png b/desktop/build/taskbar-icon@3x.png
similarity index 100%
rename from desktop/resources/taskbar-icon@3x.png
rename to desktop/build/taskbar-icon@3x.png
diff --git a/desktop/resources/ucrtbased.dll b/desktop/build/ucrtbased.dll
similarity index 100%
rename from desktop/resources/ucrtbased.dll
rename to desktop/build/ucrtbased.dll
diff --git a/desktop/resources/vcruntime140_1d.dll b/desktop/build/vcruntime140_1d.dll
similarity index 100%
rename from desktop/resources/vcruntime140_1d.dll
rename to desktop/build/vcruntime140_1d.dll
diff --git a/desktop/resources/vcruntime140d.dll b/desktop/build/vcruntime140d.dll
similarity index 100%
rename from desktop/resources/vcruntime140d.dll
rename to desktop/build/vcruntime140d.dll
diff --git a/desktop/resources/version.html b/desktop/build/version.html
similarity index 98%
rename from desktop/resources/version.html
rename to desktop/build/version.html
index 03bf806a6..b2038edd7 100644
--- a/desktop/resources/version.html
+++ b/desktop/build/version.html
@@ -1,4 +1,4 @@
-
+
Electron Updater Example
diff --git a/desktop/resources/window-icon.png b/desktop/build/window-icon.png
similarity index 100%
rename from desktop/resources/window-icon.png
rename to desktop/build/window-icon.png
diff --git a/desktop/docs/dependencies.md b/desktop/docs/dependencies.md
index 8703331a2..6b0196723 100644
--- a/desktop/docs/dependencies.md
+++ b/desktop/docs/dependencies.md
@@ -4,3 +4,11 @@ See [web/docs/dependencies.md](../../web/docs/dependencies.md) for general web
specific dependencies. See [electron.md](electron.md) for our main dependency,
Electron. The rest of this document describes the remaining, desktop specific
dependencies that are used by the Photos desktop app.
+
+## Electron related
+
+### next-electron-server
+
+This spins up a server for serving files using a protocol handler inside our
+Electron process. This allows us to directly use the output produced by `next
+build` for loading into our renderer process.
diff --git a/desktop/docs/dev.md b/desktop/docs/dev.md
new file mode 100644
index 000000000..bfa80df69
--- /dev/null
+++ b/desktop/docs/dev.md
@@ -0,0 +1,4 @@
+# Development tips
+
+- `yarn build:quick` is a variant of `yarn build` that uses the
+ `--config.compression=store` flag to (slightly) speed up electron-builder.
diff --git a/desktop/docs/electron.md b/desktop/docs/electron.md
index e6c56b55b..84c47e329 100644
--- a/desktop/docs/electron.md
+++ b/desktop/docs/electron.md
@@ -7,15 +7,15 @@ Electron embeds Chromium and Node.js in the generated app's binary. The
generated app thus consists of two separate processes - the _main_ process, and
a _renderer_ process.
-* The _main_ process is runs the embedded node. This process can deal with the
- host OS - it is conceptually like a `node` repl running on your machine. In our
- case, the TypeScript code (in the `src/` directory) gets transpiled by `tsc`
- into JavaScript in the `build/app/` directory, which gets bundled in the
- generated app's binary and is loaded by the node (main) process when the app
- starts.
+- The _main_ process is runs the embedded node. This process can deal with the
+ host OS - it is conceptually like a `node` repl running on your machine. In our
+ case, the TypeScript code (in the `src/` directory) gets transpiled by `tsc`
+ into JavaScript in the `build/app/` directory, which gets bundled in the
+ generated app's binary and is loaded by the node (main) process when the app
+ starts.
-* The _renderer_ process is a regular web app that gets loaded into the embedded
- Chromium. When the main process starts, it creates a new "window" that shows
- this embedded Chromium. In our case, we build and bundle a static export of
- the [Photos web app](../web/README.md) in the generated app. This gets loaded
- by the embedded Chromium at runtime, acting as the app's UI.
+- The _renderer_ process is a regular web app that gets loaded into the embedded
+ Chromium. When the main process starts, it creates a new "window" that shows
+ this embedded Chromium. In our case, we build and bundle a static export of
+ the [Photos web app](../web/README.md) in the generated app. This gets loaded
+ by the embedded Chromium at runtime, acting as the app's UI.
diff --git a/desktop/package.json b/desktop/package.json
index b0ea95b09..8d90fca6e 100644
--- a/desktop/package.json
+++ b/desktop/package.json
@@ -4,21 +4,22 @@
"private": true,
"description": "Desktop client for Ente Photos",
"author": "Ente ",
- "main": "build/app/main.js",
+ "main": "app/main.js",
"scripts": {
- "build": "mkdir -p build && yarn build-renderer && yarn build-main",
- "build-main": "tsc && electron-builder --config.compression=store",
- "build-renderer": "cd ../web && yarn install && yarn build:photos && cd ../desktop/build && rm -f out && ln -sf ../../web/apps/photos/out",
- "dev": "concurrently \"yarn dev-main\" \"yarn dev-renderer\"",
- "dev-main": "tsc && electron build/app/main.js",
- "dev-renderer": "cd ../web && yarn install && yarn dev:photos && cd ../desktop/build && rm -f out && ln -sf ../../web/apps/photos/out",
+ "build": "yarn build-renderer && yarn build-main",
+ "build-main": "tsc && electron-builder",
+ "build-main:quick": "tsc && electron-builder --config.compression=store",
+ "build-renderer": "cd ../web && yarn install && yarn build:photos && cd ../desktop && rm -f out && ln -sf ../web/apps/photos/out",
+ "build:quick": "yarn build-renderer && yarn build-main:quick",
+ "dev": "concurrently --names 'main,rndr,tscw' \"yarn dev-main\" \"yarn dev-renderer\" \"yarn dev-main-watch\"",
+ "dev-main": "tsc && electron app/main.js",
+ "dev-main-watch": "tsc --watch --preserveWatchOutput",
+ "dev-renderer": "cd ../web && yarn install && yarn dev:photos",
"postinstall": "electron-builder install-app-deps",
"lint": "yarn prettier --check . && eslint \"src/**/*.ts\"",
- "lint-fix": "yarn prettier --write . && eslint --fix .",
- "watch": "tsc -w"
+ "lint-fix": "yarn prettier --write . && eslint --fix src"
},
"dependencies": {
- "@sentry/electron": "^2.5.1",
"any-shell-escape": "^0.1.1",
"auto-launch": "^5.0.5",
"chokidar": "^3.5.3",
@@ -31,14 +32,13 @@
"get-folder-size": "^2.0.1",
"html-entities": "^2.4.0",
"jpeg-js": "^0.4.4",
- "next-electron-server": "file:./thirdparty/next-electron-server",
+ "next-electron-server": "^1",
"node-fetch": "^2.6.7",
"node-stream-zip": "^1.15.0",
"onnxruntime-node": "^1.16.3",
"promise-fs": "^2.1.1"
},
"devDependencies": {
- "@sentry/cli": "^1.68.0",
"@types/auto-launch": "^5.0.2",
"@types/ffmpeg-static": "^3.0.1",
"@types/get-folder-size": "^2.0.0",
@@ -55,7 +55,7 @@
"eslint": "^7.23.0",
"eslint-config-google": "^0.14.0",
"eslint-config-prettier": "^8.5.0",
- "prettier": "2.5.1",
+ "prettier": "^3",
"prettier-plugin-organize-imports": "^3.2",
"prettier-plugin-packagejson": "^2.4",
"typescript": "^4.2.3"
@@ -112,26 +112,20 @@
"x64ArchFiles": "Contents/Resources/ggmlclip-mac"
},
"afterSign": "electron-builder-notarize",
- "extraFiles": [
- {
- "from": "resources",
- "to": "resources",
- "filter": [
- "**/*"
- ]
- }
- ],
"asarUnpack": [
"node_modules/ffmpeg-static/bin/${os}/${arch}/ffmpeg",
"node_modules/ffmpeg-static/index.js",
"node_modules/ffmpeg-static/package.json"
],
- "files": [
- "build/app/**/*",
+ "extraFiles": [
{
- "from": "build/out",
- "to": "out"
+ "from": "build",
+ "to": "resources"
}
+ ],
+ "files": [
+ "app/**/*",
+ "out"
]
},
"productName": "ente",
diff --git a/desktop/sentry.properties b/desktop/sentry.properties
deleted file mode 100644
index d9303317c..000000000
--- a/desktop/sentry.properties
+++ /dev/null
@@ -1,3 +0,0 @@
-defaults.url=https://sentry.ente.io/
-defaults.org=ente
-defaults.project=desktop-photos
diff --git a/desktop/src/api/cache.ts b/desktop/src/api/cache.ts
index eabcef980..86ba4378c 100644
--- a/desktop/src/api/cache.ts
+++ b/desktop/src/api/cache.ts
@@ -22,7 +22,7 @@ const getCacheBucketDir = async (cacheName: string) => {
export async function openDiskCache(
cacheName: string,
- cacheLimitInBytes?: number
+ cacheLimitInBytes?: number,
) {
const cacheBucketDir = await getCacheBucketDir(cacheName);
if (!existsSync(cacheBucketDir)) {
@@ -42,7 +42,7 @@ export async function deleteDiskCache(cacheName: string) {
}
export async function setCustomCacheDirectory(
- directory: string
+ directory: string,
): Promise {
await ipcRenderer.invoke("set-custom-cache-directory", directory);
}
diff --git a/desktop/src/api/clip.ts b/desktop/src/api/clip.ts
index 56772474d..d2469e7b9 100644
--- a/desktop/src/api/clip.ts
+++ b/desktop/src/api/clip.ts
@@ -5,7 +5,7 @@ import { isExecError, parseExecError } from "../utils/error";
export async function computeImageEmbedding(
model: Model,
- imageData: Uint8Array
+ imageData: Uint8Array,
): Promise {
let tempInputFilePath = null;
try {
@@ -15,7 +15,7 @@ export async function computeImageEmbedding(
const embedding = await ipcRenderer.invoke(
"compute-image-embedding",
model,
- tempInputFilePath
+ tempInputFilePath,
);
return embedding;
} catch (err) {
@@ -34,13 +34,13 @@ export async function computeImageEmbedding(
export async function computeTextEmbedding(
model: Model,
- text: string
+ text: string,
): Promise {
try {
const embedding = await ipcRenderer.invoke(
"compute-text-embedding",
model,
- text
+ text,
);
return embedding;
} catch (err) {
diff --git a/desktop/src/api/common.ts b/desktop/src/api/common.ts
index 1c6281d48..f18506981 100644
--- a/desktop/src/api/common.ts
+++ b/desktop/src/api/common.ts
@@ -36,9 +36,4 @@ export const getPlatform = async (): Promise<"mac" | "windows" | "linux"> => {
}
};
-export {
- getSentryUserID,
- logToDisk,
- openLogDirectory,
- updateOptOutOfCrashReports,
-} from "../services/logging";
+export { logToDisk, openLogDirectory } from "../services/logging";
diff --git a/desktop/src/api/electronStore.ts b/desktop/src/api/electronStore.ts
index 9475134c6..5f84776e1 100644
--- a/desktop/src/api/electronStore.ts
+++ b/desktop/src/api/electronStore.ts
@@ -2,7 +2,6 @@ import { logError } from "../services/logging";
import { keysStore } from "../stores/keys.store";
import { safeStorageStore } from "../stores/safeStorage.store";
import { uploadStatusStore } from "../stores/upload.store";
-import { userPreferencesStore } from "../stores/userPreferences.store";
import { watchStore } from "../stores/watch.store";
export const clearElectronStore = () => {
@@ -11,7 +10,6 @@ export const clearElectronStore = () => {
keysStore.clear();
safeStorageStore.clear();
watchStore.clear();
- userPreferencesStore.delete("optOutOfCrashReports");
} catch (e) {
logError(e, "error while clearing electron store");
throw e;
diff --git a/desktop/src/api/export.ts b/desktop/src/api/export.ts
index f5eef4f59..8adaa236f 100644
--- a/desktop/src/api/export.ts
+++ b/desktop/src/api/export.ts
@@ -13,7 +13,7 @@ export const checkExistsAndCreateDir = async (dirPath: string) => {
export const saveStreamToDisk = async (
filePath: string,
- fileStream: ReadableStream
+ fileStream: ReadableStream,
) => {
await writeStream(filePath, fileStream);
};
diff --git a/desktop/src/api/ffmpeg.ts b/desktop/src/api/ffmpeg.ts
index ef2e2291e..9d11183a8 100644
--- a/desktop/src/api/ffmpeg.ts
+++ b/desktop/src/api/ffmpeg.ts
@@ -8,7 +8,7 @@ export async function runFFmpegCmd(
cmd: string[],
inputFile: File | ElectronFile,
outputFileName: string,
- dontTimeout?: boolean
+ dontTimeout?: boolean,
) {
let inputFilePath = null;
let createdTempInputFile = null;
@@ -16,7 +16,7 @@ export async function runFFmpegCmd(
if (!existsSync(inputFile.path)) {
const tempFilePath = await ipcRenderer.invoke(
"get-temp-file-path",
- inputFile.name
+ inputFile.name,
);
await writeStream(tempFilePath, await inputFile.stream());
inputFilePath = tempFilePath;
@@ -29,7 +29,7 @@ export async function runFFmpegCmd(
cmd,
inputFilePath,
outputFileName,
- dontTimeout
+ dontTimeout,
);
return new File([outputFileData], outputFileName);
} finally {
diff --git a/desktop/src/api/imageProcessor.ts b/desktop/src/api/imageProcessor.ts
index 84d447a54..9d93aecd1 100644
--- a/desktop/src/api/imageProcessor.ts
+++ b/desktop/src/api/imageProcessor.ts
@@ -8,7 +8,7 @@ import { isPlatform } from "../utils/common/platform";
export async function convertToJPEG(
fileData: Uint8Array,
- filename: string
+ filename: string,
): Promise {
if (isPlatform("windows")) {
throw Error(CustomErrors.WINDOWS_NATIVE_IMAGE_PROCESSING_NOT_SUPPORTED);
@@ -16,7 +16,7 @@ export async function convertToJPEG(
const convertedFileData = await ipcRenderer.invoke(
"convert-to-jpeg",
fileData,
- filename
+ filename,
);
return convertedFileData;
}
@@ -24,20 +24,20 @@ export async function convertToJPEG(
export async function generateImageThumbnail(
inputFile: File | ElectronFile,
maxDimension: number,
- maxSize: number
+ maxSize: number,
): Promise {
let inputFilePath = null;
let createdTempInputFile = null;
try {
if (isPlatform("windows")) {
throw Error(
- CustomErrors.WINDOWS_NATIVE_IMAGE_PROCESSING_NOT_SUPPORTED
+ CustomErrors.WINDOWS_NATIVE_IMAGE_PROCESSING_NOT_SUPPORTED,
);
}
if (!existsSync(inputFile.path)) {
const tempFilePath = await ipcRenderer.invoke(
"get-temp-file-path",
- inputFile.name
+ inputFile.name,
);
await writeStream(tempFilePath, await inputFile.stream());
inputFilePath = tempFilePath;
@@ -49,7 +49,7 @@ export async function generateImageThumbnail(
"generate-image-thumbnail",
inputFilePath,
maxDimension,
- maxSize
+ maxSize,
);
return thumbnail;
} finally {
diff --git a/desktop/src/api/safeStorage.ts b/desktop/src/api/safeStorage.ts
index 89529013a..64c489195 100644
--- a/desktop/src/api/safeStorage.ts
+++ b/desktop/src/api/safeStorage.ts
@@ -6,7 +6,7 @@ export async function setEncryptionKey(encryptionKey: string) {
try {
const encryptedKey: Buffer = await ipcRenderer.invoke(
"safeStorage-encrypt",
- encryptionKey
+ encryptionKey,
);
const b64EncryptedKey = Buffer.from(encryptedKey).toString("base64");
safeStorageStore.set("encryptionKey", b64EncryptedKey);
@@ -21,7 +21,7 @@ export async function getEncryptionKey(): Promise {
const b64EncryptedKey = safeStorageStore.get("encryptionKey");
if (b64EncryptedKey) {
const keyBuffer = new Uint8Array(
- Buffer.from(b64EncryptedKey, "base64")
+ Buffer.from(b64EncryptedKey, "base64"),
);
return await ipcRenderer.invoke("safeStorage-decrypt", keyBuffer);
}
diff --git a/desktop/src/api/system.ts b/desktop/src/api/system.ts
index 7a8635a9f..a4dc91e05 100644
--- a/desktop/src/api/system.ts
+++ b/desktop/src/api/system.ts
@@ -9,7 +9,7 @@ export const reloadWindow = () => {
};
export const registerUpdateEventListener = (
- showUpdateDialog: (updateInfo: AppUpdateInfo) => void
+ showUpdateDialog: (updateInfo: AppUpdateInfo) => void,
) => {
ipcRenderer.removeAllListeners("show-update-dialog");
ipcRenderer.on("show-update-dialog", (_, updateInfo: AppUpdateInfo) => {
diff --git a/desktop/src/api/upload.ts b/desktop/src/api/upload.ts
index fc137452c..280ff084f 100644
--- a/desktop/src/api/upload.ts
+++ b/desktop/src/api/upload.ts
@@ -39,7 +39,7 @@ export const getPendingUploads = async () => {
export const showUploadDirsDialog = async () => {
try {
const filePaths: string[] = await ipcRenderer.invoke(
- "show-upload-dirs-dialog"
+ "show-upload-dirs-dialog",
);
const files = await Promise.all(filePaths.map(getElectronFile));
return files;
@@ -51,7 +51,7 @@ export const showUploadDirsDialog = async () => {
export const showUploadFilesDialog = async () => {
try {
const filePaths: string[] = await ipcRenderer.invoke(
- "show-upload-files-dialog"
+ "show-upload-files-dialog",
);
const files = await Promise.all(filePaths.map(getElectronFile));
return files;
@@ -63,7 +63,7 @@ export const showUploadFilesDialog = async () => {
export const showUploadZipDialog = async () => {
try {
const filePaths: string[] = await ipcRenderer.invoke(
- "show-upload-zip-dialog"
+ "show-upload-zip-dialog",
);
let files: ElectronFile[] = [];
diff --git a/desktop/src/api/watch.ts b/desktop/src/api/watch.ts
index 9ebb5b461..1b7a4ac3c 100644
--- a/desktop/src/api/watch.ts
+++ b/desktop/src/api/watch.ts
@@ -9,7 +9,7 @@ import { isMappingPresent } from "../utils/watch";
export async function addWatchMapping(
rootFolderName: string,
folderPath: string,
- uploadStrategy: number
+ uploadStrategy: number,
) {
ElectronLog.log(`Adding watch mapping: ${folderPath}`);
const watchMappings = getWatchMappings();
@@ -35,7 +35,7 @@ export async function addWatchMapping(
export async function removeWatchMapping(folderPath: string) {
let watchMappings = getWatchMappings();
const watchMapping = watchMappings.find(
- (mapping) => mapping.folderPath === folderPath
+ (mapping) => mapping.folderPath === folderPath,
);
if (!watchMapping) {
@@ -47,7 +47,7 @@ export async function removeWatchMapping(folderPath: string) {
});
watchMappings = watchMappings.filter(
- (mapping) => mapping.folderPath !== watchMapping.folderPath
+ (mapping) => mapping.folderPath !== watchMapping.folderPath,
);
setWatchMappings(watchMappings);
@@ -55,11 +55,11 @@ export async function removeWatchMapping(folderPath: string) {
export function updateWatchMappingSyncedFiles(
folderPath: string,
- files: WatchMapping["syncedFiles"]
+ files: WatchMapping["syncedFiles"],
): void {
const watchMappings = getWatchMappings();
const watchMapping = watchMappings.find(
- (mapping) => mapping.folderPath === folderPath
+ (mapping) => mapping.folderPath === folderPath,
);
if (!watchMapping) {
@@ -72,11 +72,11 @@ export function updateWatchMappingSyncedFiles(
export function updateWatchMappingIgnoredFiles(
folderPath: string,
- files: WatchMapping["ignoredFiles"]
+ files: WatchMapping["ignoredFiles"],
): void {
const watchMappings = getWatchMappings();
const watchMapping = watchMappings.find(
- (mapping) => mapping.folderPath === folderPath
+ (mapping) => mapping.folderPath === folderPath,
);
if (!watchMapping) {
@@ -90,7 +90,7 @@ export function updateWatchMappingIgnoredFiles(
export function registerWatcherFunctions(
addFile: (file: ElectronFile) => Promise,
removeFile: (path: string) => Promise,
- removeFolder: (folderPath: string) => Promise
+ removeFolder: (folderPath: string) => Promise,
) {
ipcRenderer.removeAllListeners("watch-add");
ipcRenderer.removeAllListeners("watch-change");
diff --git a/desktop/src/config/index.ts b/desktop/src/config/index.ts
deleted file mode 100644
index a27de5aa2..000000000
--- a/desktop/src/config/index.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-const PROD_HOST_URL: string = "ente://app";
-const RENDERER_OUTPUT_DIR: string = "./out";
-const LOG_FILENAME = "ente.log";
-const MAX_LOG_SIZE = 50 * 1024 * 1024; // 50MB
-
-const FILE_STREAM_CHUNK_SIZE: number = 4 * 1024 * 1024;
-
-const SENTRY_DSN = "https://759d8498487a81ac33a0c2efa2a42c4f@sentry.ente.io/9";
-
-const RELEASE_VERSION = require("../../package.json").version;
-
-export {
- PROD_HOST_URL,
- RENDERER_OUTPUT_DIR,
- FILE_STREAM_CHUNK_SIZE,
- LOG_FILENAME,
- MAX_LOG_SIZE,
- SENTRY_DSN,
- RELEASE_VERSION,
-};
diff --git a/desktop/src/main.ts b/desktop/src/main.ts
index 3663b7b8a..a280a9b59 100644
--- a/desktop/src/main.ts
+++ b/desktop/src/main.ts
@@ -1,7 +1,7 @@
import { app, BrowserWindow } from "electron";
+import electronReload from "electron-reload";
+import serveNextAt from "next-electron-server";
import { initWatcher } from "./services/chokidar";
-import { initSentry } from "./services/sentry";
-import { getOptOutOfCrashReports } from "./services/userPreference";
import { isDev } from "./utils/common";
import { addAllowOriginHeader } from "./utils/cors";
import { createWindow } from "./utils/createWindow";
@@ -16,9 +16,7 @@ import {
handleUpdates,
logSystemInfo,
setupMacWindowOnDockIconClick,
- setupMainHotReload,
setupMainMenu,
- setupNextElectronServe,
setupTrayItem,
} from "./utils/main";
import { setupMainProcessStatsLogger } from "./utils/processStats";
@@ -29,8 +27,6 @@ let appIsQuitting = false;
let updateIsAvailable = false;
-let optedOutOfCrashReports = false;
-
export const isAppQuitting = (): boolean => {
return appIsQuitting;
};
@@ -42,22 +38,48 @@ export const setIsAppQuitting = (value: boolean): void => {
export const isUpdateAvailable = (): boolean => {
return updateIsAvailable;
};
+
export const setIsUpdateAvailable = (value: boolean): void => {
updateIsAvailable = value;
};
-export const hasOptedOutOfCrashReports = (): boolean => {
- return optedOutOfCrashReports;
+/**
+ * Hot reload the main process if anything changes in the source directory that
+ * we're running from.
+ *
+ * In particular, this gets triggered when the `tsc -w` rebuilds JS files in the
+ * `app/` directory when we change the TS files in the `src/` directory.
+ */
+const setupMainHotReload = () => {
+ if (isDev) {
+ electronReload(__dirname, {});
+ }
};
-export const updateOptOutOfCrashReports = (value: boolean): void => {
- optedOutOfCrashReports = value;
+/**
+ * The URL where the renderer HTML is being served from.
+ */
+export const rendererURL = "next://app";
+
+/**
+ * next-electron-server allows up to directly use the output of `next build` in
+ * production mode and `next dev` in development mode, whilst keeping the rest
+ * of our code the same.
+ *
+ * It uses protocol handlers to serve files from the "next://app" protocol
+ *
+ * - In development this is proxied to http://localhost:3000
+ * - In production it serves files from the `/out` directory
+ *
+ * For more details, see this comparison:
+ * https://github.com/HaNdTriX/next-electron-server/issues/5
+ */
+const setupRendererServer = () => {
+ serveNextAt(rendererURL);
};
setupMainHotReload();
-
-setupNextElectronServe();
-
+setupRendererServer();
setupLogging(isDev);
const gotTheLock = app.requestSingleInstanceLock();
@@ -83,11 +105,6 @@ if (!gotTheLock) {
app.on("ready", async () => {
logSystemInfo();
setupMainProcessStatsLogger();
- const hasOptedOutOfCrashReports = getOptOutOfCrashReports();
- updateOptOutOfCrashReports(hasOptedOutOfCrashReports);
- if (!hasOptedOutOfCrashReports) {
- initSentry();
- }
mainWindow = await createWindow();
const tray = setupTrayItem(mainWindow);
const watcher = initWatcher(mainWindow);
diff --git a/desktop/src/preload.ts b/desktop/src/preload.ts
index af4ef3222..a602e76bb 100644
--- a/desktop/src/preload.ts
+++ b/desktop/src/preload.ts
@@ -8,12 +8,10 @@ import { computeImageEmbedding, computeTextEmbedding } from "./api/clip";
import {
getAppVersion,
getPlatform,
- getSentryUserID,
logToDisk,
openDirectory,
openLogDirectory,
selectDirectory,
- updateOptOutOfCrashReports,
} from "./api/common";
import { clearElectronStore } from "./api/electronStore";
import {
@@ -61,13 +59,11 @@ import {
updateWatchMappingSyncedFiles,
} from "./api/watch";
import { setupLogging } from "./utils/logging";
-import { fixHotReloadNext12 } from "./utils/preload";
import {
logRendererProcessMemoryUsage,
setupRendererProcessStatsLogger,
} from "./utils/processStats";
-fixHotReloadNext12();
setupLogging();
setupRendererProcessStatsLogger();
@@ -108,7 +104,6 @@ windowObject["ElectronAPIs"] = {
registerUpdateEventListener,
updateAndRestart,
skipAppUpdate,
- getSentryUserID,
getAppVersion,
runFFmpegCmd,
muteUpdateNotification,
@@ -120,7 +115,6 @@ windowObject["ElectronAPIs"] = {
deleteFolder,
rename,
deleteFile,
- updateOptOutOfCrashReports,
computeImageEmbedding,
computeTextEmbedding,
getPlatform,
diff --git a/desktop/src/services/appUpdater.ts b/desktop/src/services/appUpdater.ts
index c6af2541a..2ddcef704 100644
--- a/desktop/src/services/appUpdater.ts
+++ b/desktop/src/services/appUpdater.ts
@@ -25,7 +25,7 @@ export function setupAutoUpdater(mainWindow: BrowserWindow) {
checkForUpdateAndNotify(mainWindow);
setInterval(
() => checkForUpdateAndNotify(mainWindow),
- ONE_DAY_IN_MICROSECOND
+ ONE_DAY_IN_MICROSECOND,
);
}
@@ -47,7 +47,7 @@ async function checkForUpdateAndNotify(mainWindow: BrowserWindow) {
if (
compareVersions(
updateCheckResult.updateInfo.version,
- app.getVersion()
+ app.getVersion(),
) <= 0
) {
log.debug("already at latest version");
@@ -60,7 +60,7 @@ async function checkForUpdateAndNotify(mainWindow: BrowserWindow) {
) {
log.info(
"user chose to skip version ",
- updateCheckResult.updateInfo.version
+ updateCheckResult.updateInfo.version,
);
return;
}
@@ -70,7 +70,7 @@ async function checkForUpdateAndNotify(mainWindow: BrowserWindow) {
isPlatform("mac") &&
compareVersions(
updateCheckResult.updateInfo.version,
- desktopCutoffVersion
+ desktopCutoffVersion,
) > 0
) {
log.debug("auto update not possible due to key change");
@@ -91,7 +91,7 @@ async function checkForUpdateAndNotify(mainWindow: BrowserWindow) {
) {
log.info(
"user chose to mute update notification for version ",
- updateCheckResult.updateInfo.version
+ updateCheckResult.updateInfo.version,
);
return;
}
@@ -102,7 +102,7 @@ async function checkForUpdateAndNotify(mainWindow: BrowserWindow) {
autoUpdatable: true,
version: updateCheckResult.updateInfo.version,
}),
- FIVE_MIN_IN_MICROSECOND
+ FIVE_MIN_IN_MICROSECOND,
);
});
autoUpdater.on("error", (error) => {
@@ -152,7 +152,7 @@ async function getDesktopCutoffVersion() {
function showUpdateDialog(
mainWindow: BrowserWindow,
- updateInfo: AppUpdateInfo
+ updateInfo: AppUpdateInfo,
) {
mainWindow.webContents.send("show-update-dialog", updateInfo);
}
diff --git a/desktop/src/services/clipService.ts b/desktop/src/services/clipService.ts
index 9e3a6a5b0..4a808d7a4 100644
--- a/desktop/src/services/clipService.ts
+++ b/desktop/src/services/clipService.ts
@@ -103,7 +103,7 @@ export async function getClipImageModelPath(type: "ggml" | "onnx") {
log.info("clip image model not found, downloading");
imageModelDownloadInProgress = downloadModel(
modelSavePath,
- IMAGE_MODEL_DOWNLOAD_URL[type]
+ IMAGE_MODEL_DOWNLOAD_URL[type],
);
await imageModelDownloadInProgress;
} else {
@@ -111,11 +111,11 @@ export async function getClipImageModelPath(type: "ggml" | "onnx") {
if (localFileSize !== IMAGE_MODEL_SIZE_IN_BYTES[type]) {
log.info(
"clip image model size mismatch, downloading again got:",
- localFileSize
+ localFileSize,
);
imageModelDownloadInProgress = downloadModel(
modelSavePath,
- IMAGE_MODEL_DOWNLOAD_URL[type]
+ IMAGE_MODEL_DOWNLOAD_URL[type],
);
await imageModelDownloadInProgress;
}
@@ -150,7 +150,7 @@ export async function getClipTextModelPath(type: "ggml" | "onnx") {
if (localFileSize !== TEXT_MODEL_SIZE_IN_BYTES[type]) {
log.info(
"clip text model size mismatch, downloading again got:",
- localFileSize
+ localFileSize,
);
textModelDownloadInProgress = true;
downloadModel(modelSavePath, TEXT_MODEL_DOWNLOAD_URL[type])
@@ -212,7 +212,7 @@ function getTokenizer() {
export async function computeImageEmbedding(
model: Model,
- inputFilePath: string
+ inputFilePath: string,
): Promise {
if (!existsSync(inputFilePath)) {
throw Error(CustomErrors.INVALID_FILE_PATH);
@@ -227,7 +227,7 @@ export async function computeImageEmbedding(
}
export async function computeGGMLImageEmbedding(
- inputFilePath: string
+ inputFilePath: string,
): Promise {
try {
const clipModelPath = await getClipImageModelPath("ggml");
@@ -263,7 +263,7 @@ export async function computeGGMLImageEmbedding(
}
export async function computeONNXImageEmbedding(
- inputFilePath: string
+ inputFilePath: string,
): Promise {
try {
const imageSession = await getOnnxImageSession();
@@ -277,7 +277,7 @@ export async function computeONNXImageEmbedding(
log.info(
`onnx image embedding time: ${Date.now() - t1} ms (prep:${
t2 - t1
- } ms, extraction: ${Date.now() - t2} ms)`
+ } ms, extraction: ${Date.now() - t2} ms)`,
);
const imageEmbedding = results["output"].data; // Float32Array
return normalizeEmbedding(imageEmbedding);
@@ -289,7 +289,7 @@ export async function computeONNXImageEmbedding(
export async function computeTextEmbedding(
model: Model,
- text: string
+ text: string,
): Promise {
if (model === Model.GGML_CLIP) {
return await computeGGMLTextEmbedding(text);
@@ -299,7 +299,7 @@ export async function computeTextEmbedding(
}
export async function computeGGMLTextEmbedding(
- text: string
+ text: string,
): Promise {
try {
const clipModelPath = await getClipTextModelPath("ggml");
@@ -339,7 +339,7 @@ export async function computeGGMLTextEmbedding(
}
export async function computeONNXTextEmbedding(
- text: string
+ text: string,
): Promise {
try {
const imageSession = await getOnnxTextSession();
@@ -354,7 +354,7 @@ export async function computeONNXTextEmbedding(
log.info(
`onnx text embedding time: ${Date.now() - t1} ms (prep:${
t2 - t1
- } ms, extraction: ${Date.now() - t2} ms)`
+ } ms, extraction: ${Date.now() - t2} ms)`,
);
const textEmbedding = results["output"].data; // Float32Array
return normalizeEmbedding(textEmbedding);
@@ -444,7 +444,7 @@ async function getRGBData(inputFilePath: string) {
export const computeClipMatchScore = async (
imageEmbedding: Float32Array,
- textEmbedding: Float32Array
+ textEmbedding: Float32Array,
) => {
if (imageEmbedding.length !== textEmbedding.length) {
throw Error("imageEmbedding and textEmbedding length mismatch");
diff --git a/desktop/src/services/diskCache.ts b/desktop/src/services/diskCache.ts
index be9199cbf..6861bba9f 100644
--- a/desktop/src/services/diskCache.ts
+++ b/desktop/src/services/diskCache.ts
@@ -11,7 +11,7 @@ const DEFAULT_CACHE_LIMIT = 1000 * 1000 * 1000; // 1GB
export class DiskCache implements LimitedCache {
constructor(
private cacheBucketDir: string,
- private cacheLimit = DEFAULT_CACHE_LIMIT
+ private cacheLimit = DEFAULT_CACHE_LIMIT,
) {}
async put(cacheKey: string, response: Response): Promise {
@@ -19,13 +19,13 @@ export class DiskCache implements LimitedCache {
await writeStream(cachePath, response.body);
DiskLRUService.enforceCacheSizeLimit(
this.cacheBucketDir,
- this.cacheLimit
+ this.cacheLimit,
);
}
async match(
cacheKey: string,
- { sizeInBytes }: { sizeInBytes?: number } = {}
+ { sizeInBytes }: { sizeInBytes?: number } = {},
): Promise {
const cachePath = path.join(this.cacheBucketDir, cacheKey);
if (existsSync(cachePath)) {
@@ -33,7 +33,7 @@ export class DiskCache implements LimitedCache {
if (sizeInBytes && fileStats.size !== sizeInBytes) {
logError(
Error(),
- "Cache key exists but size does not match. Deleting cache key."
+ "Cache key exists but size does not match. Deleting cache key.",
);
unlink(cachePath).catch((e) => {
if (e.code === "ENOENT") return;
@@ -47,14 +47,14 @@ export class DiskCache implements LimitedCache {
// add fallback for old cache keys
const oldCachePath = getOldAssetCachePath(
this.cacheBucketDir,
- cacheKey
+ cacheKey,
);
if (existsSync(oldCachePath)) {
const fileStats = await stat(oldCachePath);
if (sizeInBytes && fileStats.size !== sizeInBytes) {
logError(
Error(),
- "Old cache key exists but size does not match. Deleting cache key."
+ "Old cache key exists but size does not match. Deleting cache key.",
);
unlink(oldCachePath).catch((e) => {
if (e.code === "ENOENT") return;
diff --git a/desktop/src/services/diskLRU.ts b/desktop/src/services/diskLRU.ts
index cf10b7351..44b05c099 100644
--- a/desktop/src/services/diskLRU.ts
+++ b/desktop/src/services/diskLRU.ts
@@ -60,7 +60,7 @@ class DiskLRUService {
if (e.code !== "ENOENT") {
logError(
e,
- "Failed to evict least recently used"
+ "Failed to evict least recently used",
);
}
// ignoring the error, as it would get retried on the next run
@@ -77,7 +77,7 @@ class DiskLRUService {
private async findLeastRecentlyUsed(
dir: string,
- result?: LeastRecentlyUsedResult
+ result?: LeastRecentlyUsedResult,
): Promise {
result = result || { atime: new Date(), path: "" };
diff --git a/desktop/src/services/ffmpeg.ts b/desktop/src/services/ffmpeg.ts
index 6a76169b7..e0a915790 100644
--- a/desktop/src/services/ffmpeg.ts
+++ b/desktop/src/services/ffmpeg.ts
@@ -24,7 +24,7 @@ export async function runFFmpegCmd(
cmd: string[],
inputFilePath: string,
outputFileName: string,
- dontTimeout = false
+ dontTimeout = false,
) {
let tempOutputFilePath: string;
try {
@@ -49,7 +49,7 @@ export async function runFFmpegCmd(
} else {
await promiseWithTimeout(
execAsync(escapedCmd),
- FFMPEG_EXECUTION_WAIT_TIME
+ FFMPEG_EXECUTION_WAIT_TIME,
);
}
if (!existsSync(tempOutputFilePath)) {
@@ -59,7 +59,7 @@ export async function runFFmpegCmd(
"ffmpeg command execution time ",
escapedCmd,
Date.now() - startTime,
- "ms"
+ "ms",
);
const outputFile = await readFile(tempOutputFilePath);
@@ -87,7 +87,7 @@ export async function deleteTempFile(tempFilePath: string) {
if (!tempFilePath.startsWith(tempDirPath)) {
logErrorSentry(
Error("not a temp file"),
- "tried to delete a non temp file"
+ "tried to delete a non temp file",
);
}
rmSync(tempFilePath, { force: true });
diff --git a/desktop/src/services/fs.ts b/desktop/src/services/fs.ts
index cbbe06146..06d413c1f 100644
--- a/desktop/src/services/fs.ts
+++ b/desktop/src/services/fs.ts
@@ -3,10 +3,11 @@ import StreamZip from "node-stream-zip";
import path from "path";
import * as fs from "promise-fs";
import { Readable } from "stream";
-import { FILE_STREAM_CHUNK_SIZE } from "../config";
import { ElectronFile } from "../types";
import { logError } from "./logging";
+const FILE_STREAM_CHUNK_SIZE: number = 4 * 1024 * 1024;
+
// https://stackoverflow.com/a/63111390
export const getDirFilePaths = async (dirPath: string) => {
if (!(await fs.stat(dirPath)).isDirectory()) {
@@ -37,7 +38,7 @@ export const getFileStream = async (filePath: string) => {
buff,
0,
FILE_STREAM_CHUNK_SIZE,
- offset
+ offset,
)) as unknown as number;
offset += bytesRead;
if (bytesRead === 0) {
@@ -102,7 +103,7 @@ export const getValidPaths = (paths: string[]) => {
export const getZipFileStream = async (
zip: StreamZip.StreamZipAsync,
- filePath: string
+ filePath: string,
) => {
const stream = await zip.stream(filePath);
const done = {
@@ -203,7 +204,7 @@ export async function isFolder(dirPath: string) {
}
export const convertBrowserStreamToNode = (
- fileStream: ReadableStream
+ fileStream: ReadableStream,
) => {
const reader = fileStream.getReader();
const rs = new Readable();
@@ -228,7 +229,7 @@ export const convertBrowserStreamToNode = (
export async function writeNodeStream(
filePath: string,
- fileStream: NodeJS.ReadableStream
+ fileStream: NodeJS.ReadableStream,
) {
const writeable = fs.createWriteStream(filePath);
@@ -251,7 +252,7 @@ export async function writeNodeStream(
export async function writeStream(
filePath: string,
- fileStream: ReadableStream
+ fileStream: ReadableStream,
) {
const readable = convertBrowserStreamToNode(fileStream);
await writeNodeStream(filePath, readable);
@@ -266,7 +267,7 @@ export async function readTextFile(filePath: string) {
export async function moveFile(
sourcePath: string,
- destinationPath: string
+ destinationPath: string,
): Promise {
if (!existsSync(sourcePath)) {
throw new Error("File does not exist");
diff --git a/desktop/src/services/imageProcessor.ts b/desktop/src/services/imageProcessor.ts
index d9b3e45f0..cb6c7416d 100644
--- a/desktop/src/services/imageProcessor.ts
+++ b/desktop/src/services/imageProcessor.ts
@@ -80,7 +80,7 @@ function getImageMagickStaticPath() {
export async function convertToJPEG(
fileData: Uint8Array,
- filename: string
+ filename: string,
): Promise {
let tempInputFilePath: string;
let tempOutputFilePath: string;
@@ -96,7 +96,7 @@ export async function convertToJPEG(
throw new Error("heic convert output file not found");
}
const convertedFileData = new Uint8Array(
- await readFile(tempOutputFilePath)
+ await readFile(tempOutputFilePath),
);
return convertedFileData;
} catch (e) {
@@ -118,11 +118,11 @@ export async function convertToJPEG(
async function runConvertCommand(
tempInputFilePath: string,
- tempOutputFilePath: string
+ tempOutputFilePath: string,
) {
const convertCmd = constructConvertCommand(
tempInputFilePath,
- tempOutputFilePath
+ tempOutputFilePath,
);
const escapedCmd = shellescape(convertCmd);
log.info("running convert command: " + escapedCmd);
@@ -131,7 +131,7 @@ async function runConvertCommand(
function constructConvertCommand(
tempInputFilePath: string,
- tempOutputFilePath: string
+ tempOutputFilePath: string,
) {
let convertCmd: string[];
if (isPlatform("mac")) {
@@ -157,7 +157,7 @@ function constructConvertCommand(
return tempOutputFilePath;
}
return cmdPart;
- }
+ },
);
} else {
throw Error(CustomErrors.INVALID_OS(process.platform));
@@ -168,7 +168,7 @@ function constructConvertCommand(
export async function generateImageThumbnail(
inputFilePath: string,
width: number,
- maxSize: number
+ maxSize: number,
): Promise {
let tempOutputFilePath: string;
let quality = MAX_QUALITY;
@@ -180,7 +180,7 @@ export async function generateImageThumbnail(
inputFilePath,
tempOutputFilePath,
width,
- quality
+ quality,
);
if (!existsSync(tempOutputFilePath)) {
@@ -206,14 +206,14 @@ async function runThumbnailGenerationCommand(
inputFilePath: string,
tempOutputFilePath: string,
maxDimension: number,
- quality: number
+ quality: number,
) {
const thumbnailGenerationCmd: string[] =
constructThumbnailGenerationCommand(
inputFilePath,
tempOutputFilePath,
maxDimension,
- quality
+ quality,
);
const escapedCmd = shellescape(thumbnailGenerationCmd);
log.info("running thumbnail generation command: " + escapedCmd);
@@ -223,7 +223,7 @@ function constructThumbnailGenerationCommand(
inputFilePath: string,
tempOutputFilePath: string,
maxDimension: number,
- quality: number
+ quality: number,
) {
let thumbnailGenerationCmd: string[];
if (isPlatform("mac")) {
@@ -242,7 +242,7 @@ function constructThumbnailGenerationCommand(
return quality.toString();
}
return cmdPart;
- }
+ },
);
} else if (isPlatform("linux")) {
thumbnailGenerationCmd =
@@ -259,13 +259,13 @@ function constructThumbnailGenerationCommand(
if (cmdPart.includes(SAMPLE_SIZE_PLACEHOLDER)) {
return cmdPart.replaceAll(
SAMPLE_SIZE_PLACEHOLDER,
- (2 * maxDimension).toString()
+ (2 * maxDimension).toString(),
);
}
if (cmdPart.includes(MAX_DIMENSION_PLACEHOLDER)) {
return cmdPart.replaceAll(
MAX_DIMENSION_PLACEHOLDER,
- maxDimension.toString()
+ maxDimension.toString(),
);
}
if (cmdPart === QUALITY_PLACEHOLDER) {
diff --git a/desktop/src/services/logging.ts b/desktop/src/services/logging.ts
index fa82492bc..bcbacd9f5 100644
--- a/desktop/src/services/logging.ts
+++ b/desktop/src/services/logging.ts
@@ -12,11 +12,3 @@ export function openLogDirectory() {
export function logError(error: Error, message: string, info?: string): void {
ipcRenderer.invoke("log-error", error, message, info);
}
-
-export function getSentryUserID(): Promise {
- return ipcRenderer.invoke("get-sentry-id");
-}
-
-export function updateOptOutOfCrashReports(optOut: boolean) {
- return ipcRenderer.invoke("update-opt-out-crash-reports", optOut);
-}
diff --git a/desktop/src/services/sentry.ts b/desktop/src/services/sentry.ts
index 7adfcc255..4c5573152 100644
--- a/desktop/src/services/sentry.ts
+++ b/desktop/src/services/sentry.ts
@@ -1,68 +1,18 @@
-import * as Sentry from "@sentry/electron/dist/main";
-import { RELEASE_VERSION, SENTRY_DSN } from "../config";
-import { hasOptedOutOfCrashReports } from "../main";
-import { keysStore } from "../stores/keys.store";
import { isDev } from "../utils/common";
-import { makeID } from "../utils/logging";
import { logToDisk } from "./logging";
-const ENV_DEVELOPMENT = "development";
-
-const isDEVSentryENV = () =>
- process.env.NEXT_PUBLIC_SENTRY_ENV === ENV_DEVELOPMENT;
-
-export function initSentry(): void {
- Sentry.init({
- dsn: SENTRY_DSN,
- release: RELEASE_VERSION,
- environment: isDev ? "development" : "production",
- });
- Sentry.setUser({ id: getSentryUserID() });
-}
-
+/** Deprecated, but no alternative yet */
export function logErrorSentry(
error: any,
msg: string,
- info?: Record
+ info?: Record,
) {
- const err = errorWithContext(error, msg);
logToDisk(
`error: ${error?.name} ${error?.message} ${
error?.stack
- } msg: ${msg} info: ${JSON.stringify(info)}`
+ } msg: ${msg} info: ${JSON.stringify(info)}`,
);
- if (isDEVSentryENV()) {
+ if (isDev) {
console.log(error, { msg, info });
}
- if (hasOptedOutOfCrashReports()) {
- return;
- }
- Sentry.captureException(err, {
- level: Sentry.Severity.Info,
- user: { id: getSentryUserID() },
- contexts: {
- ...(info && {
- info: info,
- }),
- rootCause: { message: error?.message },
- },
- });
-}
-
-function errorWithContext(originalError: Error, context: string) {
- const errorWithContext = new Error(context);
- errorWithContext.stack =
- errorWithContext.stack.split("\n").slice(2, 4).join("\n") +
- "\n" +
- originalError.stack;
- return errorWithContext;
-}
-
-export function getSentryUserID() {
- let anonymizeUserID = keysStore.get("AnonymizeUserID")?.id;
- if (!anonymizeUserID) {
- anonymizeUserID = makeID(6);
- keysStore.set("AnonymizeUserID", { id: anonymizeUserID });
- }
- return anonymizeUserID;
}
diff --git a/desktop/src/services/upload.ts b/desktop/src/services/upload.ts
index e9db576a1..38a628c25 100644
--- a/desktop/src/services/upload.ts
+++ b/desktop/src/services/upload.ts
@@ -7,7 +7,7 @@ import { getValidPaths, getZipFileStream } from "./fs";
export const getSavedFilePaths = (type: FILE_PATH_TYPE) => {
const paths =
getValidPaths(
- uploadStatusStore.get(FILE_PATH_KEYS[type]) as string[]
+ uploadStatusStore.get(FILE_PATH_KEYS[type]) as string[],
) ?? [];
setToUploadFiles(type, paths);
@@ -17,7 +17,7 @@ export const getSavedFilePaths = (type: FILE_PATH_TYPE) => {
export async function getZipEntryAsElectronFile(
zipName: string,
zip: StreamZip.StreamZipAsync,
- entry: StreamZip.ZipEntry
+ entry: StreamZip.ZipEntry,
): Promise {
return {
path: path
diff --git a/desktop/src/services/userPreference.ts b/desktop/src/services/userPreference.ts
index 1c20e64da..e3c6db290 100644
--- a/desktop/src/services/userPreference.ts
+++ b/desktop/src/services/userPreference.ts
@@ -24,14 +24,6 @@ export function setMuteUpdateNotificationVersion(version: string) {
userPreferencesStore.set("muteUpdateNotificationVersion", version);
}
-export function getOptOutOfCrashReports() {
- return userPreferencesStore.get("optOutOfCrashReports") ?? false;
-}
-
-export function setOptOutOfCrashReports(optOut: boolean) {
- userPreferencesStore.set("optOutOfCrashReports", optOut);
-}
-
export function clearSkipAppVersion() {
userPreferencesStore.delete("skipAppVersion");
}
diff --git a/desktop/src/stores/userPreferences.store.ts b/desktop/src/stores/userPreferences.store.ts
index 546ca743e..e6fec425a 100644
--- a/desktop/src/stores/userPreferences.store.ts
+++ b/desktop/src/stores/userPreferences.store.ts
@@ -11,9 +11,6 @@ const userPreferencesSchema: Schema = {
muteUpdateNotificationVersion: {
type: "string",
},
- optOutOfCrashReports: {
- type: "boolean",
- },
customCacheDirectory: {
type: "string",
},
diff --git a/desktop/src/types/cache.ts b/desktop/src/types/cache.ts
index fde7dc038..112716eea 100644
--- a/desktop/src/types/cache.ts
+++ b/desktop/src/types/cache.ts
@@ -1,7 +1,7 @@
export interface LimitedCache {
match: (
key: string,
- options?: { sizeInBytes?: number }
+ options?: { sizeInBytes?: number },
) => Promise;
put: (key: string, data: Response) => Promise;
delete: (key: string) => Promise;
diff --git a/desktop/src/types/index.ts b/desktop/src/types/index.ts
index cd3ea8546..208983826 100644
--- a/desktop/src/types/index.ts
+++ b/desktop/src/types/index.ts
@@ -58,7 +58,6 @@ export interface UserPreferencesType {
hideDockIcon: boolean;
skipAppVersion: string;
muteUpdateNotificationVersion: string;
- optOutOfCrashReports: boolean;
customCacheDirectory: string;
}
diff --git a/desktop/src/utils/clip-bpe-ts/README.md b/desktop/src/utils/clip-bpe-ts/README.md
index dd171eb42..ee052eb41 100644
--- a/desktop/src/utils/clip-bpe-ts/README.md
+++ b/desktop/src/utils/clip-bpe-ts/README.md
@@ -1,20 +1,21 @@
# CLIP Byte Pair Encoding JavaScript Port
+
A JavaScript port of [OpenAI's CLIP byte-pair-encoding tokenizer](https://github.com/openai/CLIP/blob/3bee28119e6b28e75b82b811b87b56935314e6a5/clip/simple_tokenizer.py).
```js
import Tokenizer from "https://deno.land/x/clip_bpe@v0.0.6/mod.js";
let t = new Tokenizer();
-t.encode("hello") // [3306]
-t.encode("magnificent") // [10724]
-t.encode("magnificently") // [9725, 2922]
-t.decode(t.encode("HELLO")) // "hello "
-t.decode(t.encode("abc123")) // "abc 1 2 3 "
-t.decode(st.encode("let's see here")) // "let 's see here "
-t.encode("hello world!") // [3306, 1002, 256]
+t.encode("hello"); // [3306]
+t.encode("magnificent"); // [10724]
+t.encode("magnificently"); // [9725, 2922]
+t.decode(t.encode("HELLO")); // "hello "
+t.decode(t.encode("abc123")); // "abc 1 2 3 "
+t.decode(st.encode("let's see here")); // "let 's see here "
+t.encode("hello world!"); // [3306, 1002, 256]
// to encode for CLIP (trims to maximum of 77 tokens and adds start and end token, and pads with zeros if less than 77 tokens):
-t.encodeForCLIP("hello world!") // [49406,3306,1002,256,49407,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
+t.encodeForCLIP("hello world!"); // [49406,3306,1002,256,49407,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
```
This encoder/decoder behaves differently to the the GPT-2/3 tokenizer (JavaScript version of that [here](https://github.com/latitudegames/GPT-3-Encoder)). For example, it doesn't preserve capital letters, as shown above.
diff --git a/desktop/src/utils/clip-bpe-ts/mod.ts b/desktop/src/utils/clip-bpe-ts/mod.ts
index 880d8b438..6cdf246f7 100644
--- a/desktop/src/utils/clip-bpe-ts/mod.ts
+++ b/desktop/src/utils/clip-bpe-ts/mod.ts
@@ -75,7 +75,7 @@ export default class {
constructor() {
this.byteEncoder = bytesToUnicode();
this.byteDecoder = Object.fromEntries(
- Object.entries(this.byteEncoder).map(([k, v]) => [v, Number(k)])
+ Object.entries(this.byteEncoder).map(([k, v]) => [v, Number(k)]),
);
let merges = bpeVocabData.text.split("\n");
merges = merges.slice(1, 49152 - 256 - 2 + 1);
@@ -346,10 +346,10 @@ export default class {
vocab.push("<|startoftext|>", "<|endoftext|>");
this.encoder = Object.fromEntries(vocab.map((v, i) => [v, i]));
this.decoder = Object.fromEntries(
- Object.entries(this.encoder).map(([k, v]) => [v, k])
+ Object.entries(this.encoder).map(([k, v]) => [v, k]),
);
this.bpeRanks = Object.fromEntries(
- mergedMerges.map((v, i) => [v.join("·😎·"), i])
+ mergedMerges.map((v, i) => [v.join("·😎·"), i]),
); // ·😎· because js doesn't yet have tuples
this.cache = {
"<|startoftext|>": "<|startoftext|>",
@@ -436,7 +436,7 @@ export default class {
bpeTokens.push(
...this.bpe(token)
.split(" ")
- .map((bpeToken: string) => this.encoder[bpeToken])
+ .map((bpeToken: string) => this.encoder[bpeToken]),
);
}
return bpeTokens;
diff --git a/desktop/src/utils/common/index.ts b/desktop/src/utils/common/index.ts
index 61880bcda..e970dfec4 100644
--- a/desktop/src/utils/common/index.ts
+++ b/desktop/src/utils/common/index.ts
@@ -4,7 +4,7 @@ export const isDev = !app.isPackaged;
export const promiseWithTimeout = async (
request: Promise,
- timeout: number
+ timeout: number,
): Promise => {
const timeoutRef: {
current: NodeJS.Timeout;
@@ -12,7 +12,7 @@ export const promiseWithTimeout = async (
const rejectOnTimeout = new Promise((_, reject) => {
timeoutRef.current = setTimeout(
() => reject(Error(CustomErrors.WAIT_TIME_EXCEEDED)),
- timeout
+ timeout,
);
});
const requestWithTimeOutCancellation = async () => {
diff --git a/desktop/src/utils/cors.ts b/desktop/src/utils/cors.ts
index bec656061..25f76211a 100644
--- a/desktop/src/utils/cors.ts
+++ b/desktop/src/utils/cors.ts
@@ -16,6 +16,6 @@ export function addAllowOriginHeader(mainWindow: BrowserWindow) {
callback({
responseHeaders: details.responseHeaders,
});
- }
+ },
);
}
diff --git a/desktop/src/utils/createWindow.ts b/desktop/src/utils/createWindow.ts
index b9e6a5b47..c7d44e6c9 100644
--- a/desktop/src/utils/createWindow.ts
+++ b/desktop/src/utils/createWindow.ts
@@ -1,8 +1,7 @@
import { app, BrowserWindow, nativeImage } from "electron";
import ElectronLog from "electron-log";
import * as path from "path";
-import { PROD_HOST_URL } from "../config";
-import { isAppQuitting } from "../main";
+import { isAppQuitting, rendererURL } from "../main";
import autoLauncher from "../services/autoLauncher";
import { logErrorSentry } from "../services/sentry";
import { getHideDockIconPreference } from "../services/userPreference";
@@ -41,21 +40,21 @@ export async function createWindow(): Promise {
if (isDev) {
splash.loadFile(`../resources/splash.html`);
- mainWindow.loadURL(PROD_HOST_URL);
+ mainWindow.loadURL(rendererURL);
// Open the DevTools.
mainWindow.webContents.openDevTools();
} else {
splash.loadURL(
- `file://${path.join(process.resourcesPath, "splash.html")}`
+ `file://${path.join(process.resourcesPath, "splash.html")}`,
);
- mainWindow.loadURL(PROD_HOST_URL);
+ mainWindow.loadURL(rendererURL);
}
mainWindow.webContents.on("did-fail-load", () => {
splash.close();
isDev
? mainWindow.loadFile(`../resources/error.html`)
: splash.loadURL(
- `file://${path.join(process.resourcesPath, "error.html")}`
+ `file://${path.join(process.resourcesPath, "error.html")}`,
);
mainWindow.maximize();
mainWindow.show();
@@ -76,7 +75,7 @@ export async function createWindow(): Promise {
logErrorSentry(
Error("render-process-gone"),
"webContents event render-process-gone",
- { details }
+ { details },
);
ElectronLog.log("webContents event render-process-gone", details);
});
diff --git a/desktop/src/utils/error.ts b/desktop/src/utils/error.ts
index aff17edb6..1922045a2 100644
--- a/desktop/src/utils/error.ts
+++ b/desktop/src/utils/error.ts
@@ -9,7 +9,7 @@ export const parseExecError = (err: any) => {
if (errMessage.includes("Bad CPU type in executable")) {
return CustomErrors.UNSUPPORTED_PLATFORM(
process.platform,
- process.arch
+ process.arch,
);
} else {
return errMessage;
diff --git a/desktop/src/utils/ipcComms.ts b/desktop/src/utils/ipcComms.ts
index 84b80fae1..eec644aeb 100644
--- a/desktop/src/utils/ipcComms.ts
+++ b/desktop/src/utils/ipcComms.ts
@@ -10,7 +10,6 @@ import {
Tray,
} from "electron";
import path from "path";
-import { updateOptOutOfCrashReports } from "../main";
import {
getAppVersion,
muteUpdateNotification,
@@ -27,11 +26,10 @@ import {
convertToJPEG,
generateImageThumbnail,
} from "../services/imageProcessor";
-import { getSentryUserID, logErrorSentry } from "../services/sentry";
+import { logErrorSentry } from "../services/sentry";
import {
getCustomCacheDirectory,
setCustomCacheDirectory,
- setOptOutOfCrashReports,
} from "../services/userPreference";
import { getPlatform } from "./common/platform";
import { createWindow } from "./createWindow";
@@ -40,7 +38,7 @@ import { generateTempFilePath } from "./temp";
export default function setupIpcComs(
tray: Tray,
mainWindow: BrowserWindow,
- watcher: chokidar.FSWatcher
+ watcher: chokidar.FSWatcher,
): void {
ipcMain.handle("select-dir", async () => {
const result = await dialog.showOpenDialog({
@@ -146,9 +144,6 @@ export default function setupIpcComs(
ipcMain.on("mute-update-notification", (_, version) => {
muteUpdateNotification(version);
});
- ipcMain.handle("get-sentry-id", () => {
- return getSentryUserID();
- });
ipcMain.handle("get-app-version", () => {
return getAppVersion();
@@ -161,9 +156,9 @@ export default function setupIpcComs(
cmd,
inputFilePath,
outputFileName,
- dontTimeout
+ dontTimeout,
);
- }
+ },
);
ipcMain.handle("get-temp-file-path", (_, formatSuffix) => {
return generateTempFilePath(formatSuffix);
@@ -176,13 +171,9 @@ export default function setupIpcComs(
"generate-image-thumbnail",
(_, fileData, maxDimension, maxSize) => {
return generateImageThumbnail(fileData, maxDimension, maxSize);
- }
+ },
);
- ipcMain.handle("update-opt-out-crash-reports", (_, optOut) => {
- setOptOutOfCrashReports(optOut);
- updateOptOutOfCrashReports(optOut);
- });
ipcMain.handle("compute-image-embedding", (_, model, inputFilePath) => {
return computeImageEmbedding(model, inputFilePath);
});
diff --git a/desktop/src/utils/logging.ts b/desktop/src/utils/logging.ts
index c843642f8..351a1aef8 100644
--- a/desktop/src/utils/logging.ts
+++ b/desktop/src/utils/logging.ts
@@ -1,9 +1,8 @@
import log from "electron-log";
-import { LOG_FILENAME, MAX_LOG_SIZE } from "../config";
export function setupLogging(isDev?: boolean) {
- log.transports.file.fileName = LOG_FILENAME;
- log.transports.file.maxSize = MAX_LOG_SIZE;
+ log.transports.file.fileName = "ente.log";
+ log.transports.file.maxSize = 50 * 1024 * 1024; // 50MB;
if (!isDev) {
log.transports.console.level = false;
}
@@ -11,22 +10,9 @@ export function setupLogging(isDev?: boolean) {
"[{y}-{m}-{d}T{h}:{i}:{s}{z}] [{level}]{scope} {text}";
}
-export function makeID(length: number) {
- let result = "";
- const characters =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
- const charactersLength = characters.length;
- for (let i = 0; i < length; i++) {
- result += characters.charAt(
- Math.floor(Math.random() * charactersLength)
- );
- }
- return result;
-}
-
export function convertBytesToHumanReadable(
bytes: number,
- precision = 2
+ precision = 2,
): string {
if (bytes === 0 || isNaN(bytes)) {
return "0 MB";
diff --git a/desktop/src/utils/main.ts b/desktop/src/utils/main.ts
index ebf466c03..569752326 100644
--- a/desktop/src/utils/main.ts
+++ b/desktop/src/utils/main.ts
@@ -1,12 +1,10 @@
import { app, BrowserWindow, Menu, nativeImage, Tray } from "electron";
import ElectronLog from "electron-log";
-import electronReload from "electron-reload";
-import serveNextAt from "next-electron-server";
import os from "os";
import path from "path";
import { existsSync } from "promise-fs";
import util from "util";
-import { PROD_HOST_URL, RENDERER_OUTPUT_DIR } from "../config";
+import { rendererURL } from "../main";
import { setupAutoUpdater } from "../services/appUpdater";
import autoLauncher from "../services/autoLauncher";
import { getHideDockIconPreference } from "../services/userPreference";
@@ -27,7 +25,7 @@ export function setupTrayItem(mainWindow: BrowserWindow) {
: "taskbar-icon.png";
const trayImgPath = path.join(
isDev ? "build" : process.resourcesPath,
- iconName
+ iconName,
);
const trayIcon = nativeImage.createFromPath(trayImgPath);
const tray = new Tray(trayIcon);
@@ -39,11 +37,22 @@ export function setupTrayItem(mainWindow: BrowserWindow) {
export function handleDownloads(mainWindow: BrowserWindow) {
mainWindow.webContents.session.on("will-download", (_, item) => {
item.setSavePath(
- getUniqueSavePath(item.getFilename(), app.getPath("downloads"))
+ getUniqueSavePath(item.getFilename(), app.getPath("downloads")),
);
});
}
+export function handleExternalLinks(mainWindow: BrowserWindow) {
+ mainWindow.webContents.setWindowOpenHandler(({ url }) => {
+ if (!url.startsWith(rendererURL)) {
+ require("electron").shell.openExternal(url);
+ return { action: "deny" };
+ } else {
+ return { action: "allow" };
+ }
+ });
+}
+
export function getUniqueSavePath(filename: string, directory: string): string {
let uniqueFileSavePath = path.join(directory, filename);
const { name: filenameWithoutExtension, ext: extension } =
@@ -76,18 +85,6 @@ export async function setupMainMenu(mainWindow: BrowserWindow) {
Menu.setApplicationMenu(await buildMenuBar(mainWindow));
}
-export function setupMainHotReload() {
- if (isDev) {
- electronReload(__dirname, {});
- }
-}
-
-export function setupNextElectronServe() {
- serveNextAt(PROD_HOST_URL, {
- outputDir: RENDERER_OUTPUT_DIR,
- });
-}
-
export async function handleDockIconHideOnAutoLaunch() {
const shouldHideDockIcon = getHideDockIconPreference();
const wasAutoLaunched = await autoLauncher.wasAutoLaunched();
@@ -110,17 +107,6 @@ export function logSystemInfo() {
ElectronLog.info({ appVersion });
}
-export function handleExternalLinks(mainWindow: BrowserWindow) {
- mainWindow.webContents.setWindowOpenHandler(({ url }) => {
- if (!url.startsWith(PROD_HOST_URL)) {
- require("electron").shell.openExternal(url);
- return { action: "deny" };
- } else {
- return { action: "allow" };
- }
- });
-}
-
export async function checkIfInstalledViaBrew() {
if (!isPlatform("mac")) {
return false;
diff --git a/desktop/src/utils/menu.ts b/desktop/src/utils/menu.ts
index 3c6a1b4e4..c86786ff6 100644
--- a/desktop/src/utils/menu.ts
+++ b/desktop/src/utils/menu.ts
@@ -64,7 +64,7 @@ export async function buildMenuBar(mainWindow: BrowserWindow): Promise