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 { label: "View Changelog", click: () => { shell.openExternal( - "https://github.com/ente-io/ente/blob/main/desktop/CHANGELOG.md" + "https://github.com/ente-io/ente/blob/main/desktop/CHANGELOG.md", ); }, }, diff --git a/desktop/src/utils/preload.ts b/desktop/src/utils/preload.ts deleted file mode 100644 index 8b36f8c3f..000000000 --- a/desktop/src/utils/preload.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { webFrame } from "electron"; - -export const fixHotReloadNext12 = () => { - webFrame.executeJavaScript(`Object.defineProperty(globalThis, 'WebSocket', { - value: new Proxy(WebSocket, { - construct: (Target, [url, protocols]) => { - if (url.endsWith('/_next/webpack-hmr')) { - // Fix the Next.js hmr client url - return new Target("ws://localhost:3000/_next/webpack-hmr", protocols) - } else { - return new Target(url, protocols) - } - } - }) - });`); -}; diff --git a/desktop/src/utils/processStats.ts b/desktop/src/utils/processStats.ts index 9f993288b..b10238eea 100644 --- a/desktop/src/utils/processStats.ts +++ b/desktop/src/utils/processStats.ts @@ -16,11 +16,11 @@ const HIGH_RENDERER_MEMORY_USAGE_THRESHOLD_IN_KILOBYTES = 1024 * 1024; // 1 GB async function logMainProcessStats() { const processMemoryInfo = await getNormalizedProcessMemoryInfo( - await process.getProcessMemoryInfo() + await process.getProcessMemoryInfo(), ); const cpuUsage = process.getCPUUsage(); const heapStatistics = getNormalizedHeapStatistics( - process.getHeapStatistics() + process.getHeapStatistics(), ); ElectronLog.log("main process stats", { @@ -42,11 +42,11 @@ async function logSpikeMainMemoryUsage() { const processMemoryInfo = await process.getProcessMemoryInfo(); const currentMemoryUsage = Math.max( processMemoryInfo.residentSet ?? 0, - processMemoryInfo.private + processMemoryInfo.private, ); const previousMemoryUsage = Math.max( previousMainProcessMemoryInfo.residentSet ?? 0, - previousMainProcessMemoryInfo.private + previousMainProcessMemoryInfo.private, ); const isSpiking = currentMemoryUsage - previousMemoryUsage >= @@ -66,7 +66,7 @@ async function logSpikeMainMemoryUsage() { await getNormalizedProcessMemoryInfo(previousMainProcessMemoryInfo); const cpuUsage = process.getCPUUsage(); const heapStatistics = getNormalizedHeapStatistics( - process.getHeapStatistics() + process.getHeapStatistics(), ); ElectronLog.log("reporting main memory usage spike", { @@ -94,12 +94,12 @@ async function logSpikeRendererMemoryUsage() { const processMemoryInfo = await process.getProcessMemoryInfo(); const currentMemoryUsage = Math.max( processMemoryInfo.residentSet ?? 0, - processMemoryInfo.private + processMemoryInfo.private, ); const previousMemoryUsage = Math.max( previousRendererProcessMemoryInfo.private, - previousRendererProcessMemoryInfo.residentSet ?? 0 + previousRendererProcessMemoryInfo.residentSet ?? 0, ); const isSpiking = currentMemoryUsage - previousMemoryUsage >= @@ -117,11 +117,11 @@ async function logSpikeRendererMemoryUsage() { await getNormalizedProcessMemoryInfo(processMemoryInfo); const normalizedPreviousProcessMemoryInfo = await getNormalizedProcessMemoryInfo( - previousRendererProcessMemoryInfo + previousRendererProcessMemoryInfo, ); const cpuUsage = process.getCPUUsage(); const heapStatistics = getNormalizedHeapStatistics( - process.getHeapStatistics() + process.getHeapStatistics(), ); ElectronLog.log("reporting renderer memory usage spike", { @@ -140,11 +140,11 @@ async function logSpikeRendererMemoryUsage() { async function logRendererProcessStats() { const blinkMemoryInfo = getNormalizedBlinkMemoryInfo(); const heapStatistics = getNormalizedHeapStatistics( - process.getHeapStatistics() + process.getHeapStatistics(), ); const webFrameResourceUsage = getNormalizedWebFrameResourceUsage(); const processMemoryInfo = await getNormalizedProcessMemoryInfo( - await process.getProcessMemoryInfo() + await process.getProcessMemoryInfo(), ); ElectronLog.log("renderer process stats", { blinkMemoryInfo, @@ -157,7 +157,7 @@ async function logRendererProcessStats() { export function setupMainProcessStatsLogger() { setInterval( logSpikeMainMemoryUsage, - SPIKE_DETECTION_INTERVAL_IN_MICROSECONDS + SPIKE_DETECTION_INTERVAL_IN_MICROSECONDS, ); setInterval(logMainProcessStats, LOGGING_INTERVAL_IN_MICROSECONDS); } @@ -165,7 +165,7 @@ export function setupMainProcessStatsLogger() { export function setupRendererProcessStatsLogger() { setInterval( logSpikeRendererMemoryUsage, - SPIKE_DETECTION_INTERVAL_IN_MICROSECONDS + SPIKE_DETECTION_INTERVAL_IN_MICROSECONDS, ); setInterval(logRendererProcessStats, LOGGING_INTERVAL_IN_MICROSECONDS); } @@ -174,21 +174,21 @@ export async function logRendererProcessMemoryUsage(message: string) { const processMemoryInfo = await process.getProcessMemoryInfo(); const processMemory = Math.max( processMemoryInfo.private, - processMemoryInfo.residentSet ?? 0 + processMemoryInfo.residentSet ?? 0, ); ElectronLog.log( "renderer ProcessMemory", message, - convertBytesToHumanReadable(processMemory * 1024) + convertBytesToHumanReadable(processMemory * 1024), ); } const getNormalizedProcessMemoryInfo = async ( - processMemoryInfo: Electron.ProcessMemoryInfo + processMemoryInfo: Electron.ProcessMemoryInfo, ) => { return { residentSet: convertBytesToHumanReadable( - processMemoryInfo.residentSet * 1024 + processMemoryInfo.residentSet * 1024, ), private: convertBytesToHumanReadable(processMemoryInfo.private * 1024), shared: convertBytesToHumanReadable(processMemoryInfo.shared * 1024), @@ -199,40 +199,40 @@ const getNormalizedBlinkMemoryInfo = () => { const blinkMemoryInfo = process.getBlinkMemoryInfo(); return { allocated: convertBytesToHumanReadable( - blinkMemoryInfo.allocated * 1024 + blinkMemoryInfo.allocated * 1024, ), total: convertBytesToHumanReadable(blinkMemoryInfo.total * 1024), }; }; const getNormalizedHeapStatistics = ( - heapStatistics: Electron.HeapStatistics + heapStatistics: Electron.HeapStatistics, ) => { return { totalHeapSize: convertBytesToHumanReadable( - heapStatistics.totalHeapSize * 1024 + heapStatistics.totalHeapSize * 1024, ), totalHeapSizeExecutable: convertBytesToHumanReadable( - heapStatistics.totalHeapSizeExecutable * 1024 + heapStatistics.totalHeapSizeExecutable * 1024, ), totalPhysicalSize: convertBytesToHumanReadable( - heapStatistics.totalPhysicalSize * 1024 + heapStatistics.totalPhysicalSize * 1024, ), totalAvailableSize: convertBytesToHumanReadable( - heapStatistics.totalAvailableSize * 1024 + heapStatistics.totalAvailableSize * 1024, ), usedHeapSize: convertBytesToHumanReadable( - heapStatistics.usedHeapSize * 1024 + heapStatistics.usedHeapSize * 1024, ), heapSizeLimit: convertBytesToHumanReadable( - heapStatistics.heapSizeLimit * 1024 + heapStatistics.heapSizeLimit * 1024, ), mallocedMemory: convertBytesToHumanReadable( - heapStatistics.mallocedMemory * 1024 + heapStatistics.mallocedMemory * 1024, ), peakMallocedMemory: convertBytesToHumanReadable( - heapStatistics.peakMallocedMemory * 1024 + heapStatistics.peakMallocedMemory * 1024, ), doesZapGarbage: heapStatistics.doesZapGarbage, }; @@ -244,51 +244,51 @@ const getNormalizedWebFrameResourceUsage = () => { images: { count: webFrameResourceUsage.images.count, size: convertBytesToHumanReadable( - webFrameResourceUsage.images.size + webFrameResourceUsage.images.size, ), liveSize: convertBytesToHumanReadable( - webFrameResourceUsage.images.liveSize + webFrameResourceUsage.images.liveSize, ), }, scripts: { count: webFrameResourceUsage.scripts.count, size: convertBytesToHumanReadable( - webFrameResourceUsage.scripts.size + webFrameResourceUsage.scripts.size, ), liveSize: convertBytesToHumanReadable( - webFrameResourceUsage.scripts.liveSize + webFrameResourceUsage.scripts.liveSize, ), }, cssStyleSheets: { count: webFrameResourceUsage.cssStyleSheets.count, size: convertBytesToHumanReadable( - webFrameResourceUsage.cssStyleSheets.size + webFrameResourceUsage.cssStyleSheets.size, ), liveSize: convertBytesToHumanReadable( - webFrameResourceUsage.cssStyleSheets.liveSize + webFrameResourceUsage.cssStyleSheets.liveSize, ), }, xslStyleSheets: { count: webFrameResourceUsage.xslStyleSheets.count, size: convertBytesToHumanReadable( - webFrameResourceUsage.xslStyleSheets.size + webFrameResourceUsage.xslStyleSheets.size, ), liveSize: convertBytesToHumanReadable( - webFrameResourceUsage.xslStyleSheets.liveSize + webFrameResourceUsage.xslStyleSheets.liveSize, ), }, fonts: { count: webFrameResourceUsage.fonts.count, size: convertBytesToHumanReadable(webFrameResourceUsage.fonts.size), liveSize: convertBytesToHumanReadable( - webFrameResourceUsage.fonts.liveSize + webFrameResourceUsage.fonts.liveSize, ), }, other: { count: webFrameResourceUsage.other.count, size: convertBytesToHumanReadable(webFrameResourceUsage.other.size), liveSize: convertBytesToHumanReadable( - webFrameResourceUsage.other.liveSize + webFrameResourceUsage.other.liveSize, ), }, }; diff --git a/desktop/src/utils/temp.ts b/desktop/src/utils/temp.ts index f8e597870..91496ce13 100644 --- a/desktop/src/utils/temp.ts +++ b/desktop/src/utils/temp.ts @@ -21,7 +21,7 @@ function generateTempName(length: number) { const charactersLength = CHARACTERS.length; for (let i = 0; i < length; i++) { result += CHARACTERS.charAt( - Math.floor(Math.random() * charactersLength) + Math.floor(Math.random() * charactersLength), ); } return result; diff --git a/desktop/src/utils/watch.ts b/desktop/src/utils/watch.ts index 41a8e71e4..d8575ebd7 100644 --- a/desktop/src/utils/watch.ts +++ b/desktop/src/utils/watch.ts @@ -2,10 +2,10 @@ import { WatchMapping } from "../types"; export function isMappingPresent( watchMappings: WatchMapping[], - folderPath: string + folderPath: string, ) { const watchMapping = watchMappings?.find( - (mapping) => mapping.folderPath === folderPath + (mapping) => mapping.folderPath === folderPath, ); return !!watchMapping; } diff --git a/desktop/thirdparty/next-electron-server b/desktop/thirdparty/next-electron-server deleted file mode 160000 index a88030295..000000000 --- a/desktop/thirdparty/next-electron-server +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a88030295c89dd8f43d9e3a45025678d95c78a45 diff --git a/desktop/tsconfig.json b/desktop/tsconfig.json index 1efdc3d01..142c36005 100644 --- a/desktop/tsconfig.json +++ b/desktop/tsconfig.json @@ -3,8 +3,8 @@ "target": "es2021", "module": "commonjs", "esModuleInterop": true, - /* Emit the generated JS into build/app */ - "outDir": "build/app", + /* Emit the generated JS into app */ + "outDir": "app", "noImplicitAny": true, "sourceMap": true, "baseUrl": "src", diff --git a/desktop/yarn.lock b/desktop/yarn.lock index e5a7625d3..c8080d23f 100644 --- a/desktop/yarn.lock +++ b/desktop/yarn.lock @@ -188,110 +188,6 @@ resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== -"@sentry/browser@6.7.1": - version "6.7.1" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-6.7.1.tgz#e01144a08984a486ecc91d7922cc457e9c9bd6b7" - integrity sha512-R5PYx4TTvifcU790XkK6JVGwavKaXwycDU0MaAwfc4Vf7BLm5KCNJCsDySu1RPAap/017MVYf54p6dWvKiRviA== - dependencies: - "@sentry/core" "6.7.1" - "@sentry/types" "6.7.1" - "@sentry/utils" "6.7.1" - tslib "^1.9.3" - -"@sentry/cli@^1.68.0": - version "1.74.4" - resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-1.74.4.tgz#7df82f68045a155e1885bfcbb5d303e5259eb18e" - integrity sha512-BMfzYiedbModsNBJlKeBOLVYUtwSi99LJ8gxxE4Bp5N8hyjNIN0WVrozAVZ27mqzAuy6151Za3dpmOLO86YlGw== - dependencies: - https-proxy-agent "^5.0.0" - mkdirp "^0.5.5" - node-fetch "^2.6.7" - npmlog "^4.1.2" - progress "^2.0.3" - proxy-from-env "^1.1.0" - which "^2.0.2" - -"@sentry/core@6.7.1": - version "6.7.1" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-6.7.1.tgz#c3aaa6415d06bec65ac446b13b84f073805633e3" - integrity sha512-VAv8OR/7INn2JfiLcuop4hfDcyC7mfL9fdPndQEhlacjmw8gRrgXjR7qyhnCTgzFLkHI7V5bcdIzA83TRPYQpA== - dependencies: - "@sentry/hub" "6.7.1" - "@sentry/minimal" "6.7.1" - "@sentry/types" "6.7.1" - "@sentry/utils" "6.7.1" - tslib "^1.9.3" - -"@sentry/electron@^2.5.1": - version "2.5.4" - resolved "https://registry.yarnpkg.com/@sentry/electron/-/electron-2.5.4.tgz#337b2f7e228e805a3e4eb3611c7b12c6cf87c618" - integrity sha512-tCCK+P581TmdjsDpHBQz7qYcldzGdUk1Fd6FPxPy1JKGzeY4uf/uSLKzR80Lzs5kTpEZFOwiMHSA8yjwFp5qoA== - dependencies: - "@sentry/browser" "6.7.1" - "@sentry/core" "6.7.1" - "@sentry/minimal" "6.7.1" - "@sentry/node" "6.7.1" - "@sentry/types" "6.7.1" - "@sentry/utils" "6.7.1" - tslib "^2.2.0" - -"@sentry/hub@6.7.1": - version "6.7.1" - resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-6.7.1.tgz#d46d24deec67f0731a808ca16796e6765b371bc1" - integrity sha512-eVCTWvvcp6xa0A5GGNHMQEWslmKPlisE5rGmsV/kjvSUv3zSrI0eIDfb51ikdnCiBjHpK2NBWP8Vy8cZOEJegg== - dependencies: - "@sentry/types" "6.7.1" - "@sentry/utils" "6.7.1" - tslib "^1.9.3" - -"@sentry/minimal@6.7.1": - version "6.7.1" - resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-6.7.1.tgz#babf85ee2f167e9dcf150d750d7a0b250c98449c" - integrity sha512-HDDPEnQRD6hC0qaHdqqKDStcdE1KhkFh0RCtJNMCDn0zpav8Dj9AteF70x6kLSlliAJ/JFwi6AmQrLz+FxPexw== - dependencies: - "@sentry/hub" "6.7.1" - "@sentry/types" "6.7.1" - tslib "^1.9.3" - -"@sentry/node@6.7.1": - version "6.7.1" - resolved "https://registry.yarnpkg.com/@sentry/node/-/node-6.7.1.tgz#b09e2eca8e187168feba7bd865a23935bf0f5cc0" - integrity sha512-rtZo1O8ROv4lZwuljQz3iFZW89oXSlgXCG2VqkxQyRspPWu89abROpxLjYzsWwQ8djnur1XjFv51kOLDUTS6Qw== - dependencies: - "@sentry/core" "6.7.1" - "@sentry/hub" "6.7.1" - "@sentry/tracing" "6.7.1" - "@sentry/types" "6.7.1" - "@sentry/utils" "6.7.1" - cookie "^0.4.1" - https-proxy-agent "^5.0.0" - lru_map "^0.3.3" - tslib "^1.9.3" - -"@sentry/tracing@6.7.1": - version "6.7.1" - resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-6.7.1.tgz#b11f0c17a6c5dc14ef44733e5436afb686683268" - integrity sha512-wyS3nWNl5mzaC1qZ2AIp1hjXnfO9EERjMIJjCihs2LWBz1r3efxrHxJHs8wXlNWvrT3KLhq/7vvF5CdU82uPeQ== - dependencies: - "@sentry/hub" "6.7.1" - "@sentry/minimal" "6.7.1" - "@sentry/types" "6.7.1" - "@sentry/utils" "6.7.1" - tslib "^1.9.3" - -"@sentry/types@6.7.1": - version "6.7.1" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.7.1.tgz#c8263e1886df5e815570c4668eb40a1cfaa1c88b" - integrity sha512-9AO7HKoip2MBMNQJEd6+AKtjj2+q9Ze4ooWUdEvdOVSt5drg7BGpK221/p9JEOyJAZwEPEXdcMd3VAIMiOb4MA== - -"@sentry/utils@6.7.1": - version "6.7.1" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.7.1.tgz#909184ad580f0f6375e1e4d4a6ffd33dfe64a4d1" - integrity sha512-Tq2otdbWlHAkctD+EWTYKkEx6BL1Qn3Z/imkO06/PvzpWvVhJWQ5qHAzz5XnwwqNHyV03KVzYB6znq1Bea9HuA== - dependencies: - "@sentry/types" "6.7.1" - tslib "^1.9.3" - "@sindresorhus/is@^4.0.0": version "4.6.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" @@ -662,19 +558,6 @@ applescript@^1.0.0: resolved "https://registry.yarnpkg.com/applescript/-/applescript-1.0.0.tgz#bb87af568cad034a4e48c4bdaf6067a3a2701317" integrity sha512-yvtNHdWvtbYEiIazXAdp/NY+BBb65/DAseqlNiJQjOx9DynuzOYDbVLBJvuc0ve0VL9x6B3OHF6eH52y9hCBtQ== -aproba@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== - -are-we-there-yet@~1.1.2: - version "1.1.7" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz#b15474a932adab4ff8a50d9adfa7e4e926f21146" - integrity sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -1090,16 +973,6 @@ config-file-ts@^0.2.4: glob "^7.1.6" typescript "^4.0.2" -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== - -cookie@^0.4.1: - version "0.4.2" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" - integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== - core-util-is@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -1201,11 +1074,6 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== - detect-indent@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-7.0.1.tgz#cbb060a12842b9c4d333f1cac4aa4da1bb66bc25" @@ -1848,20 +1716,6 @@ gar@^1.0.4: resolved "https://registry.yarnpkg.com/gar/-/gar-1.0.4.tgz#f777bc7db425c0572fdeb52676172ca1ae9888b8" integrity sha512-w4n9cPWyP7aHxKxYHFQMegj7WIAsL/YX/C4Bs5Rr8s1H9M1rNtRWRsw+ovYMkXDQ5S4ZbYHsHAPmevPjPgw44w== -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg== - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" @@ -2033,11 +1887,6 @@ has-symbols@^1.0.3: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== - has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" @@ -2164,7 +2013,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@^2.0.3, inherits@~2.0.1: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -2249,11 +2098,6 @@ isarray@0.0.1: resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== - isbinaryfile@^4.0.8: version "4.0.10" resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.10.tgz#0c5b5e30c2557a2f06febd37b7322946aaee42b3" @@ -2462,11 +2306,6 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -lru_map@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" - integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== - matcher@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/matcher/-/matcher-3.0.0.tgz#bd9060f4c5b70aa8041ccc6f80368760994f30ca" @@ -2570,7 +2409,7 @@ minizlib@^2.1.1: minipass "^3.0.0" yallist "^4.0.0" -mkdirp@^0.5.1, mkdirp@^0.5.5: +mkdirp@^0.5.1: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== @@ -2602,8 +2441,10 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -"next-electron-server@file:./thirdparty/next-electron-server": - version "0.0.8" +next-electron-server@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/next-electron-server/-/next-electron-server-1.0.0.tgz#03e133ed64a5ef671b6c6409f908c4901b1828cb" + integrity sha512-fTUaHwT0Jry2fbdUSIkAiIqgDAInI5BJFF4/j90/okvZCYlyx6yxpXB30KpzmOG6TN/ESwyvsFJVvS2WHT8PAA== node-addon-api@^1.6.3: version "1.7.2" @@ -2642,16 +2483,6 @@ normalize-url@^6.0.1: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== -npmlog@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - nugget@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/nugget/-/nugget-2.0.2.tgz#398b591377b740b3dd308fabecd5ea09cf3443da" @@ -2675,11 +2506,6 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== - object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" @@ -2873,21 +2699,16 @@ prettier-plugin-packagejson@^2.4: sort-package-json "2.8.0" synckit "0.9.0" -prettier@2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.5.1.tgz#fff75fa9d519c54cf0fce328c1017d94546bc56a" - integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg== +prettier@^3: + version "3.2.5" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368" + integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A== pretty-bytes@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-4.0.2.tgz#b2bf82e7350d65c6c33aa95aaa5a4f6327f61cd9" integrity sha512-yJAF+AjbHKlxQ8eezMd/34Mnj/YTQ3i6kLzvVsH4l/BfIFtp444n0wVbnsn66JimZ9uBofv815aRp1zCppxlWw== -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - progress-stream@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/progress-stream/-/progress-stream-1.2.0.tgz#2cd3cfea33ba3a89c9c121ec3347abe9ab125f77" @@ -2916,11 +2737,6 @@ promise-retry@^2.0.1: err-code "^2.0.2" retry "^0.12.0" -proxy-from-env@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" - integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== - psl@^1.1.28: version "1.9.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" @@ -2995,19 +2811,6 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" -readable-stream@^2.0.6: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - readable-stream@^3.0.2: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" @@ -3149,11 +2952,6 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -3207,11 +3005,6 @@ serialize-error@^7.0.1: dependencies: type-fest "^0.13.1" -set-blocking@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== - shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -3229,11 +3022,6 @@ shell-quote@^1.7.3: resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123" integrity sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw== -signal-exit@^3.0.0: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - simple-update-notifier@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz#d70b92bdab7d6d90dfd73931195a30b6e3d7cebb" @@ -3387,7 +3175,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -3408,14 +3196,7 @@ string_decoder@~0.10.x: resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: +strip-ansi@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== @@ -3587,12 +3368,12 @@ truncate-utf8-bytes@^1.0.0: dependencies: utf8-byte-length "^1.0.1" -tslib@^1.8.1, tslib@^1.9.3: +tslib@^1.8.1: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.1.0, tslib@^2.2.0: +tslib@^2.1.0: version "2.4.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== @@ -3695,7 +3476,7 @@ utf8-byte-length@^1.0.1: resolved "https://registry.yarnpkg.com/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz#f45f150c4c66eee968186505ab93fcbb8ad6bf61" integrity sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA== -util-deprecate@^1.0.1, util-deprecate@~1.0.1: +util-deprecate@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== @@ -3749,20 +3530,13 @@ whatwg-url@^5.0.0: tr46 "~0.0.3" webidl-conversions "^3.0.0" -which@^2.0.1, which@^2.0.2: +which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.0.0" -wide-align@^1.1.0: - version "1.1.5" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" - integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== - dependencies: - string-width "^1.0.2 || 2 || 3 || 4" - winreg@1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/winreg/-/winreg-1.2.4.tgz#ba065629b7a925130e15779108cf540990e98d1b" diff --git a/mobile/.gitignore b/mobile/.gitignore index 40821c9c1..47e6ea41b 100644 --- a/mobile/.gitignore +++ b/mobile/.gitignore @@ -34,6 +34,7 @@ lib/generated_plugin_registrant.dart android/key.properties android/app/.settings/* +android/.settings/ .env diff --git a/mobile/CHANGELOG.md b/mobile/CHANGELOG.md index 627fea5ad..445bb9147 100644 --- a/mobile/CHANGELOG.md +++ b/mobile/CHANGELOG.md @@ -1,7 +1,7 @@ # CHANGELOG -## v0.8.66 +## v0.8.67 ### Added * #### Home Widget ✨ diff --git a/mobile/android/app/src/main/res/drawable-hdpi/ic_home_widget_default.png b/mobile/android/app/src/main/res/drawable-hdpi/ic_home_widget_default.png index 109fbb894..f66451a49 100644 Binary files a/mobile/android/app/src/main/res/drawable-hdpi/ic_home_widget_default.png and b/mobile/android/app/src/main/res/drawable-hdpi/ic_home_widget_default.png differ diff --git a/mobile/android/app/src/main/res/drawable-ldpi/ic_home_widget_default.png b/mobile/android/app/src/main/res/drawable-ldpi/ic_home_widget_default.png index 3291f9ce0..7db5ac406 100644 Binary files a/mobile/android/app/src/main/res/drawable-ldpi/ic_home_widget_default.png and b/mobile/android/app/src/main/res/drawable-ldpi/ic_home_widget_default.png differ diff --git a/mobile/android/app/src/main/res/drawable-mdpi/ic_home_widget_default.png b/mobile/android/app/src/main/res/drawable-mdpi/ic_home_widget_default.png index 43ce2db98..b5be0ac8e 100644 Binary files a/mobile/android/app/src/main/res/drawable-mdpi/ic_home_widget_default.png and b/mobile/android/app/src/main/res/drawable-mdpi/ic_home_widget_default.png differ diff --git a/mobile/android/app/src/main/res/drawable-xhdpi/ic_home_widget_default.png b/mobile/android/app/src/main/res/drawable-xhdpi/ic_home_widget_default.png index 50781076d..bc9a25ab9 100644 Binary files a/mobile/android/app/src/main/res/drawable-xhdpi/ic_home_widget_default.png and b/mobile/android/app/src/main/res/drawable-xhdpi/ic_home_widget_default.png differ diff --git a/mobile/android/app/src/main/res/drawable-xxhdpi/ic_home_widget_default.png b/mobile/android/app/src/main/res/drawable-xxhdpi/ic_home_widget_default.png index a27d7829c..52971c10a 100644 Binary files a/mobile/android/app/src/main/res/drawable-xxhdpi/ic_home_widget_default.png and b/mobile/android/app/src/main/res/drawable-xxhdpi/ic_home_widget_default.png differ diff --git a/mobile/android/app/src/main/res/drawable-xxxhdpi/ic_home_widget_default.png b/mobile/android/app/src/main/res/drawable-xxxhdpi/ic_home_widget_default.png index 0143b9d38..ca010e9da 100644 Binary files a/mobile/android/app/src/main/res/drawable-xxxhdpi/ic_home_widget_default.png and b/mobile/android/app/src/main/res/drawable-xxxhdpi/ic_home_widget_default.png differ diff --git a/mobile/lib/app.dart b/mobile/lib/app.dart index 49e742f2f..d4b852540 100644 --- a/mobile/lib/app.dart +++ b/mobile/lib/app.dart @@ -7,17 +7,24 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:home_widget/home_widget.dart' as hw; import 'package:logging/logging.dart'; import 'package:media_extension/media_extension_action_types.dart'; import 'package:photos/ente_theme_data.dart'; import "package:photos/generated/l10n.dart"; import "package:photos/l10n/l10n.dart"; +import "package:photos/models/collection/collection_items.dart"; import 'package:photos/services/app_lifecycle_service.dart'; +import "package:photos/services/collections_service.dart"; +import "package:photos/services/favorites_service.dart"; +import "package:photos/services/home_widget_service.dart"; import "package:photos/services/machine_learning/machine_learning_controller.dart"; import 'package:photos/services/sync_service.dart'; import 'package:photos/ui/tabs/home_widget.dart'; import "package:photos/ui/viewer/actions/file_viewer.dart"; +import "package:photos/ui/viewer/gallery/collection_page.dart"; import "package:photos/utils/intent_util.dart"; +import "package:photos/utils/navigation_util.dart"; class EnteApp extends StatefulWidget { final Future Function(String) runBackgroundTask; @@ -55,6 +62,46 @@ class _EnteAppState extends State with WidgetsBindingObserver { WidgetsBinding.instance.addObserver(this); } + @override + void didChangeDependencies() { + super.didChangeDependencies(); + _checkForWidgetLaunch(); + hw.HomeWidget.widgetClicked.listen(_launchedFromWidget); + } + + void _checkForWidgetLaunch() { + hw.HomeWidget.initiallyLaunchedFromHomeWidget().then(_launchedFromWidget); + } + + Future _launchedFromWidget(Uri? uri) async { + if (uri == null) return; + final collectionID = + await FavoritesService.instance.getFavoriteCollectionID(); + if (collectionID == null) { + return; + } + final collection = CollectionsService.instance.getCollectionByID( + collectionID, + ); + if (collection == null) { + return; + } + unawaited(HomeWidgetService.instance.initHomeWidget()); + + final thumbnail = await CollectionsService.instance.getCover(collection); + unawaited( + routeToPage( + context, + CollectionPage( + CollectionWithThumbnail( + collection, + thumbnail, + ), + ), + ), + ); + } + setLocale(Locale newLocale) { setState(() { locale = newLocale; diff --git a/mobile/lib/core/configuration.dart b/mobile/lib/core/configuration.dart index f82486631..cd6b5156e 100644 --- a/mobile/lib/core/configuration.dart +++ b/mobile/lib/core/configuration.dart @@ -24,6 +24,7 @@ import 'package:photos/models/private_key_attributes.dart'; import 'package:photos/services/billing_service.dart'; import 'package:photos/services/collections_service.dart'; import 'package:photos/services/favorites_service.dart'; +import "package:photos/services/home_widget_service.dart"; import 'package:photos/services/ignored_files_service.dart'; import 'package:photos/services/machine_learning/semantic_search/semantic_search_service.dart'; import 'package:photos/services/memories_service.dart'; @@ -31,7 +32,6 @@ import 'package:photos/services/search_service.dart'; import 'package:photos/services/sync_service.dart'; import 'package:photos/utils/crypto_util.dart'; import 'package:photos/utils/file_uploader.dart'; -import "package:photos/utils/home_widget_util.dart"; import 'package:photos/utils/validator_util.dart'; import 'package:shared_preferences/shared_preferences.dart'; import "package:tuple/tuple.dart"; @@ -175,7 +175,7 @@ class Configuration { MemoriesService.instance.clearCache(); BillingService.instance.clearCache(); SearchService.instance.clearCache(); - unawaited(clearHomeWidget()); + unawaited(HomeWidgetService.instance.clearHomeWidget()); Bus.instance.fire(UserLoggedOutEvent()); } else { await _preferences.setBool("auto_logout", true); diff --git a/mobile/lib/main.dart b/mobile/lib/main.dart index e634ed12f..49dbc01b1 100644 --- a/mobile/lib/main.dart +++ b/mobile/lib/main.dart @@ -27,6 +27,7 @@ import 'package:photos/services/collections_service.dart'; import "package:photos/services/entity_service.dart"; import 'package:photos/services/favorites_service.dart'; import 'package:photos/services/feature_flag_service.dart'; +import 'package:photos/services/home_widget_service.dart'; import 'package:photos/services/local_file_update_service.dart'; import 'package:photos/services/local_sync_service.dart'; import "package:photos/services/location_service.dart"; @@ -46,7 +47,6 @@ import 'package:photos/ui/tools/app_lock.dart'; import 'package:photos/ui/tools/lock_screen.dart'; import 'package:photos/utils/crypto_util.dart'; import 'package:photos/utils/file_uploader.dart'; -import "package:photos/utils/home_widget_util.dart"; import 'package:photos/utils/local_settings.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -110,8 +110,8 @@ ThemeMode _themeMode(AdaptiveThemeMode? savedThemeMode) { Future _homeWidgetSync() async { if (!Platform.isAndroid) return; try { - if (await countHomeWidgets() != 0) { - await initHomeWidget(); + if (await HomeWidgetService.instance.countHomeWidgets() != 0) { + await HomeWidgetService.instance.initHomeWidget(); } } catch (e, s) { _logger.severe("Error in initSlideshowWidget", e, s); @@ -210,6 +210,12 @@ Future _init(bool isBackground, {String via = ''}) async { LocalFileUpdateService.instance.init(preferences); SearchService.instance.init(); StorageBonusService.instance.init(preferences); + if (!isBackground && + Platform.isAndroid && + await HomeWidgetService.instance.countHomeWidgets() == 0) { + unawaited(HomeWidgetService.instance.initHomeWidget()); + } + if (Platform.isIOS) { // ignore: unawaited_futures PushService.instance.init().then((_) { @@ -275,9 +281,15 @@ Future _scheduleHeartBeat( } Future _scheduleFGHomeWidgetSync() async { + Future.delayed(kFGHomeWidgetSyncFrequency, () async { + unawaited(_homeWidgetSyncPeriodic()); + }); +} + +Future _homeWidgetSyncPeriodic() async { await _homeWidgetSync(); Future.delayed(kFGHomeWidgetSyncFrequency, () async { - unawaited(_scheduleFGHomeWidgetSync()); + unawaited(_homeWidgetSyncPeriodic()); }); } diff --git a/mobile/lib/services/home_widget_service.dart b/mobile/lib/services/home_widget_service.dart new file mode 100644 index 000000000..1d6892bb8 --- /dev/null +++ b/mobile/lib/services/home_widget_service.dart @@ -0,0 +1,173 @@ +import "dart:math"; + +import "package:flutter/material.dart"; +import 'package:home_widget/home_widget.dart' as hw; +import "package:logging/logging.dart"; +import "package:photos/core/configuration.dart"; +import "package:photos/core/constants.dart"; +import "package:photos/db/files_db.dart"; +import "package:photos/models/file/file_type.dart"; +import "package:photos/services/favorites_service.dart"; +import "package:photos/utils/file_util.dart"; +import "package:photos/utils/preload_util.dart"; + +class HomeWidgetService { + final Logger _logger = Logger((HomeWidgetService).toString()); + + HomeWidgetService._privateConstructor(); + + static final HomeWidgetService instance = + HomeWidgetService._privateConstructor(); + + Future initHomeWidget() async { + final isLoggedIn = Configuration.instance.isLoggedIn(); + + if (!isLoggedIn) { + await clearHomeWidget(); + _logger.info("user not logged in"); + return; + } + + final collectionID = + await FavoritesService.instance.getFavoriteCollectionID(); + if (collectionID == null) { + await clearHomeWidget(); + _logger.info("Favorite collection not found"); + return; + } + + try { + await hw.HomeWidget.setAppGroupId(iOSGroupID); + final res = await FilesDB.instance.getFilesInCollection( + collectionID, + galleryLoadStartTime, + galleryLoadEndTime, + ); + + final previousGeneratedId = + await hw.HomeWidget.getWidgetData("home_widget_last_img"); + + if (res.files.length == 1 && + res.files[0].generatedID == previousGeneratedId) { + _logger + .info("Only one image found and it's the same as the previous one"); + return; + } + if (res.files.isEmpty) { + await clearHomeWidget(); + _logger.info("No images found"); + return; + } + final files = res.files.where( + (element) => + element.generatedID != previousGeneratedId && + element.fileType == FileType.image, + ); + + final randomNumber = Random().nextInt(files.length); + final randomFile = files.elementAt(randomNumber); + final fullImage = await getFileFromServer(randomFile); + if (fullImage == null) throw Exception("File not found"); + + final image = await decodeImageFromList(await fullImage.readAsBytes()); + final width = image.width.toDouble(); + final height = image.height.toDouble(); + final size = min(min(width, height), 1024.0); + final aspectRatio = width / height; + late final int cacheWidth; + late final int cacheHeight; + if (aspectRatio > 1) { + cacheWidth = 1024; + cacheHeight = (1024 / aspectRatio).round(); + } else if (aspectRatio < 1) { + cacheHeight = 1024; + cacheWidth = (1024 * aspectRatio).round(); + } else { + cacheWidth = 1024; + cacheHeight = 1024; + } + final Image img = Image.file( + fullImage, + fit: BoxFit.cover, + cacheWidth: cacheWidth, + cacheHeight: cacheHeight, + ); + + await PreloadImage.loadImage(img.image); + + final widget = ClipRRect( + borderRadius: BorderRadius.circular(32), + child: Container( + width: size, + height: size, + decoration: BoxDecoration( + color: Colors.black, + image: DecorationImage(image: img.image, fit: BoxFit.cover), + ), + ), + ); + + await hw.HomeWidget.renderFlutterWidget( + widget, + logicalSize: Size(size, size), + key: "slideshow", + ); + + if (randomFile.generatedID != null) { + await hw.HomeWidget.saveWidgetData( + "home_widget_last_img", + randomFile.generatedID!, + ); + } + + await hw.HomeWidget.updateWidget( + name: 'SlideshowWidgetProvider', + androidName: 'SlideshowWidgetProvider', + qualifiedAndroidName: 'io.ente.photos.SlideshowWidgetProvider', + iOSName: 'SlideshowWidget', + ); + _logger.info( + ">>> OG size of SlideshowWidget image: ${width} x $height", + ); + _logger.info( + ">>> SlideshowWidget image rendered with size ${cacheWidth} x $cacheHeight", + ); + } catch (e) { + _logger.severe("Error rendering widget", e); + } + } + + Future countHomeWidgets() async { + return await hw.HomeWidget.getWidgetCount( + name: 'SlideshowWidgetProvider', + androidName: 'SlideshowWidgetProvider', + qualifiedAndroidName: 'io.ente.photos.SlideshowWidgetProvider', + iOSName: 'SlideshowWidget', + ) ?? + 0; + } + + Future clearHomeWidget() async { + final previousGeneratedId = + await hw.HomeWidget.getWidgetData("home_widget_last_img"); + if (previousGeneratedId == null) return; + + _logger.info("Clearing SlideshowWidget"); + await hw.HomeWidget.saveWidgetData( + "slideshow", + null, + ); + + await hw.HomeWidget.updateWidget( + name: 'SlideshowWidgetProvider', + androidName: 'SlideshowWidgetProvider', + qualifiedAndroidName: 'io.ente.photos.SlideshowWidgetProvider', + iOSName: 'SlideshowWidget', + ); + await hw.HomeWidget.saveWidgetData( + "home_widget_last_img", + null, + ); + _logger.info(">>> SlideshowWidget cleared"); + } +} diff --git a/mobile/lib/utils/home_widget_util.dart b/mobile/lib/utils/home_widget_util.dart deleted file mode 100644 index 7f1ff91e1..000000000 --- a/mobile/lib/utils/home_widget_util.dart +++ /dev/null @@ -1,147 +0,0 @@ -import "dart:math"; - -import "package:flutter/material.dart"; -import 'package:home_widget/home_widget.dart' as hw; -import "package:logging/logging.dart"; -import "package:photos/core/configuration.dart"; -import "package:photos/core/constants.dart"; -import "package:photos/db/files_db.dart"; -import "package:photos/models/file/file_type.dart"; -import "package:photos/services/favorites_service.dart"; -import "package:photos/utils/file_util.dart"; -import "package:photos/utils/preload_util.dart"; - -Future countHomeWidgets() async { - return await hw.HomeWidget.getWidgetCount( - name: 'SlideshowWidgetProvider', - androidName: 'SlideshowWidgetProvider', - qualifiedAndroidName: 'io.ente.photos.SlideshowWidgetProvider', - iOSName: 'SlideshowWidget', - ) ?? - 0; -} - -Future initHomeWidget() async { - final Logger logger = Logger("initHomeWidget"); - final user = Configuration.instance.getUserID(); - - if (user == null) { - await clearHomeWidget(); - throw Exception("User not found"); - } - - final collectionID = - await FavoritesService.instance.getFavoriteCollectionID(); - if (collectionID == null) { - await clearHomeWidget(); - throw Exception("Collection not found"); - } - - try { - await hw.HomeWidget.setAppGroupId(iOSGroupID); - final res = await FilesDB.instance.getFilesInCollection( - collectionID, - galleryLoadStartTime, - galleryLoadEndTime, - ); - - final previousGeneratedId = - await hw.HomeWidget.getWidgetData("home_widget_last_img"); - - if (res.files.length == 1 && - res.files[0].generatedID == previousGeneratedId) { - logger.info("Only one image found and it's the same as the previous one"); - return; - } - if (res.files.isEmpty) { - await clearHomeWidget(); - return; - } - final files = res.files.where( - (element) => - element.generatedID != previousGeneratedId && - element.fileType == FileType.image, - ); - - final randomNumber = Random().nextInt(files.length); - final randomFile = files.elementAt(randomNumber); - final fullImage = await getFileFromServer(randomFile); - if (fullImage == null) throw Exception("File not found"); - - Image img = Image.file(fullImage); - var imgProvider = img.image; - await PreloadImage.loadImage(imgProvider); - - img = Image.file(fullImage); - imgProvider = img.image; - - final image = await decodeImageFromList(await fullImage.readAsBytes()); - final width = image.width.toDouble(); - final height = image.height.toDouble(); - final size = min(min(width, height), 1024.0); - - final widget = ClipRRect( - borderRadius: BorderRadius.circular(32), - child: Container( - width: size, - height: size, - decoration: BoxDecoration( - color: Colors.black, - image: DecorationImage(image: imgProvider, fit: BoxFit.cover), - ), - ), - ); - - await hw.HomeWidget.renderFlutterWidget( - widget, - logicalSize: Size(size, size), - key: "slideshow", - ); - - await hw.HomeWidget.updateWidget( - name: 'SlideshowWidgetProvider', - androidName: 'SlideshowWidgetProvider', - qualifiedAndroidName: 'io.ente.photos.SlideshowWidgetProvider', - iOSName: 'SlideshowWidget', - ); - - if (randomFile.generatedID != null) { - await hw.HomeWidget.saveWidgetData( - "home_widget_last_img", - randomFile.generatedID!, - ); - } - - logger.info( - ">>> SlideshowWidget rendered with size ${width}x$height", - ); - } catch (_) { - throw Exception("Error rendering widget"); - } -} - -Future clearHomeWidget() async { - final previousGeneratedId = - await hw.HomeWidget.getWidgetData("home_widget_last_img"); - if (previousGeneratedId == null) return; - - final Logger logger = Logger("clearHomeWidget"); - - logger.info("Clearing SlideshowWidget"); - await hw.HomeWidget.saveWidgetData( - "slideshow", - null, - ); - - await hw.HomeWidget.updateWidget( - name: 'SlideshowWidgetProvider', - androidName: 'SlideshowWidgetProvider', - qualifiedAndroidName: 'io.ente.photos.SlideshowWidgetProvider', - iOSName: 'SlideshowWidget', - ); - await hw.HomeWidget.saveWidgetData( - "home_widget_last_img", - null, - ); - logger.info(">>> SlideshowWidget cleared"); -} diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index b457f0bc7..2ea9bb3ce 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -12,7 +12,7 @@ description: ente photos application # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 0.8.66+586 +version: 0.8.67+587 publish_to: none environment: diff --git a/server/ente/billing.go b/server/ente/billing.go index 4d8d3401d..5a0ff08a8 100644 --- a/server/ente/billing.go +++ b/server/ente/billing.go @@ -176,11 +176,6 @@ type SubscriptionUpdateResponse struct { ClientSecret string `json:"clientSecret"` } -type StripeSubscriptionInfo struct { - PlanCountry string - AccountCountry StripeAccountCountry -} - type StripeEventLog struct { UserID int64 StripeSubscription stripe.Subscription diff --git a/server/ente/passkey.go b/server/ente/passkey.go index 203fb5982..edeb99fd5 100644 --- a/server/ente/passkey.go +++ b/server/ente/passkey.go @@ -14,7 +14,7 @@ type Passkey struct { var MaxPasskeys = 10 type SetPasskeyRecoveryRequest struct { - Secret uuid.UUID `json:"secret" binding:"required"` + Secret string `json:"secret" binding:"required"` // The UserSecretCipher has SkipSecret encrypted with the user's recoveryKey // If the user sends the correct UserSecretCipher, we can be sure that the user has the recoveryKey, // and we can allow the user to recover their MFA. diff --git a/server/pkg/controller/billing.go b/server/pkg/controller/billing.go index 228a3344b..0d01aeeb9 100644 --- a/server/pkg/controller/billing.go +++ b/server/pkg/controller/billing.go @@ -85,30 +85,27 @@ func (c *BillingController) GetPlansV2(countryCode string, stripeAccountCountry // GetStripeAccountCountry returns the stripe account country the user's existing plan is from // if he doesn't have a stripe subscription then ente.DefaultStripeAccountCountry is returned func (c *BillingController) GetStripeAccountCountry(userID int64) (ente.StripeAccountCountry, error) { - stipeSubInfo, hasStripeSub, err := c.GetUserStripeSubscriptionInfo(userID) + subscription, err := c.BillingRepo.GetUserSubscription(userID) if err != nil { return "", stacktrace.Propagate(err, "") } - if hasStripeSub { - return stipeSubInfo.AccountCountry, nil - } else { + if subscription.PaymentProvider != ente.Stripe { //if user doesn't have a stripe subscription, return the default stripe account country return ente.DefaultStripeAccountCountry, nil + } else { + return subscription.Attributes.StripeAccountCountry, nil } } // GetUserPlans returns the active plans for a user func (c *BillingController) GetUserPlans(ctx *gin.Context, userID int64) ([]ente.BillingPlan, error) { - stripeSubInfo, hasStripeSub, err := c.GetUserStripeSubscriptionInfo(userID) + stripeAccountCountry, err := c.GetStripeAccountCountry(userID) if err != nil { - return []ente.BillingPlan{}, stacktrace.Propagate(err, "Failed to get user's subscription country and stripe account") - } - if hasStripeSub { - return c.GetPlansV2(stripeSubInfo.PlanCountry, stripeSubInfo.AccountCountry), nil - } else { - // user doesn't have a stipe subscription, so return the default account plans for the country the user is from - return c.GetPlansV2(network.GetClientCountry(ctx), ente.DefaultStripeAccountCountry), nil + return []ente.BillingPlan{}, stacktrace.Propagate(err, "Failed to get user's country stripe account") } + // always return the plans based on the user's country determined by the IP + return c.GetPlansV2(network.GetClientCountry(ctx), stripeAccountCountry), nil + } // GetSubscription returns the current subscription for a user if any @@ -208,23 +205,6 @@ func (c *BillingController) HasActiveSelfOrFamilySubscription(userID int64) erro return nil } -func (c *BillingController) GetUserStripeSubscriptionInfo(userID int64) (ente.StripeSubscriptionInfo, bool, error) { - s, err := c.BillingRepo.GetUserSubscription(userID) - if err != nil { - return ente.StripeSubscriptionInfo{}, false, stacktrace.Propagate(err, "") - } - // skipping country code extraction for non-stripe subscriptions - // as they have same product id across countries and hence can't be distinquished - if s.PaymentProvider != ente.Stripe { - return ente.StripeSubscriptionInfo{}, false, nil - } - _, countryCode, err := c.getPlanWithCountry(s) - if err != nil { - return ente.StripeSubscriptionInfo{}, false, stacktrace.Propagate(err, "") - } - return ente.StripeSubscriptionInfo{PlanCountry: countryCode, AccountCountry: s.Attributes.StripeAccountCountry}, true, nil -} - // VerifySubscription verifies and returns the verified subscription func (c *BillingController) VerifySubscription( userID int64, diff --git a/server/pkg/repo/two_factor_recovery/repository.go b/server/pkg/repo/two_factor_recovery/repository.go index 0720c0823..4bc63fdd5 100644 --- a/server/pkg/repo/two_factor_recovery/repository.go +++ b/server/pkg/repo/two_factor_recovery/repository.go @@ -35,7 +35,7 @@ func (r *Repository) GetStatus(userID int64) (*ente.TwoFactorRecoveryStatus, err } func (r *Repository) SetPasskeyRecovery(ctx context.Context, userID int64, req *ente.SetPasskeyRecoveryRequest) error { - serveEncPasskey, encErr := crypto.Encrypt(req.Secret.String(), r.SecretEncryptionKey) + serveEncPasskey, encErr := crypto.Encrypt(req.Secret, r.SecretEncryptionKey) if encErr != nil { return stacktrace.Propagate(encErr, "failed to encrypt passkey secret") } diff --git a/web/apps/accounts/sentry.client.config.ts b/web/apps/accounts/sentry.client.config.ts deleted file mode 100644 index c43273663..000000000 --- a/web/apps/accounts/sentry.client.config.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { initSentry } from "@ente/shared/sentry/config/sentry.config.base"; - -initSentry("https://0f7214c7feb9b1dd2fed5db09b42fa1b@sentry.ente.io/5"); diff --git a/web/apps/accounts/sentry.edge.config.ts b/web/apps/accounts/sentry.edge.config.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/web/apps/accounts/sentry.properties b/web/apps/accounts/sentry.properties deleted file mode 100644 index 27c3a286f..000000000 --- a/web/apps/accounts/sentry.properties +++ /dev/null @@ -1,6 +0,0 @@ -# This file is used by the SentryWebpackPlugin to upload sourcemaps when the -# SENTRY_AUTH_TOKEN environment variable is defined. - -defaults.url = https://sentry.ente.io/ -defaults.org = ente -defaults.project = web-photos diff --git a/web/apps/accounts/sentry.server.config.ts b/web/apps/accounts/sentry.server.config.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/web/apps/accounts/src/pages/passkeys/flow/index.tsx b/web/apps/accounts/src/pages/passkeys/flow/index.tsx index 435ca61dd..1f082bf6b 100644 --- a/web/apps/accounts/src/pages/passkeys/flow/index.tsx +++ b/web/apps/accounts/src/pages/passkeys/flow/index.tsx @@ -40,6 +40,7 @@ const PasskeysFlow = () => { redirect !== "" && !( redirectURL.host.endsWith(".ente.io") || + redirectURL.host.endsWith(".ente.sh") || redirectURL.host.endsWith("bada-frame.pages.dev") ) && redirectURL.protocol !== "ente:" && diff --git a/web/apps/auth/next.config.js b/web/apps/auth/next.config.js index eea88bf93..81a64d7dd 100644 --- a/web/apps/auth/next.config.js +++ b/web/apps/auth/next.config.js @@ -1,3 +1 @@ -const nextConfigBase = require("@/next/next.config.base.js"); - -module.exports = nextConfigBase; +module.exports = require("@/next/next.config.base.js"); diff --git a/web/apps/auth/sentry.client.config.ts b/web/apps/auth/sentry.client.config.ts deleted file mode 100644 index 373718e8e..000000000 --- a/web/apps/auth/sentry.client.config.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { initSentry } from "@ente/shared/sentry/config/sentry.config.base"; - -initSentry("https://5d344112b570b1a368b6f5c1d0bb798b@sentry.ente.io/8"); diff --git a/web/apps/auth/sentry.edge.config.ts b/web/apps/auth/sentry.edge.config.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/web/apps/auth/sentry.properties b/web/apps/auth/sentry.properties deleted file mode 100644 index e9b0cad16..000000000 --- a/web/apps/auth/sentry.properties +++ /dev/null @@ -1,6 +0,0 @@ -# This file is used by the SentryWebpackPlugin to upload sourcemaps when the -# SENTRY_AUTH_TOKEN environment variable is defined. - -defaults.url = https://sentry.ente.io/ -defaults.org = ente -defaults.project = web-auth diff --git a/web/apps/auth/sentry.server.config.ts b/web/apps/auth/sentry.server.config.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/web/apps/auth/src/pages/_error.tsx b/web/apps/auth/src/pages/_error.tsx deleted file mode 100644 index bf1bb89be..000000000 --- a/web/apps/auth/src/pages/_error.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { APPS } from "@ente/shared/apps/constants"; -import ErrorPage from "@ente/shared/next/pages/_error"; -import { useRouter } from "next/router"; -import { AppContext } from "pages/_app"; -import { useContext } from "react"; - -export default function Error() { - const appContext = useContext(AppContext); - const router = useRouter(); - return ( - - ); -} diff --git a/web/apps/auth/src/pages/passkeys/finish/index.tsx b/web/apps/auth/src/pages/passkeys/finish/index.tsx new file mode 100644 index 000000000..289f351de --- /dev/null +++ b/web/apps/auth/src/pages/passkeys/finish/index.tsx @@ -0,0 +1,11 @@ +import PasskeysFinishPage from "@ente/accounts/pages/passkeys/finish"; + +const PasskeysFinish = () => { + return ( + <> + + + ); +}; + +export default PasskeysFinish; diff --git a/web/apps/cast/next.config.js b/web/apps/cast/next.config.js index eea88bf93..81a64d7dd 100644 --- a/web/apps/cast/next.config.js +++ b/web/apps/cast/next.config.js @@ -1,3 +1 @@ -const nextConfigBase = require("@/next/next.config.base.js"); - -module.exports = nextConfigBase; +module.exports = require("@/next/next.config.base.js"); diff --git a/web/apps/cast/sentry.client.config.ts b/web/apps/cast/sentry.client.config.ts deleted file mode 100644 index c43273663..000000000 --- a/web/apps/cast/sentry.client.config.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { initSentry } from "@ente/shared/sentry/config/sentry.config.base"; - -initSentry("https://0f7214c7feb9b1dd2fed5db09b42fa1b@sentry.ente.io/5"); diff --git a/web/apps/cast/sentry.edge.config.ts b/web/apps/cast/sentry.edge.config.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/web/apps/cast/sentry.properties b/web/apps/cast/sentry.properties deleted file mode 100644 index 27c3a286f..000000000 --- a/web/apps/cast/sentry.properties +++ /dev/null @@ -1,6 +0,0 @@ -# This file is used by the SentryWebpackPlugin to upload sourcemaps when the -# SENTRY_AUTH_TOKEN environment variable is defined. - -defaults.url = https://sentry.ente.io/ -defaults.org = ente -defaults.project = web-photos diff --git a/web/apps/cast/sentry.server.config.ts b/web/apps/cast/sentry.server.config.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/web/apps/cast/src/services/InMemoryStore.ts b/web/apps/cast/src/services/InMemoryStore.ts index ded73faf0..88e77b869 100644 --- a/web/apps/cast/src/services/InMemoryStore.ts +++ b/web/apps/cast/src/services/InMemoryStore.ts @@ -1,5 +1,4 @@ export enum MS_KEYS { - OPT_OUT_OF_CRASH_REPORTS = "optOutOfCrashReports", SRP_CONFIGURE_IN_PROGRESS = "srpConfigureInProgress", REDIRECT_URL = "redirectUrl", } diff --git a/web/apps/photos/.env.development b/web/apps/photos/.env.development index 045fffaee..038f0237a 100644 --- a/web/apps/photos/.env.development +++ b/web/apps/photos/.env.development @@ -22,7 +22,6 @@ # # - Logs go to the browser console (in addition to the log file) # - There is some additional logging -# - Sentry is not initialized # - ... (search for isDevBuild to see all impacts) # # Note that even in development build, the app still connects to the production diff --git a/web/apps/photos/next.config.js b/web/apps/photos/next.config.js index eea88bf93..81a64d7dd 100644 --- a/web/apps/photos/next.config.js +++ b/web/apps/photos/next.config.js @@ -1,3 +1 @@ -const nextConfigBase = require("@/next/next.config.base.js"); - -module.exports = nextConfigBase; +module.exports = require("@/next/next.config.base.js"); diff --git a/web/apps/photos/public/locales/bg-BG/translation.json b/web/apps/photos/public/locales/bg-BG/translation.json index 6ca5bd9b0..6b02fae65 100644 --- a/web/apps/photos/public/locales/bg-BG/translation.json +++ b/web/apps/photos/public/locales/bg-BG/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", diff --git a/web/apps/photos/public/locales/de-DE/translation.json b/web/apps/photos/public/locales/de-DE/translation.json index 3fcd4c542..f5a6f13b3 100644 --- a/web/apps/photos/public/locales/de-DE/translation.json +++ b/web/apps/photos/public/locales/de-DE/translation.json @@ -176,7 +176,7 @@ "SUBSCRIPTION_CANCEL_FAILED": "Abonnement konnte nicht storniert werden", "SUBSCRIPTION_CANCEL_SUCCESS": "Abonnement erfolgreich beendet", "REACTIVATE_SUBSCRIPTION": "Abonnement reaktivieren", - "REACTIVATE_SUBSCRIPTION_MESSAGE": "", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "Nach der Reaktivierung wird am {{date, dateTime}} abgerechnet", "SUBSCRIPTION_ACTIVATE_SUCCESS": "Abonnement erfolgreich aktiviert ", "SUBSCRIPTION_ACTIVATE_FAILED": "Reaktivierung der Abonnementverlängerung fehlgeschlagen", "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "Vielen Dank", @@ -258,25 +258,25 @@ "SCAN_QR_CODE": "QR‐Code stattdessen scannen", "ENABLE_TWO_FACTOR": "Zwei-Faktor-Authentifizierung aktivieren", "ENABLE": "Aktivieren", - "LOST_DEVICE": "", + "LOST_DEVICE": "Zwei-Faktor-Gerät verloren", "INCORRECT_CODE": "Falscher Code", "TWO_FACTOR_INFO": "", "DISABLE_TWO_FACTOR_LABEL": "Deaktiviere die Zwei-Faktor-Authentifizierung", - "UPDATE_TWO_FACTOR_LABEL": "", + "UPDATE_TWO_FACTOR_LABEL": "Authentifizierungsgerät aktualisieren", "DISABLE": "Deaktivieren", "RECONFIGURE": "Neu einrichten", - "UPDATE_TWO_FACTOR": "", + "UPDATE_TWO_FACTOR": "Zweiten Faktor aktualisieren", "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "", - "DISABLE_TWO_FACTOR": "", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "", + "UPDATE": "Aktualisierung", + "DISABLE_TWO_FACTOR": "Zweiten Faktor deaktivieren", + "DISABLE_TWO_FACTOR_MESSAGE": "Bist du sicher, dass du die Zwei-Faktor-Authentifizierung deaktivieren willst", + "TWO_FACTOR_DISABLE_FAILED": "Fehler beim Deaktivieren des zweiten Faktors, bitte versuchen Sie es erneut", "EXPORT_DATA": "Daten exportieren", "SELECT_FOLDER": "Ordner auswählen", "DESTINATION": "Zielort", "START": "Start", - "LAST_EXPORT_TIME": "", - "EXPORT_AGAIN": "", + "LAST_EXPORT_TIME": "Letztes Exportdatum", + "EXPORT_AGAIN": "Neusynchronisation", "LOCAL_STORAGE_NOT_ACCESSIBLE": "", "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "", "SEND_OTT": "OTP senden", @@ -302,17 +302,17 @@ "TOO_LARGE_INFO": "Diese Dateien wurden nicht hochgeladen, da sie unsere maximale Dateigröße überschreiten", "THUMBNAIL_GENERATION_FAILED_INFO": "Diese Dateien wurden hochgeladen, aber leider konnten wir nicht die Thumbnails für sie generieren.", "UPLOAD_TO_COLLECTION": "In Album hochladen", - "UNCATEGORIZED": "", + "UNCATEGORIZED": "Unkategorisiert", "ARCHIVE": "Archiv", "FAVORITES": "Favoriten", "ARCHIVE_COLLECTION": "Album archivieren", "ARCHIVE_SECTION_NAME": "Archiv", "ALL_SECTION_NAME": "Alle", "MOVE_TO_COLLECTION": "Zum Album verschieben", - "UNARCHIVE": "", - "UNARCHIVE_COLLECTION": "", - "HIDE_COLLECTION": "", - "UNHIDE_COLLECTION": "", + "UNARCHIVE": "Dearchivieren", + "UNARCHIVE_COLLECTION": "Album dearchivieren", + "HIDE_COLLECTION": "Album ausblenden", + "UNHIDE_COLLECTION": "Album wieder einblenden", "MOVE": "Verschieben", "ADD": "Hinzufügen", "REMOVE": "Entfernen", @@ -334,14 +334,14 @@ "LEAVE_SHARED_ALBUM_MESSAGE": "", "NOT_FILE_OWNER": "Dateien in einem freigegebenen Album können nicht gelöscht werden", "CONFIRM_SELF_REMOVE_MESSAGE": "", - "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Einige der Elemente, die du entfernst, wurden von anderen Nutzern hinzugefügt und du wirst den Zugriff auf sie verlieren.", "SORT_BY_CREATION_TIME_ASCENDING": "Ältestem", "SORT_BY_UPDATION_TIME_DESCENDING": "Zuletzt aktualisiert", "SORT_BY_NAME": "Name", "COMPRESS_THUMBNAILS": "", "THUMBNAIL_REPLACED": "", "FIX_THUMBNAIL": "Komprimiere", - "FIX_THUMBNAIL_LATER": "", + "FIX_THUMBNAIL_LATER": "Später komprimieren", "REPLACE_THUMBNAIL_NOT_STARTED": "", "REPLACE_THUMBNAIL_COMPLETED": "", "REPLACE_THUMBNAIL_NOOP": "", @@ -374,31 +374,31 @@ "PARTICIPANTS": "", "CHANGE_PERMISSIONS_TO_VIEWER": "", "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", - "CONVERT_TO_VIEWER": "", + "CONVERT_TO_VIEWER": "Ja, zu \"Beobachter\" ändern", "CONVERT_TO_COLLABORATOR": "", "CHANGE_PERMISSION": "", "REMOVE_PARTICIPANT": "Entfernen?", "CONFIRM_REMOVE": "Ja, entfernen", "MANAGE": "Verwalten", - "ADDED_AS": "", - "COLLABORATOR_RIGHTS": "", + "ADDED_AS": "Hinzugefügt als", + "COLLABORATOR_RIGHTS": "Bearbeiter können Fotos & Videos zu dem geteilten Album hinzufügen", "REMOVE_PARTICIPANT_HEAD": "Teilnehmer entfernen", "OWNER": "Besitzer", "COLLABORATORS": "", - "ADD_MORE": "", + "ADD_MORE": "Mehr hinzufügen", "VIEWERS": "", - "OR_ADD_EXISTING": "", + "OR_ADD_EXISTING": "Oder eine Vorherige auswählen", "REMOVE_PARTICIPANT_MESSAGE": "", "NOT_FOUND": "404 - Nicht gefunden", "LINK_EXPIRED": "Link ist abgelaufen", "LINK_EXPIRED_MESSAGE": "Dieser Link ist abgelaufen oder wurde deaktiviert!", - "MANAGE_LINK": "", + "MANAGE_LINK": "Link verwalten", "LINK_TOO_MANY_REQUESTS": "Sorry, dieses Album wurde auf zu vielen Geräten angezeigt!", "FILE_DOWNLOAD": "Downloads erlauben", "LINK_PASSWORD_LOCK": "Passwort Sperre", - "PUBLIC_COLLECT": "", + "PUBLIC_COLLECT": "Hinzufügen von Fotos erlauben", "LINK_DEVICE_LIMIT": "Geräte Limit", - "NO_DEVICE_LIMIT": "", + "NO_DEVICE_LIMIT": "Keins", "LINK_EXPIRY": "Ablaufdatum des Links", "NEVER": "Niemals", "DISABLE_FILE_DOWNLOAD": "", @@ -412,7 +412,7 @@ "DISABLE_PASSWORD": "", "DISABLE_PASSWORD_MESSAGE": "", "PASSWORD_LOCK": "Passwort Sperre", - "LOCK": "", + "LOCK": "Sperren", "DOWNLOAD_UPLOAD_LOGS": "", "UPLOAD_FILES": "Datei", "UPLOAD_DIRS": "Ordner", @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", diff --git a/web/apps/photos/public/locales/en-US/translation.json b/web/apps/photos/public/locales/en-US/translation.json index 510471eaa..ea74f4f5f 100644 --- a/web/apps/photos/public/locales/en-US/translation.json +++ b/web/apps/photos/public/locales/en-US/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "Downloading {{name}}", "DOWNLOAD_FAILED": "Download failed", "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} files", - "CRASH_REPORTING": "Crash reporting", "CHRISTMAS": "Christmas", "CHRISTMAS_EVE": "Christmas Eve", "NEW_YEAR": "New Year", diff --git a/web/apps/photos/public/locales/es-ES/translation.json b/web/apps/photos/public/locales/es-ES/translation.json index 839ad5b91..64c2849eb 100644 --- a/web/apps/photos/public/locales/es-ES/translation.json +++ b/web/apps/photos/public/locales/es-ES/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", diff --git a/web/apps/photos/public/locales/fa-IR/translation.json b/web/apps/photos/public/locales/fa-IR/translation.json index 29efad393..68e1da3b9 100644 --- a/web/apps/photos/public/locales/fa-IR/translation.json +++ b/web/apps/photos/public/locales/fa-IR/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", diff --git a/web/apps/photos/public/locales/fi-FI/translation.json b/web/apps/photos/public/locales/fi-FI/translation.json index 89408ba55..fbc0b937a 100644 --- a/web/apps/photos/public/locales/fi-FI/translation.json +++ b/web/apps/photos/public/locales/fi-FI/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", diff --git a/web/apps/photos/public/locales/fr-FR/translation.json b/web/apps/photos/public/locales/fr-FR/translation.json index b53954188..2d183c9eb 100644 --- a/web/apps/photos/public/locales/fr-FR/translation.json +++ b/web/apps/photos/public/locales/fr-FR/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "Téléchargement de {{name}}", "DOWNLOAD_FAILED": "Échec du téléchargement", "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} fichiers", - "CRASH_REPORTING": "Rapport de plantage", "CHRISTMAS": "Noël", "CHRISTMAS_EVE": "Réveillon de Noël", "NEW_YEAR": "Nouvel an", diff --git a/web/apps/photos/public/locales/it-IT/translation.json b/web/apps/photos/public/locales/it-IT/translation.json index a03c35f79..dd7afc158 100644 --- a/web/apps/photos/public/locales/it-IT/translation.json +++ b/web/apps/photos/public/locales/it-IT/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", diff --git a/web/apps/photos/public/locales/ko-KR/translation.json b/web/apps/photos/public/locales/ko-KR/translation.json index 24ac00c12..754fef892 100644 --- a/web/apps/photos/public/locales/ko-KR/translation.json +++ b/web/apps/photos/public/locales/ko-KR/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", diff --git a/web/apps/photos/public/locales/nl-NL/translation.json b/web/apps/photos/public/locales/nl-NL/translation.json index 10374c7e0..2b2aa1111 100644 --- a/web/apps/photos/public/locales/nl-NL/translation.json +++ b/web/apps/photos/public/locales/nl-NL/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "{{name}} downloaden", "DOWNLOAD_FAILED": "Download mislukt", "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} bestanden", - "CRASH_REPORTING": "Foutenrapportering", "CHRISTMAS": "Kerst", "CHRISTMAS_EVE": "Kerstavond", "NEW_YEAR": "Nieuwjaar", diff --git a/web/apps/photos/public/locales/pt-BR/translation.json b/web/apps/photos/public/locales/pt-BR/translation.json index 99ffb2b4a..4eaa398c4 100644 --- a/web/apps/photos/public/locales/pt-BR/translation.json +++ b/web/apps/photos/public/locales/pt-BR/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "Transferindo {{name}}", "DOWNLOAD_FAILED": "Falha ao baixar", "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} arquivos", - "CRASH_REPORTING": "Relatório de falhas", "CHRISTMAS": "Natal", "CHRISTMAS_EVE": "Véspera de Natal", "NEW_YEAR": "Ano Novo", diff --git a/web/apps/photos/public/locales/pt-PT/translation.json b/web/apps/photos/public/locales/pt-PT/translation.json index 8332af46a..ac7d17968 100644 --- a/web/apps/photos/public/locales/pt-PT/translation.json +++ b/web/apps/photos/public/locales/pt-PT/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", diff --git a/web/apps/photos/public/locales/ru-RU/translation.json b/web/apps/photos/public/locales/ru-RU/translation.json index c578832f5..0e9715563 100644 --- a/web/apps/photos/public/locales/ru-RU/translation.json +++ b/web/apps/photos/public/locales/ru-RU/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "Загрузка {{name}}", "DOWNLOAD_FAILED": "Загрузка не удалась", "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} файлов", - "CRASH_REPORTING": "Отчеты об ошибках", "CHRISTMAS": "Рождество", "CHRISTMAS_EVE": "Канун Рождества", "NEW_YEAR": "Новый год", diff --git a/web/apps/photos/public/locales/sv-SE/translation.json b/web/apps/photos/public/locales/sv-SE/translation.json index 49636cc35..550780b44 100644 --- a/web/apps/photos/public/locales/sv-SE/translation.json +++ b/web/apps/photos/public/locales/sv-SE/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", diff --git a/web/apps/photos/public/locales/th-TH/translation.json b/web/apps/photos/public/locales/th-TH/translation.json index 89408ba55..fbc0b937a 100644 --- a/web/apps/photos/public/locales/th-TH/translation.json +++ b/web/apps/photos/public/locales/th-TH/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", diff --git a/web/apps/photos/public/locales/tr-TR/translation.json b/web/apps/photos/public/locales/tr-TR/translation.json index 89408ba55..fbc0b937a 100644 --- a/web/apps/photos/public/locales/tr-TR/translation.json +++ b/web/apps/photos/public/locales/tr-TR/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", diff --git a/web/apps/photos/public/locales/zh-CN/translation.json b/web/apps/photos/public/locales/zh-CN/translation.json index 0be918442..6e513f24b 100644 --- a/web/apps/photos/public/locales/zh-CN/translation.json +++ b/web/apps/photos/public/locales/zh-CN/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "正在下载 {{name}}", "DOWNLOAD_FAILED": "下载失败", "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} 个文件", - "CRASH_REPORTING": "崩溃报告", "CHRISTMAS": "圣诞", "CHRISTMAS_EVE": "平安夜", "NEW_YEAR": "新年", diff --git a/web/apps/photos/sentry.client.config.ts b/web/apps/photos/sentry.client.config.ts deleted file mode 100644 index c43273663..000000000 --- a/web/apps/photos/sentry.client.config.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { initSentry } from "@ente/shared/sentry/config/sentry.config.base"; - -initSentry("https://0f7214c7feb9b1dd2fed5db09b42fa1b@sentry.ente.io/5"); diff --git a/web/apps/photos/sentry.edge.config.ts b/web/apps/photos/sentry.edge.config.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/web/apps/photos/sentry.properties b/web/apps/photos/sentry.properties deleted file mode 100644 index 27c3a286f..000000000 --- a/web/apps/photos/sentry.properties +++ /dev/null @@ -1,6 +0,0 @@ -# This file is used by the SentryWebpackPlugin to upload sourcemaps when the -# SENTRY_AUTH_TOKEN environment variable is defined. - -defaults.url = https://sentry.ente.io/ -defaults.org = ente -defaults.project = web-photos diff --git a/web/apps/photos/sentry.server.config.ts b/web/apps/photos/sentry.server.config.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/web/apps/photos/src/components/Sidebar/Preferences/index.tsx b/web/apps/photos/src/components/Sidebar/Preferences/index.tsx index ec9d61a47..04dc79a13 100644 --- a/web/apps/photos/src/components/Sidebar/Preferences/index.tsx +++ b/web/apps/photos/src/components/Sidebar/Preferences/index.tsx @@ -1,17 +1,10 @@ import ChevronRight from "@mui/icons-material/ChevronRight"; import { Box, DialogProps, Stack } from "@mui/material"; import { EnteDrawer } from "components/EnteDrawer"; +import { EnteMenuItem } from "components/Menu/EnteMenuItem"; import Titlebar from "components/Titlebar"; import { t } from "i18next"; -import isElectron from "is-electron"; import { useState } from "react"; - -import ElectronAPIs from "@ente/shared/electron"; -import { useLocalState } from "@ente/shared/hooks/useLocalState"; -import { logError } from "@ente/shared/sentry"; -import InMemoryStore, { MS_KEYS } from "@ente/shared/storage/InMemoryStore"; -import { LS_KEYS } from "@ente/shared/storage/localStorage"; -import { EnteMenuItem } from "components/Menu/EnteMenuItem"; import AdvancedSettings from "../AdvancedSettings"; import MapSettings from "../MapSetting"; import { LanguageSelector } from "./LanguageSelector"; @@ -19,10 +12,6 @@ import { LanguageSelector } from "./LanguageSelector"; export default function Preferences({ open, onClose, onRootClose }) { const [advancedSettingsView, setAdvancedSettingsView] = useState(false); const [mapSettingsView, setMapSettingsView] = useState(false); - const [optOutOfCrashReports, setOptOutOfCrashReports] = useLocalState( - LS_KEYS.OPT_OUT_OF_CRASH_REPORTS, - false, - ); const openAdvancedSettings = () => setAdvancedSettingsView(true); const closeAdvancedSettings = () => setAdvancedSettingsView(false); @@ -43,23 +32,6 @@ export default function Preferences({ open, onClose, onRootClose }) { } }; - const toggleOptOutOfCrashReports = async () => { - try { - if (isElectron()) { - await ElectronAPIs.updateOptOutOfCrashReports( - !optOutOfCrashReports, - ); - } - setOptOutOfCrashReports(!optOutOfCrashReports); - InMemoryStore.set( - MS_KEYS.OPT_OUT_OF_CRASH_REPORTS, - !optOutOfCrashReports, - ); - } catch (e) { - logError(e, "toggleOptOutOfCrashReports failed"); - } - }; - return ( - - } diff --git a/web/apps/photos/src/components/Sidebar/UtilitySection.tsx b/web/apps/photos/src/components/Sidebar/UtilitySection.tsx index 454ef55bf..b297f36ee 100644 --- a/web/apps/photos/src/components/Sidebar/UtilitySection.tsx +++ b/web/apps/photos/src/components/Sidebar/UtilitySection.tsx @@ -165,11 +165,13 @@ export default function UtilitySection({ closeSidebar }) { label={t("TWO_FACTOR")} /> - + {isInternalUser() && ( + + )} - ); -} diff --git a/web/apps/photos/src/services/upload/thumbnailService.ts b/web/apps/photos/src/services/upload/thumbnailService.ts index 8b1cf7a61..74ce23f4c 100644 --- a/web/apps/photos/src/services/upload/thumbnailService.ts +++ b/web/apps/photos/src/services/upload/thumbnailService.ts @@ -1,4 +1,4 @@ -import { CustomError, errorWithContext } from "@ente/shared/error"; +import { CustomError } from "@ente/shared/error"; import { addLogLine } from "@ente/shared/logging"; import { getFileNameSize } from "@ente/shared/logging/web"; import { logError } from "@ente/shared/sentry"; @@ -145,10 +145,9 @@ export async function generateImageThumbnailUsingCanvas( clearTimeout(timeout); resolve(null); } catch (e) { - const err = errorWithContext( - e, - `${CustomError.THUMBNAIL_GENERATION_FAILED} err: ${e}`, - ); + const err = new Error(CustomError.THUMBNAIL_GENERATION_FAILED, { + cause: e, + }); reject(err); } }; diff --git a/web/docs/deploy.md b/web/docs/deploy.md index 8e479db97..c17de8ffa 100644 --- a/web/docs/deploy.md +++ b/web/docs/deploy.md @@ -9,7 +9,11 @@ Cloudflare Pages. anything inside `docs/` gets merged to `main`. * Every night, all the web apps get automatically deployed to a nightly preview - URLs using the current code in main. + URLs (`*.ente.sh`) using the current code in main. + +* A preview deployment can be made by triggering the "Preview (web)" workflow. + This allows us to deploy a build of any of the apps from an arbitrary branch + to [preview.ente.sh](https://preview.ente.sh). Use the various `yarn deploy:*` commands to help with production deployments. For example, `yarn deploy:photos` will open a PR to merge the current `main` @@ -21,6 +25,7 @@ and publish to [web.ente.io](https://web.ente.io). > the merge commit. ## Deployments + Here is a list of all the deployments, whether or not they are production deployments, and the action that triggers them: @@ -36,6 +41,7 @@ deployments, and the action that triggers them: | [auth.ente.sh](https://auth.ente.sh) | Preview | Nightly deploy of `main` | | [cast.ente.sh](https://cast.ente.sh) | Preview | Nightly deploy of `main` | | [photos.ente.sh](https://photos.ente.sh) | Preview | Nightly deploy of `main` | +| [preview.ente.sh](https://preview.ente.sh) | Preview | Manually triggered | ### Other subdomains @@ -49,6 +55,19 @@ Apart from this, there are also some other deployments: - `payments.ente.io` and `family.ente.io` are currently in a separate repositories (Enhancement: bring them in here). +### Preview deployments + +To trigger a preview deployment, manually trigger the "Preview (web)" workflow +from the Actions tab on GitHub. You'll need to select the app to build, and the +branch to use. This'll then build the specified app (e.g. "photos") from that +branch, and deploy it to [preview.ente.sh](https://preview.ente.sh). + +The workflow can also be triggered using GitHub's CLI, gh. e.g. + +```sh +gh workflow run web-preview -F app=cast --ref my-branch +``` + --- ## Details diff --git a/web/package.json b/web/package.json index bdbce0b42..f7e734651 100644 --- a/web/package.json +++ b/web/package.json @@ -26,7 +26,6 @@ "lint-fix": "yarn prettier --write . && yarn workspaces run eslint --fix ." }, "resolutions": { - "@sentry/cli": "1.75.0", "libsodium": "0.7.9" }, "devDependencies": { diff --git a/web/packages/next/next.config.base.js b/web/packages/next/next.config.base.js index 5439c9443..ef7b65fac 100644 --- a/web/packages/next/next.config.base.js +++ b/web/packages/next/next.config.base.js @@ -10,7 +10,6 @@ * https://nextjs.org/docs/pages/api-reference/next-config-js */ -const { withSentryConfig } = require("@sentry/nextjs"); const cp = require("child_process"); const gitSHA = cp @@ -21,8 +20,7 @@ const gitSHA = cp .trimEnd(); /** - * The base Next.js config. Before exporting this, we wrap this in - * {@link withSentryConfig}. + * Configuration for the Next.js build * * @type {import("next").NextConfig} */ @@ -54,33 +52,6 @@ const nextConfig = { } return config; }, - - // Build time Sentry configuration - // https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/ - sentry: { - widenClientFileUpload: true, - disableServerWebpackPlugin: true, - }, }; -const sentryWebpackPluginOptions = { - // The same release value needs to be used both: - // 1. here to create a new release on Sentry and upload sourcemaps to it, - // 2. and when initializing Sentry in the browser (`Sentry.init`). - release: gitSHA, -}; - -// withSentryConfig extends the default Next.js usage of webpack to: -// -// 1. Initialize the SDK on client page load (See `sentry.client.config.ts`) -// -// 2. Upload sourcemaps, using the settings defined in `sentry.properties`. -// -// Sourcemaps are only uploaded to Sentry if SENTRY_AUTH_TOKEN is defined. Note -// that sourcemaps are always generated in the static export; the Sentry Webpack -// plugin behavies as if the `productionBrowserSourceMaps` Next.js configuration -// setting is `true`. -// -// Irritatingly, Sentry insists that we create empty sentry.server.config.ts and -// sentry.edge.config.ts files, even though we are not using those parts. -module.exports = withSentryConfig(nextConfig, sentryWebpackPluginOptions); +module.exports = nextConfig; diff --git a/web/packages/shared/electron/service.ts b/web/packages/shared/electron/service.ts index 2f00b42f4..8e035e632 100644 --- a/web/packages/shared/electron/service.ts +++ b/web/packages/shared/electron/service.ts @@ -12,11 +12,7 @@ import { deserializeToResponse, serializeResponse } from "./worker/utils/proxy"; export interface LimitedElectronAPIs extends Pick< ElectronAPIsType, - | "openDiskCache" - | "deleteDiskCache" - | "getSentryUserID" - | "convertToJPEG" - | "logToDisk" + "openDiskCache" | "deleteDiskCache" | "convertToJPEG" | "logToDisk" > {} class WorkerSafeElectronServiceImpl implements LimitedElectronAPIs { @@ -56,10 +52,6 @@ class WorkerSafeElectronServiceImpl implements LimitedElectronAPIs { return await this.proxiedElectron.deleteDiskCache(cacheName); } - async getSentryUserID() { - await this.ready; - return this.proxiedElectron.getSentryUserID(); - } async convertToJPEG( inputFileData: Uint8Array, filename: string, diff --git a/web/packages/shared/electron/types.ts b/web/packages/shared/electron/types.ts index df5829ab0..34b8ee591 100644 --- a/web/packages/shared/electron/types.ts +++ b/web/packages/shared/electron/types.ts @@ -80,7 +80,6 @@ export interface ElectronAPIsType { ) => void; updateAndRestart: () => void; skipAppUpdate: (version: string) => void; - getSentryUserID: () => Promise; getAppVersion: () => Promise; runFFmpegCmd: ( cmd: string[], @@ -101,7 +100,6 @@ export interface ElectronAPIsType { deleteFolder: (path: string) => Promise; deleteFile: (path: string) => void; rename: (oldPath: string, newPath: string) => Promise; - updateOptOutOfCrashReports: (optOut: boolean) => Promise; computeImageEmbedding: ( model: Model, imageData: Uint8Array, diff --git a/web/packages/shared/electron/worker/client.ts b/web/packages/shared/electron/worker/client.ts index 12b34a4e7..92db7d972 100644 --- a/web/packages/shared/electron/worker/client.ts +++ b/web/packages/shared/electron/worker/client.ts @@ -9,7 +9,6 @@ export interface ProxiedLimitedElectronAPIs { cacheLimitInBytes?: number, ) => Promise; deleteDiskCache: (cacheName: string) => Promise; - getSentryUserID: () => Promise; convertToJPEG: ( inputFileData: Uint8Array, filename: string, @@ -42,10 +41,6 @@ export class WorkerSafeElectronClient implements ProxiedLimitedElectronAPIs { return await ElectronAPIs.deleteDiskCache(cacheName); } - async getSentryUserID() { - return await ElectronAPIs.getSentryUserID(); - } - async convertToJPEG( inputFileData: Uint8Array, filename: string, diff --git a/web/packages/shared/error/index.ts b/web/packages/shared/error/index.ts index 0463c9610..be8f10cea 100644 --- a/web/packages/shared/error/index.ts +++ b/web/packages/shared/error/index.ts @@ -109,15 +109,6 @@ export function handleUploadError(error: any): Error { return parsedError; } -export 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 parseUploadErrorCodes(error: any) { let parsedMessage = null; if (error instanceof ApiError) { diff --git a/web/packages/shared/logging/web.ts b/web/packages/shared/logging/web.ts index e0c36dc89..235406735 100644 --- a/web/packages/shared/logging/web.ts +++ b/web/packages/shared/logging/web.ts @@ -7,7 +7,6 @@ import { setData, } from "@ente/shared/storage/localStorage"; import { addLogLine } from "."; -import { getSentryUserID } from "../sentry/utils"; import { formatDateTimeShort } from "../time/format"; import { ElectronFile } from "../upload/types"; import type { User } from "../user/types"; @@ -75,10 +74,9 @@ export const logStartupMessage = async (appId: string) => { // TODO (MR): Remove the need to lowercase it, change the enum itself. const appIdL = appId.toLowerCase(); const userID = (getData(LS_KEYS.USER) as User)?.id; - const sentryID = await getSentryUserID(); const buildId = isDevBuild ? "dev" : `git ${process.env.GIT_SHA}`; - addLogLine(`ente-${appIdL}-web ${buildId} uid ${userID} sid ${sentryID}`); + addLogLine(`ente-${appIdL}-web ${buildId} uid ${userID}`); }; function getLogs(): Log[] { diff --git a/web/packages/shared/next/pages/_error.tsx b/web/packages/shared/next/pages/_error.tsx deleted file mode 100644 index c0fc2e39f..000000000 --- a/web/packages/shared/next/pages/_error.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import * as Sentry from "@sentry/nextjs"; -import NextErrorComponent from "next/error"; - -const CustomErrorComponent = (props) => ( - -); - -CustomErrorComponent.getInitialProps = async (contextData) => { - // In case this is running in a serverless function, await this in order to give Sentry - // time to send the error before the lambda exits - await Sentry.captureUnderscoreErrorException(contextData); - - // This will contain the status code of the response - return NextErrorComponent.getInitialProps(contextData); -}; - -export default CustomErrorComponent; diff --git a/web/packages/shared/package.json b/web/packages/shared/package.json index b4d4e1671..807fdd7e6 100644 --- a/web/packages/shared/package.json +++ b/web/packages/shared/package.json @@ -5,7 +5,6 @@ "dependencies": { "@/next": "*", "@ente/eslint-config": "*", - "@sentry/nextjs": "7.77.0", "axios": "^1.6.7" } } diff --git a/web/packages/shared/sentry/config/sentry.config.base.ts b/web/packages/shared/sentry/config/sentry.config.base.ts deleted file mode 100644 index d37572de6..000000000 --- a/web/packages/shared/sentry/config/sentry.config.base.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { isDevBuild } from "@/utils/env"; -import { runningInBrowser } from "@ente/shared/platform"; -import { getSentryUserID } from "@ente/shared/sentry/utils"; -import { getHasOptedOutOfCrashReports } from "@ente/shared/storage/localStorage/helpers"; -import * as Sentry from "@sentry/nextjs"; - -export const initSentry = async (dsn: string) => { - // Don't initialize Sentry for dev builds - if (isDevBuild) return; - - // Don't initialize Sentry if the user has opted out of crash reporting - if (optedOut()) return; - - Sentry.init({ - dsn, - release: process.env.GIT_SHA, - attachStacktrace: true, - autoSessionTracking: false, - tunnel: "https://sentry-reporter.ente.io", - beforeSend(event) { - event.request = event.request || {}; - const currentURL = new URL(document.location.href); - currentURL.hash = ""; - event.request.url = currentURL.href; - return event; - }, - integrations: function (i) { - return i.filter(function (i) { - return i.name !== "Breadcrumbs"; - }); - }, - }); - - Sentry.setUser({ id: await getSentryUserID() }); -}; - -/** Return true if the user has opted out of crash reporting */ -const optedOut = () => runningInBrowser() && getHasOptedOutOfCrashReports(); diff --git a/web/packages/shared/sentry/index.ts b/web/packages/shared/sentry/index.ts index 9279c1134..2dae035b7 100644 --- a/web/packages/shared/sentry/index.ts +++ b/web/packages/shared/sentry/index.ts @@ -1,59 +1,27 @@ -import { ApiError, errorWithContext } from "@ente/shared/error"; -import { addLocalLog, addLogLine } from "@ente/shared/logging"; -import { - getSentryUserID, - isErrorUnnecessaryForSentry, -} from "@ente/shared/sentry/utils"; -import InMemoryStore, { MS_KEYS } from "@ente/shared/storage/InMemoryStore"; -import { getHasOptedOutOfCrashReports } from "@ente/shared/storage/localStorage/helpers"; -import * as Sentry from "@sentry/nextjs"; +import { ApiError } from "@ente/shared/error"; +import { addLogLine } from "@ente/shared/logging"; +/** Deprecated: Use `logError` from `@/utils/logging` */ export const logError = async ( error: any, msg: string, info?: Record, skipAddLogLine = false, ) => { - const err = errorWithContext(error, msg); - if (!skipAddLogLine) { - if (error instanceof ApiError) { - addLogLine(`error: ${error?.name} ${error?.message} + if (skipAddLogLine) return; + + if (error instanceof ApiError) { + addLogLine(`error: ${error?.name} ${error?.message} msg: ${msg} errorCode: ${JSON.stringify(error?.errCode)} httpStatusCode: ${JSON.stringify(error?.httpStatusCode)} ${ info ? `info: ${JSON.stringify(info)}` : "" } ${error?.stack}`); - } else { - addLogLine( - `error: ${error?.name} ${error?.message} + } else { + addLogLine( + `error: ${error?.name} ${error?.message} msg: ${msg} ${info ? `info: ${JSON.stringify(info)}` : ""} ${error?.stack}`, - ); - } - } - if (!InMemoryStore.has(MS_KEYS.OPT_OUT_OF_CRASH_REPORTS)) { - const optedOutOfCrashReports = getHasOptedOutOfCrashReports(); - InMemoryStore.set( - MS_KEYS.OPT_OUT_OF_CRASH_REPORTS, - optedOutOfCrashReports, ); } - if (InMemoryStore.get(MS_KEYS.OPT_OUT_OF_CRASH_REPORTS)) { - addLocalLog(() => `skipping sentry error: ${error?.name}`); - return; - } - if (isErrorUnnecessaryForSentry(error)) { - return; - } - - Sentry.captureException(err, { - level: "info", - user: { id: await getSentryUserID() }, - contexts: { - ...(info && { - info: info, - }), - rootCause: { message: error?.message, completeError: error }, - }, - }); }; diff --git a/web/packages/shared/sentry/utils.ts b/web/packages/shared/sentry/utils.ts deleted file mode 100644 index 258db570e..000000000 --- a/web/packages/shared/sentry/utils.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { WorkerSafeElectronService } from "@ente/shared/electron/service"; -import { - getLocalSentryUserID, - setLocalSentryUserID, -} from "@ente/shared/storage/localStorage/helpers"; -import { HttpStatusCode } from "axios"; -import isElectron from "is-electron"; -import { ApiError } from "../error"; - -export async function getSentryUserID() { - if (isElectron()) { - return await WorkerSafeElectronService.getSentryUserID(); - } else { - let anonymizeUserID = getLocalSentryUserID(); - if (!anonymizeUserID) { - anonymizeUserID = makeID(6); - setLocalSentryUserID(anonymizeUserID); - } - return anonymizeUserID; - } -} - -function makeID(length) { - 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 isErrorUnnecessaryForSentry(error: any) { - if (error?.message?.includes("Network Error")) { - return true; - } else if ( - error instanceof ApiError && - error.httpStatusCode === HttpStatusCode.Unauthorized - ) { - return true; - } - return false; -} diff --git a/web/packages/shared/storage/InMemoryStore.ts b/web/packages/shared/storage/InMemoryStore.ts index ded73faf0..88e77b869 100644 --- a/web/packages/shared/storage/InMemoryStore.ts +++ b/web/packages/shared/storage/InMemoryStore.ts @@ -1,5 +1,4 @@ export enum MS_KEYS { - OPT_OUT_OF_CRASH_REPORTS = "optOutOfCrashReports", SRP_CONFIGURE_IN_PROGRESS = "srpConfigureInProgress", REDIRECT_URL = "redirectUrl", } diff --git a/web/packages/shared/storage/localStorage/helpers.ts b/web/packages/shared/storage/localStorage/helpers.ts index d8092a56a..95ae280e3 100644 --- a/web/packages/shared/storage/localStorage/helpers.ts +++ b/web/packages/shared/storage/localStorage/helpers.ts @@ -37,18 +37,6 @@ export function setLocalMapEnabled(value: boolean) { setData(LS_KEYS.MAP_ENABLED, { value }); } -export function getHasOptedOutOfCrashReports(): boolean { - return getData(LS_KEYS.OPT_OUT_OF_CRASH_REPORTS)?.value ?? false; -} - -export function getLocalSentryUserID() { - return getData(LS_KEYS.AnonymizedUserID)?.id; -} - -export function setLocalSentryUserID(id: string) { - setData(LS_KEYS.AnonymizedUserID, { id }); -} - export function getLocalReferralSource() { return getData(LS_KEYS.REFERRAL_SOURCE)?.source; } diff --git a/web/packages/shared/storage/localStorage/index.ts b/web/packages/shared/storage/localStorage/index.ts index e40b64457..14901fdd4 100644 --- a/web/packages/shared/storage/localStorage/index.ts +++ b/web/packages/shared/storage/localStorage/index.ts @@ -12,7 +12,6 @@ export enum LS_KEYS { JUST_SIGNED_UP = "justSignedUp", SHOW_BACK_BUTTON = "showBackButton", EXPORT = "export", - AnonymizedUserID = "anonymizedUserID", THUMBNAIL_FIX_STATE = "thumbnailFixState", LIVE_PHOTO_INFO_SHOWN_COUNT = "livePhotoInfoShownCount", LOGS = "logs", @@ -26,7 +25,6 @@ export enum LS_KEYS { MAP_ENABLED = "mapEnabled", SRP_SETUP_ATTRIBUTES = "srpSetupAttributes", SRP_ATTRIBUTES = "srpAttributes", - OPT_OUT_OF_CRASH_REPORTS = "optOutOfCrashReports", CF_PROXY_DISABLED = "cfProxyDisabled", REFERRAL_SOURCE = "referralSource", CLIENT_PACKAGE = "clientPackage", diff --git a/web/packages/utils/logging.ts b/web/packages/utils/logging.ts index b3d7d8567..cd9c4b53b 100644 --- a/web/packages/utils/logging.ts +++ b/web/packages/utils/logging.ts @@ -17,7 +17,7 @@ * * TODO (MR): Currently this is a placeholder function to funnel error logs * through. This needs to do what the existing logError in @ente/shared does, - * but it cannot have a direct Electron/Sentry dependency here. For now, we just + * but it cannot have a direct Electron dependency here. For now, we just * log on the console. */ export const logError = (message: string, e?: unknown) => { @@ -35,5 +35,7 @@ export const logError = (message: string, e?: unknown) => { // For the rest rare cases, use the default string serialization of e. es = String(e); } + + // TODO(MR): Use addLogLine console.error(`${message}: ${es}`); }; diff --git a/web/yarn.lock b/web/yarn.lock index 134ed421d..4e31afe7e 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -302,11 +302,6 @@ wrap-ansi "^8.1.0" wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" -"@jridgewell/sourcemap-codec@^1.4.13": - version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== - "@mui/base@5.0.0-beta.36": version "5.0.0-beta.36" resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-beta.36.tgz#29ca2de9d387f6d3943b6f18a84415c43e5f206c" @@ -538,161 +533,11 @@ dependencies: dequal "^2.0.3" -"@rollup/plugin-commonjs@24.0.0": - version "24.0.0" - resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-24.0.0.tgz#fb7cf4a6029f07ec42b25daa535c75b05a43f75c" - integrity sha512-0w0wyykzdyRRPHOb0cQt14mIBLujfAv6GgP6g8nvg/iBxEm112t3YPPq+Buqe2+imvElTka+bjNlJ/gB56TD8g== - dependencies: - "@rollup/pluginutils" "^5.0.1" - commondir "^1.0.1" - estree-walker "^2.0.2" - glob "^8.0.3" - is-reference "1.2.1" - magic-string "^0.27.0" - -"@rollup/pluginutils@^5.0.1": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.1.0.tgz#7e53eddc8c7f483a4ad0b94afb1f7f5fd3c771e0" - integrity sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g== - dependencies: - "@types/estree" "^1.0.0" - estree-walker "^2.0.2" - picomatch "^2.3.1" - "@rushstack/eslint-patch@^1.3.3": version "1.7.2" resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.7.2.tgz#2d4260033e199b3032a08b41348ac10de21c47e9" integrity sha512-RbhOOTCNoCrbfkRyoXODZp75MlpiHMgbE5MEBZAnnnLyQNgrigEj4p0lzsMDyc1zVsJDLrivB58tgg3emX0eEA== -"@sentry-internal/tracing@7.77.0": - version "7.77.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.77.0.tgz#f3d82486f8934a955b3dd2aa54c8d29586e42a37" - integrity sha512-8HRF1rdqWwtINqGEdx8Iqs9UOP/n8E0vXUu3Nmbqj4p5sQPA7vvCfq+4Y4rTqZFc7sNdFpDsRION5iQEh8zfZw== - dependencies: - "@sentry/core" "7.77.0" - "@sentry/types" "7.77.0" - "@sentry/utils" "7.77.0" - -"@sentry/browser@7.77.0": - version "7.77.0" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.77.0.tgz#155440f1a0d3a1bbd5d564c28d6b0c9853a51d72" - integrity sha512-nJ2KDZD90H8jcPx9BysQLiQW+w7k7kISCWeRjrEMJzjtge32dmHA8G4stlUTRIQugy5F+73cOayWShceFP7QJQ== - dependencies: - "@sentry-internal/tracing" "7.77.0" - "@sentry/core" "7.77.0" - "@sentry/replay" "7.77.0" - "@sentry/types" "7.77.0" - "@sentry/utils" "7.77.0" - -"@sentry/cli@1.75.0", "@sentry/cli@^1.74.6": - version "1.75.0" - resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-1.75.0.tgz#4a5e71b5619cd4e9e6238cc77857c66f6b38d86a" - integrity sha512-vT8NurHy00GcN8dNqur4CMIYvFH3PaKdkX3qllVvi4syybKqjwoz+aWRCvprbYv0knweneFkLt1SmBWqazUMfA== - dependencies: - https-proxy-agent "^5.0.0" - mkdirp "^0.5.5" - node-fetch "^2.6.7" - progress "^2.0.3" - proxy-from-env "^1.1.0" - which "^2.0.2" - -"@sentry/core@7.77.0": - version "7.77.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.77.0.tgz#21100843132beeeff42296c8370cdcc7aa1d8510" - integrity sha512-Tj8oTYFZ/ZD+xW8IGIsU6gcFXD/gfE+FUxUaeSosd9KHwBQNOLhZSsYo/tTVf/rnQI/dQnsd4onPZLiL+27aTg== - dependencies: - "@sentry/types" "7.77.0" - "@sentry/utils" "7.77.0" - -"@sentry/integrations@7.77.0": - version "7.77.0" - resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-7.77.0.tgz#f2717e05cb7c69363316ccd34096b2ea07ae4c59" - integrity sha512-P055qXgBHeZNKnnVEs5eZYLdy6P49Zr77A1aWJuNih/EenzMy922GOeGy2mF6XYrn1YJSjEwsNMNsQkcvMTK8Q== - dependencies: - "@sentry/core" "7.77.0" - "@sentry/types" "7.77.0" - "@sentry/utils" "7.77.0" - localforage "^1.8.1" - -"@sentry/nextjs@7.77.0": - version "7.77.0" - resolved "https://registry.yarnpkg.com/@sentry/nextjs/-/nextjs-7.77.0.tgz#036b1c45dd106e01d44967c97985464e108922be" - integrity sha512-8tYPBt5luFjrng1sAMJqNjM9sq80q0jbt6yariADU9hEr7Zk8YqFaOI2/Q6yn9dZ6XyytIRtLEo54kk2AO94xw== - dependencies: - "@rollup/plugin-commonjs" "24.0.0" - "@sentry/core" "7.77.0" - "@sentry/integrations" "7.77.0" - "@sentry/node" "7.77.0" - "@sentry/react" "7.77.0" - "@sentry/types" "7.77.0" - "@sentry/utils" "7.77.0" - "@sentry/vercel-edge" "7.77.0" - "@sentry/webpack-plugin" "1.20.0" - chalk "3.0.0" - resolve "1.22.8" - rollup "2.78.0" - stacktrace-parser "^0.1.10" - -"@sentry/node@7.77.0": - version "7.77.0" - resolved "https://registry.yarnpkg.com/@sentry/node/-/node-7.77.0.tgz#a247452779a5bcb55724457707286e3e4a29dbbe" - integrity sha512-Ob5tgaJOj0OYMwnocc6G/CDLWC7hXfVvKX/ofkF98+BbN/tQa5poL+OwgFn9BA8ud8xKzyGPxGU6LdZ8Oh3z/g== - dependencies: - "@sentry-internal/tracing" "7.77.0" - "@sentry/core" "7.77.0" - "@sentry/types" "7.77.0" - "@sentry/utils" "7.77.0" - https-proxy-agent "^5.0.0" - -"@sentry/react@7.77.0": - version "7.77.0" - resolved "https://registry.yarnpkg.com/@sentry/react/-/react-7.77.0.tgz#9da14e4b21eae4b5a6306d39bb7c42ef0827d2c2" - integrity sha512-Q+htKzib5em0MdaQZMmPomaswaU3xhcVqmLi2CxqQypSjbYgBPPd+DuhrXKoWYLDDkkbY2uyfe4Lp3yLRWeXYw== - dependencies: - "@sentry/browser" "7.77.0" - "@sentry/types" "7.77.0" - "@sentry/utils" "7.77.0" - hoist-non-react-statics "^3.3.2" - -"@sentry/replay@7.77.0": - version "7.77.0" - resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-7.77.0.tgz#21d242c9cd70a7235237216174873fd140b6eb80" - integrity sha512-M9Ik2J5ekl+C1Och3wzLRZVaRGK33BlnBwfwf3qKjgLDwfKW+1YkwDfTHbc2b74RowkJbOVNcp4m8ptlehlSaQ== - dependencies: - "@sentry-internal/tracing" "7.77.0" - "@sentry/core" "7.77.0" - "@sentry/types" "7.77.0" - "@sentry/utils" "7.77.0" - -"@sentry/types@7.77.0": - version "7.77.0" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.77.0.tgz#c5d00fe547b89ccde59cdea59143bf145cee3144" - integrity sha512-nfb00XRJVi0QpDHg+JkqrmEBHsqBnxJu191Ded+Cs1OJ5oPXEW6F59LVcBScGvMqe+WEk1a73eH8XezwfgrTsA== - -"@sentry/utils@7.77.0": - version "7.77.0" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.77.0.tgz#1f88501f0b8777de31b371cf859d13c82ebe1379" - integrity sha512-NmM2kDOqVchrey3N5WSzdQoCsyDkQkiRxExPaNI2oKQ/jMWHs9yt0tSy7otPBcXs0AP59ihl75Bvm1tDRcsp5g== - dependencies: - "@sentry/types" "7.77.0" - -"@sentry/vercel-edge@7.77.0": - version "7.77.0" - resolved "https://registry.yarnpkg.com/@sentry/vercel-edge/-/vercel-edge-7.77.0.tgz#6a90a869878e4e78803c4331c30aea841fcc6a73" - integrity sha512-ffddPCgxVeAccPYuH5sooZeHBqDuJ9OIhIRYKoDi4TvmwAzWo58zzZWhRpkHqHgIQdQvhLVZ5F+FSQVWnYSOkw== - dependencies: - "@sentry/core" "7.77.0" - "@sentry/types" "7.77.0" - "@sentry/utils" "7.77.0" - -"@sentry/webpack-plugin@1.20.0": - version "1.20.0" - resolved "https://registry.yarnpkg.com/@sentry/webpack-plugin/-/webpack-plugin-1.20.0.tgz#e7add76122708fb6b4ee7951294b521019720e58" - integrity sha512-Ssj1mJVFsfU6vMCOM2d+h+KQR7QHSfeIP16t4l20Uq/neqWXZUQ2yvQfe4S3BjdbJXz/X4Rw8Hfy1Sd0ocunYw== - dependencies: - "@sentry/cli" "^1.74.6" - webpack-sources "^2.0.0 || ^3.0.0" - "@stripe/stripe-js@^1.13.2": version "1.54.2" resolved "https://registry.yarnpkg.com/@stripe/stripe-js/-/stripe-js-1.54.2.tgz#0665848e22cbda936cfd05256facdfbba121438d" @@ -764,11 +609,6 @@ "@types/node" "*" base-x "^3.0.6" -"@types/estree@*", "@types/estree@^1.0.0": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" - integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== - "@types/geojson@*": version "7946.0.14" resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.14.tgz#319b63ad6df705ee2a65a73ef042c8271e696613" @@ -1127,13 +967,6 @@ acorn@^8.0.4, acorn@^8.9.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== -agent-base@6: - version "6.0.2" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" - integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== - dependencies: - debug "4" - ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -1444,14 +1277,6 @@ caniuse-lite@^1.0.30001579: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001589.tgz#7ad6dba4c9bf6561aec8291976402339dc157dfb" integrity sha512-vNQWS6kI+q6sBlHbh71IIeC+sRwK2N3EDySc/updIGhIee2x5z00J4c1242/5/d6EpEMdOnk/m+6tuk4/tcsqg== -chalk@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" - integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -1552,11 +1377,6 @@ commander@^7.2.0: resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -1631,13 +1451,6 @@ debounce@^2.0.0: resolved "https://registry.yarnpkg.com/debounce/-/debounce-2.0.0.tgz#b2f914518a1481466f4edaee0b063e4d473ad549" integrity sha512-xRetU6gL1VJbs85Mc4FoEGSjQxzpdxRyFhe3lmWFyy2EzydIcD4xzUvRJMD+NPDfMwKNhxa3PvsIOU32luIWeA== -debug@4, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -1645,6 +1458,13 @@ debug@^3.2.7: dependencies: ms "^2.1.1" +debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" @@ -2100,11 +1920,6 @@ estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== -estree-walker@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" - integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== - esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -2378,17 +2193,6 @@ glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^8.0.3: - version "8.1.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" - integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^5.0.1" - once "^1.3.0" - globals@^13.19.0: version "13.24.0" resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" @@ -2519,7 +2323,7 @@ heic-decode@^2.0.0: dependencies: libheif-js "^1.17.1" -hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2: +hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== @@ -2549,14 +2353,6 @@ html-tokenize@^2.0.0: readable-stream "~1.0.27-1" through2 "~0.4.1" -https-proxy-agent@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" - integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== - dependencies: - agent-base "6" - debug "4" - i18next-http-backend@^2.5: version "2.5.0" resolved "https://registry.yarnpkg.com/i18next-http-backend/-/i18next-http-backend-2.5.0.tgz#8396a7df30bfe722eff7a65f629df32a61720414" @@ -2777,13 +2573,6 @@ is-plain-object@^5.0.0: resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== -is-reference@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" - integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ== - dependencies: - "@types/estree" "*" - is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" @@ -3032,7 +2821,7 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== -localforage@^1.8.1, localforage@^1.9.0: +localforage@^1.9.0: version "1.10.0" resolved "https://registry.yarnpkg.com/localforage/-/localforage-1.10.0.tgz#5c465dc5f62b2807c3a84c0c6a1b1b3212781dd4" integrity sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg== @@ -3090,13 +2879,6 @@ lru-cache@^6.0.0: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3" integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q== -magic-string@^0.27.0: - version "0.27.0" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.27.0.tgz#e4a3413b4bab6d98d2becffd48b4a257effdbbf3" - integrity sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA== - dependencies: - "@jridgewell/sourcemap-codec" "^1.4.13" - "memoize-one@>=3.1.1 <6", memoize-one@^5.0.0: version "5.2.1" resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" @@ -3146,13 +2928,6 @@ minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" -minimatch@^5.0.1: - version "5.1.6" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" - integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== - dependencies: - brace-expansion "^2.0.1" - minimist@^1.2.0, minimist@^1.2.6, minimist@~1.2.5: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" @@ -3163,13 +2938,6 @@ minimist@^1.2.0, minimist@^1.2.6, minimist@~1.2.5: resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== -mkdirp@^0.5.5: - version "0.5.6" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" - integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== - dependencies: - minimist "^1.2.6" - ml-array-max@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/ml-array-max/-/ml-array-max-1.2.4.tgz#2373e2b7e51c8807e456cc0ef364c5863713623b" @@ -3257,7 +3025,7 @@ next@^14.1: "@next/swc-win32-ia32-msvc" "14.1.0" "@next/swc-win32-x64-msvc" "14.1.0" -node-fetch@^2.6.12, node-fetch@^2.6.7: +node-fetch@^2.6.1, node-fetch@^2.6.12: version "2.7.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== @@ -3540,11 +3308,6 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== -progress@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== - prop-types-extra@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/prop-types-extra/-/prop-types-extra-1.1.1.tgz#58c3b74cbfbb95d304625975aa2f0848329a010b" @@ -3838,7 +3601,7 @@ resolve-pkg-maps@^1.0.0: resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== -resolve@1.22.8, resolve@^1.19.0, resolve@^1.22.4: +resolve@^1.19.0, resolve@^1.22.4: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== @@ -3873,13 +3636,6 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" -rollup@2.78.0: - version "2.78.0" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.78.0.tgz#00995deae70c0f712ea79ad904d5f6b033209d9e" - integrity sha512-4+YfbQC9QEVvKTanHhIAFVUFSRsezvQF8vFOJwtGfb9Bb+r014S+qryr9PSmw8x6sMnPkmFBGAvIFVQxvJxjtg== - optionalDependencies: - fsevents "~2.3.2" - run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -4067,13 +3823,6 @@ source-map@^0.5.7: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== -stacktrace-parser@^0.1.10: - version "0.1.10" - resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" - integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== - dependencies: - type-fest "^0.7.1" - streamsearch@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" @@ -4342,11 +4091,6 @@ type-fest@^0.20.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== -type-fest@^0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" - integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== - type-fest@^2.19.0: version "2.19.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" @@ -4489,11 +4233,6 @@ webpack-bundle-analyzer@4.10.1: sirv "^2.0.3" ws "^7.3.1" -"webpack-sources@^2.0.0 || ^3.0.0": - version "3.2.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" - integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== - whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" @@ -4552,7 +4291,7 @@ which-typed-array@^1.1.14, which-typed-array@^1.1.9: gopd "^1.0.1" has-tostringtag "^1.0.1" -which@^2.0.1, which@^2.0.2: +which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==