diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..d5314d13e --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +ui/* diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 26602518b..cc1f66b0f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,53 +6,52 @@ on: - v* jobs: - release: - runs-on: ${{ matrix.os }} + release: + runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [macos-latest, ubuntu-latest, windows-latest] + strategy: + matrix: + os: [macos-latest, ubuntu-latest, windows-latest] - steps: - - name: Check out Git repository - uses: actions/checkout@v2 - with: - submodules: recursive + steps: + - name: Check out Git repository + uses: actions/checkout@v3 + with: + submodules: recursive - - name: Install Node.js, NPM and Yarn - uses: actions/setup-node@v2.1.5 - with: - node-version: 14 + - name: Install Node.js, NPM and Yarn + uses: actions/setup-node@v3 + with: + node-version: 16 - - name: Prepare for app notarization - if: startsWith(matrix.os, 'macos') - # Import Apple API key for app notarization on macOS - run: | - mkdir -p ~/private_keys/ - echo '${{ secrets.api_key }}' > ~/private_keys/AuthKey_${{ secrets.api_key_id }}.p8 + - name: Prepare for app notarization + if: startsWith(matrix.os, 'macos') + # Import Apple API key for app notarization on macOS + run: | + mkdir -p ~/private_keys/ + echo '${{ secrets.api_key }}' > ~/private_keys/AuthKey_${{ secrets.api_key_id }}.p8 - - name: Install libarchive-tools for pacman build # Related https://github.com/electron-userland/electron-builder/issues/4181 - if: startsWith(matrix.os, 'ubuntu') - run: sudo apt-get install libarchive-tools + - name: Install libarchive-tools for pacman build # Related https://github.com/electron-userland/electron-builder/issues/4181 + if: startsWith(matrix.os, 'ubuntu') + run: sudo apt-get install libarchive-tools - - name: Electron Builder Action - uses: samuelmeuli/action-electron-builder@v1.6.0 - with: - # GitHub token, automatically provided to the action - # (No need to define this secret in the repo settings) - github_token: ${{ secrets.github_token }} + - name: Ente Electron Builder Action + uses: ente-io/action-electron-builder@v1.0.0 + with: + # GitHub token, automatically provided to the action + # (No need to define this secret in the repo settings) + github_token: ${{ secrets.github_token }} - # If the commit is tagged with a version (e.g. "v1.0.0"), - # release the app after building - release: ${{ startsWith(github.ref, 'refs/tags/v') }} - - mac_certs: ${{ secrets.mac_certs }} - mac_certs_password: ${{ secrets.mac_certs_password }} - env: - # 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}} - USE_HARD_LINKS: false + # If the commit is tagged with a version (e.g. "v1.0.0"), + # release the app after building + release: ${{ startsWith(github.ref, 'refs/tags/v') }} + mac_certs: ${{ secrets.mac_certs }} + mac_certs_password: ${{ secrets.mac_certs_password }} + env: + # 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}} + USE_HARD_LINKS: false diff --git a/.github/workflows/cla.yaml b/.github/workflows/cla.yaml new file mode 100644 index 000000000..25340ec9f --- /dev/null +++ b/.github/workflows/cla.yaml @@ -0,0 +1,38 @@ +name: "CLA Assistant" +on: + issue_comment: + types: [created] + pull_request_target: + types: [opened, closed, synchronize] + +jobs: + CLAAssistant: + # This job only runs for pull request comments + if: ${{ github.event.issue.pull_request }} + runs-on: ubuntu-latest + steps: + - name: "CLA Assistant" + if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target' + # Beta Release + uses: contributor-assistant/github-action@v2.2.1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # the below token should have repo scope and must be manually added by you in the repository's secret + PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }} + with: + path-to-signatures: "signatures/version1/cla.json" + path-to-document: "https://github.com/ente-io/cla/blob/main/CLA.md" # e.g. a CLA or a DCO document + # branch should not be protected + branch: "main" + allowlist: enteio + + # the followings are the optional inputs - If the optional inputs are not given, then default values will be taken + #remote-organization-name: enter the remote organization name where the signatures should be stored (Default is storing the signatures in the same repository) + remote-repository-name: cla + #create-file-commit-message: 'For example: Creating file for storing CLA Signatures' + #signed-commit-message: 'For example: $contributorName has signed the CLA in #$pullRequestNo' + #custom-notsigned-prcomment: 'pull request comment with Introductory message to ask new contributors to sign' + #custom-pr-sign-comment: 'The signature to be committed in order to sign the CLA' + #custom-allsigned-prcomment: 'pull request comment when all contributors has signed, defaults to **CLA Assistant Lite bot** All Contributors have signed the CLA.' + #lock-pullrequest-aftermerge: false - if you don't want this bot to automatically lock the pull request after merging (default - true) + #use-dco-flag: true - If you are using DCO instead of CLA diff --git a/CLA.md b/CLA.md new file mode 100644 index 000000000..71c216537 --- /dev/null +++ b/CLA.md @@ -0,0 +1,98 @@ +## Contributor License Agreement + +Thank you for your contribution to ente projects. + +This contributor license agreement documents the rights granted by contributors +to Ente Technologies, Inc ("ente"). This license is for your protection as a +Contributor as well as the protection of ente, its users, and its licensees; you +may still license your own Contributions under other terms. + +In exchange for the ability to participate in the ente community and for other +good consideration, the receipt of which is hereby acknowledged, you accept and +agree to the following terms and conditions for Your present and future +Contributions submitted to ente. Except for the license granted herein to ente +and recipients of software distributed by ente, You reserve all right, title, +and interest in and to Your Contributions. + +1. Definitions. + + "You" (or "Your") shall mean the copyright owner or legal entity authorized + by the copyright owner that is making this Agreement with ente. For legal + entities, the entity making a Contribution and all other entities that + control, are controlled by, or are under common control with that entity are + considered to be a single Contributor. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the direction or + management of such entity, whether by contract or otherwise, or (ii) + ownership of fifty percent (50%) or more of the outstanding shares, or (iii) + beneficial ownership of such entity. + + "Contribution" shall mean any original work of authorship or invention, + including any modifications or additions to an existing work, that is + intentionally submitted by You to ente for inclusion in, or documentation of, + any of the products owned or managed by ente (the "Work"). For the purposes + of this definition, "submitted" means any form of electronic, verbal, or + written communication sent to ente or its representatives, including but not + limited to communication on electronic mailing lists, source code control + systems, and issue tracking systems that are managed by, or on behalf of, + ente for the purpose of discussing and improving the Work, but excluding + communication that is conspicuously marked or otherwise designated in writing + by You as "Not a Contribution." + +2. Grant of Copyright License. Subject to the terms and conditions of this + Agreement, You hereby grant to ente and to recipients of software distributed + by ente a perpetual, worldwide, non-exclusive, no-charge, royalty-free, + irrevocable copyright license to reproduce, prepare derivative works of, + publicly display, publicly perform, and distribute Your Contributions and + such derivative works. + +3. Grant of Patent License. Subject to the terms and conditions of this + Agreement, You hereby grant to ente and to recipients of software distributed + by ente a perpetual, worldwide, non-exclusive, no-charge, royalty-free, + irrevocable (except as stated in this section) patent license to make, have + made, use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable by You that + are necessarily infringed by Your Contribution(s) alone or by combination of + Your Contribution(s) with the Work to which such Contribution(s) was + submitted. If any entity institutes patent litigation against You or any + other entity (including a cross-claim or counterclaim in a lawsuit) alleging + that your Contribution, or the Work to which you have contributed, + constitutes direct or contributory patent infringement, then any patent + licenses granted to that entity under this Agreement for that Contribution or + Work shall terminate as of the date such litigation is filed. + +4. You represent that you are legally entitled to grant the above license. If + your employer(s) has rights to intellectual property that you create that + includes your Contributions, you represent that you have received permission + to make Contributions on behalf of that employer, that your employer has + waived such rights for your contributions to ente, or that your employer has + executed with ente a separate contributor license agreement substantially + similar to this Agreement. If You are a current employee or contractor of + ente, then the terms of your existing Employment Agreement or Consulting + Services Agreement shall supersede this CLA, and remain in full effect. + +5. You represent that each of Your Contributions is Your original creation (see + section 7 for submissions on behalf of others). You represent that Your + Contribution submissions include complete details of any third-party license + or other restriction (including, but not limited to, related patents and + trademarks) of which you are personally aware and which are associated with + any part of Your Contributions. + +6. You are not expected to provide support for Your Contributions, except to the + extent You desire to provide support. You may provide support for free, for + a fee, or not at all. Unless required by applicable law or agreed to in + writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT + WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, + without limitation, any warranties or conditions of title, non-infringement, + merchantability, or fitness for a particular purpose. + +7. Should You wish to submit work that is not Your original creation, You may + submit it to ente separately from any Contribution, identifying the complete + details of its source and of any license or other restriction (including, but + not limited to, related patents, trademarks, and license agreements) of which + you are personally aware, and conspicuously marking the work as "Not a + Contribution". Third-party materials licensed pursuant to: [license name(s) + here]" (substituting the bracketed text with the appropriate license + name(s)). + +8. You agree to notify ente of any facts or circumstances of which you become + aware that would make these representations inaccurate in any respect. diff --git a/build/error.html b/build/error.html index a0199f702..54b787357 100644 --- a/build/error.html +++ b/build/error.html @@ -5,7 +5,7 @@ - ente.io | encrypted photo storage - loading failed + ente Photos diff --git a/build/splash.html b/build/splash.html index a06f23d8e..776f375f8 100644 --- a/build/splash.html +++ b/build/splash.html @@ -5,7 +5,7 @@ - ente.io | encrypted photo storage + ente Photos diff --git a/package.json b/package.json index 73c0563c8..ca78edd61 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "ente", "productName": "ente", - "version": "1.6.18-alpha.1", + "version": "1.6.20", "private": true, "description": "Desktop client for ente.io", "main": "app/main.js", @@ -68,7 +68,7 @@ "start": "concurrently \"yarn start-main\" \"yarn start-renderer\"", "build-renderer": "cd ui && yarn install && yarn build && cd ..", "build": "yarn build-renderer && yarn build-main", - "test-release": "yarn build && electron-builder --config.compression=store" + "test-release": "cross-env IS_TEST_RELEASE=true yarn build && electron-builder --config.compression=store" }, "author": "ente ", "devDependencies": { @@ -83,6 +83,7 @@ "@typescript-eslint/eslint-plugin": "^5.28.0", "@typescript-eslint/parser": "^5.28.0", "concurrently": "^7.0.0", + "cross-env": "^7.0.3", "electron": "^21.2.2", "electron-builder": "^23.0.3", "electron-builder-notarize": "^1.2.0", diff --git a/src/api/imageProcessor.ts b/src/api/imageProcessor.ts index 61b0ae529..b4464233f 100644 --- a/src/api/imageProcessor.ts +++ b/src/api/imageProcessor.ts @@ -1,10 +1,15 @@ +import { CustomErrors } from '../constants/errors'; import { ipcRenderer } from 'electron/renderer'; import { existsSync } from 'fs'; import { writeStream } from '../services/fs'; import { logError } from '../services/logging'; import { ElectronFile } from '../types'; +import { isPlatform } from '../utils/common/platform'; export async function convertHEIC(fileData: Uint8Array): Promise { + if (isPlatform('windows')) { + throw Error(CustomErrors.WINDOWS_NATIVE_IMAGE_PROCESSING_NOT_SUPPORTED); + } const convertedFileData = await ipcRenderer.invoke( 'convert-heic', fileData @@ -20,6 +25,11 @@ export async function generateImageThumbnail( let inputFilePath = null; let createdTempInputFile = null; try { + if (isPlatform('windows')) { + throw Error( + CustomErrors.WINDOWS_NATIVE_IMAGE_PROCESSING_NOT_SUPPORTED + ); + } if (!existsSync(inputFile.path)) { const tempFilePath = await ipcRenderer.invoke( 'get-temp-file-path', diff --git a/src/api/watch.ts b/src/api/watch.ts index d8ff2d1d3..20008375e 100644 --- a/src/api/watch.ts +++ b/src/api/watch.ts @@ -4,13 +4,14 @@ import { ipcRenderer } from 'electron'; import { ElectronFile, WatchMapping } from '../types'; import { getElectronFile } from '../services/fs'; import { getWatchMappings, setWatchMappings } from '../services/watch'; +import ElectronLog from 'electron-log'; export async function addWatchMapping( rootFolderName: string, folderPath: string, uploadStrategy: number ) { - folderPath = path.normalize(folderPath); + ElectronLog.log(`Adding watch mapping: ${folderPath}`); const watchMappings = getWatchMappings(); if (isMappingPresent(watchMappings, folderPath)) { throw new Error(`Watch mapping already exists`); @@ -93,23 +94,19 @@ export function registerWatcherFunctions( ) { ipcRenderer.removeAllListeners('watch-add'); ipcRenderer.removeAllListeners('watch-change'); - ipcRenderer.removeAllListeners('watch-unlink'); + ipcRenderer.removeAllListeners('watch-unlink-dir'); ipcRenderer.on('watch-add', async (_, filePath: string) => { - filePath = path.normalize( - filePath.split(path.sep).join(path.posix.sep) - ); + filePath = filePath.split(path.sep).join(path.posix.sep); + await addFile(await getElectronFile(filePath)); }); ipcRenderer.on('watch-unlink', async (_, filePath: string) => { - filePath = path.normalize( - filePath.split(path.sep).join(path.posix.sep) - ); + filePath = filePath.split(path.sep).join(path.posix.sep); + await removeFile(filePath); }); ipcRenderer.on('watch-unlink-dir', async (_, folderPath: string) => { - folderPath = path.normalize( - folderPath.split(path.sep).join(path.posix.sep) - ); + folderPath = folderPath.split(path.sep).join(path.posix.sep); await removeFolder(folderPath); }); } diff --git a/src/constants/errors.ts b/src/constants/errors.ts new file mode 100644 index 000000000..43e4773d8 --- /dev/null +++ b/src/constants/errors.ts @@ -0,0 +1,5 @@ +export const CustomErrors = { + WINDOWS_NATIVE_IMAGE_PROCESSING_NOT_SUPPORTED: + 'Windows native image processing is not supported', + INVALID_OS: (os: string) => `Invalid OS - ${os}`, +}; diff --git a/src/preload.ts b/src/preload.ts index 8d2157999..32204839f 100644 --- a/src/preload.ts +++ b/src/preload.ts @@ -51,7 +51,10 @@ import { fixHotReloadNext12 } from './utils/preload'; import { isFolder, getDirFiles } from './api/fs'; import { convertHEIC, generateImageThumbnail } from './api/imageProcessor'; import { setupLogging } from './utils/logging'; -import { setupRendererProcessStatsLogger } from './utils/processStats'; +import { + setupRendererProcessStatsLogger, + logRendererProcessMemoryUsage, +} from './utils/processStats'; import { runFFmpegCmd } from './api/ffmpeg'; fixHotReloadNext12(); @@ -107,4 +110,5 @@ windowObject['ElectronAPIs'] = { runFFmpegCmd, muteUpdateNotification, generateImageThumbnail, + logRendererProcessMemoryUsage, }; diff --git a/src/services/appUpdater.ts b/src/services/appUpdater.ts index 84a2bfeba..99ecef8b9 100644 --- a/src/services/appUpdater.ts +++ b/src/services/appUpdater.ts @@ -12,7 +12,7 @@ import { import fetch from 'node-fetch'; import { logErrorSentry } from './sentry'; import ElectronLog from 'electron-log'; -import { isPlatform } from '../utils/main'; +import { isPlatform } from '../utils/common/platform'; const FIVE_MIN_IN_MICROSECOND = 5 * 60 * 1000; const ONE_DAY_IN_MICROSECOND = 1 * 24 * 60 * 60 * 1000; diff --git a/src/services/autoLauncher.ts b/src/services/autoLauncher.ts index c28eb177c..139d5166c 100644 --- a/src/services/autoLauncher.ts +++ b/src/services/autoLauncher.ts @@ -1,4 +1,4 @@ -import { isPlatform } from '../utils/main'; +import { isPlatform } from '../utils/common/platform'; import { AutoLauncherClient } from '../types/autoLauncher'; import linuxAutoLauncher from './autoLauncherClients/linuxAutoLauncher'; import macAndWindowsAutoLauncher from './autoLauncherClients/macAndWindowsAutoLauncher'; diff --git a/src/services/fs.ts b/src/services/fs.ts index 9565cb086..b5ef8eb11 100644 --- a/src/services/fs.ts +++ b/src/services/fs.ts @@ -184,12 +184,22 @@ export const getZipFileStream = async ( }; export async function isFolder(dirPath: string) { - return await fs - .stat(dirPath) - .then((stats) => { - return stats.isDirectory(); - }) - .catch(() => false); + try { + const stats = await fs.stat(dirPath); + return stats.isDirectory(); + } catch (e) { + let err = e; + // if code is defined, it's an error from fs.stat + if (typeof e.code !== 'undefined') { + // ENOENT means the file does not exist + if (e.code === 'ENOENT') { + return false; + } + err = Error(`fs error code: ${e.code}`); + } + logError(err, 'isFolder failed'); + return false; + } } export const convertBrowserStreamToNode = ( diff --git a/src/services/imageProcessor.ts b/src/services/imageProcessor.ts index e211e2b64..05b252ba7 100644 --- a/src/services/imageProcessor.ts +++ b/src/services/imageProcessor.ts @@ -5,10 +5,11 @@ import { existsSync, rmSync } from 'fs'; import { readFile, writeFile } from 'promise-fs'; import { generateTempFilePath } from '../utils/temp'; import { logErrorSentry } from './sentry'; -import { isPlatform } from '../utils/main'; +import { isPlatform } from '../utils/common/platform'; import { isDev } from '../utils/common'; import path from 'path'; import log from 'electron-log'; +import { CustomErrors } from '../constants/errors'; const shellescape = require('any-shell-escape'); const asyncExec = util.promisify(exec); @@ -157,7 +158,7 @@ function constructConvertCommand( } ); } else { - Error(`${process.platform} native heic convert not supported yet`); + throw Error(CustomErrors.INVALID_OS(process.platform)); } return convertCmd; } @@ -271,9 +272,7 @@ function constructThumbnailGenerationCommand( return cmdPart; }); } else { - Error( - `${process.platform} native thumbnail generation not supported yet` - ); + throw Error(CustomErrors.INVALID_OS(process.platform)); } return thumbnailGenerationCmd; } diff --git a/src/utils/common.ts b/src/utils/common/index.ts similarity index 100% rename from src/utils/common.ts rename to src/utils/common/index.ts diff --git a/src/utils/common/platform.ts b/src/utils/common/platform.ts new file mode 100644 index 000000000..2ee705d5f --- /dev/null +++ b/src/utils/common/platform.ts @@ -0,0 +1,11 @@ +export function isPlatform(platform: 'mac' | 'windows' | 'linux') { + if (process.platform === 'darwin') { + return platform === 'mac'; + } else if (process.platform === 'win32') { + return platform === 'windows'; + } else if (process.platform === 'linux') { + return platform === 'linux'; + } else { + return false; + } +} diff --git a/src/utils/createWindow.ts b/src/utils/createWindow.ts index db356d467..391a8e285 100644 --- a/src/utils/createWindow.ts +++ b/src/utils/createWindow.ts @@ -3,9 +3,11 @@ import * as path from 'path'; import { isDev } from './common'; import { isAppQuitting } from '../main'; import { PROD_HOST_URL } from '../config'; -import { isPlatform } from './main'; +import { isPlatform } from './common/platform'; import { getHideDockIconPreference } from '../services/userPreference'; import autoLauncher from '../services/autoLauncher'; +import ElectronLog from 'electron-log'; +import { logErrorSentry } from '../services/sentry'; export async function createWindow(): Promise { const appImgPath = isDev @@ -64,6 +66,20 @@ export async function createWindow(): Promise { // ignore } }); + mainWindow.webContents.on('render-process-gone', (event, details) => { + mainWindow.webContents.reload(); + logErrorSentry( + Error('render-process-gone'), + 'webContents event render-process-gone', + { details } + ); + ElectronLog.log('webContents event render-process-gone', details); + }); + mainWindow.webContents.on('unresponsive', () => { + mainWindow.webContents.forcefullyCrashRenderer(); + ElectronLog.log('webContents event unresponsive'); + }); + setTimeout(() => { try { splash.destroy(); diff --git a/src/utils/main.ts b/src/utils/main.ts index 81fedbf7a..729bc3d3b 100644 --- a/src/utils/main.ts +++ b/src/utils/main.ts @@ -11,6 +11,7 @@ import { getHideDockIconPreference } from '../services/userPreference'; import { setupAutoUpdater } from '../services/appUpdater'; import ElectronLog from 'electron-log'; import os from 'os'; +import { isPlatform } from './common/platform'; export function handleUpdates(mainWindow: BrowserWindow) { if (!isDev) { @@ -84,18 +85,6 @@ export function setupNextElectronServe() { }); } -export function isPlatform(platform: 'mac' | 'windows' | 'linux') { - if (process.platform === 'darwin') { - return platform === 'mac'; - } else if (process.platform === 'win32') { - return platform === 'windows'; - } else if (process.platform === 'linux') { - return platform === 'linux'; - } else { - return false; - } -} - export async function handleDockIconHideOnAutoLaunch() { const shouldHideDockIcon = getHideDockIconPreference(); const wasAutoLaunched = await autoLauncher.wasAutoLaunched(); diff --git a/src/utils/menu.ts b/src/utils/menu.ts index 5002a1205..6ecb8459b 100644 --- a/src/utils/menu.ts +++ b/src/utils/menu.ts @@ -11,7 +11,7 @@ import { } from '../services/userPreference'; import { setIsAppQuitting } from '../main'; import autoLauncher from '../services/autoLauncher'; -import { isPlatform } from './main'; +import { isPlatform } from './common/platform'; import ElectronLog from 'electron-log'; export function buildContextMenu( diff --git a/src/utils/processStats.ts b/src/utils/processStats.ts index 64f900d58..00b3a71d1 100644 --- a/src/utils/processStats.ts +++ b/src/utils/processStats.ts @@ -5,9 +5,9 @@ const LOGGING_INTERVAL_IN_MICROSECONDS = 30 * 1000; // 30 seconds const SPIKE_DETECTION_INTERVAL_IN_MICROSECONDS = 1 * 1000; // 1 seconds -const MAIN_MEMORY_USAGE_DIFF_IN_KILOBYTES_CONSIDERED_AS_SPIKE = 10 * 1024; // 10 MB +const MAIN_MEMORY_USAGE_DIFF_IN_KILOBYTES_CONSIDERED_AS_SPIKE = 50 * 1024; // 50 MB -const HIGH_MAIN_MEMORY_USAGE_THRESHOLD_IN_KILOBYTES = 100 * 1024; // 100 MB +const HIGH_MAIN_MEMORY_USAGE_THRESHOLD_IN_KILOBYTES = 200 * 1024; // 200 MB const RENDERER_MEMORY_USAGE_DIFF_IN_KILOBYTES_CONSIDERED_AS_SPIKE = 200 * 1024; // 200 MB @@ -40,15 +40,15 @@ let mainProcessUsingHighMemory = false; async function logSpikeMainMemoryUsage() { const processMemoryInfo = await process.getProcessMemoryInfo(); const currentMemoryUsage = Math.max( - processMemoryInfo.residentSet, + processMemoryInfo.residentSet ?? 0, processMemoryInfo.private ); - const previewMemoryUsage = Math.max( - previousMainProcessMemoryInfo.private, - previousMainProcessMemoryInfo.residentSet + const previousMemoryUsage = Math.max( + previousMainProcessMemoryInfo.residentSet ?? 0, + previousMainProcessMemoryInfo.private ); const isSpiking = - currentMemoryUsage - previewMemoryUsage >= + currentMemoryUsage - previousMemoryUsage >= MAIN_MEMORY_USAGE_DIFF_IN_KILOBYTES_CONSIDERED_AS_SPIKE; const isHighMemoryUsage = @@ -92,15 +92,16 @@ let rendererUsingHighMemory = false; async function logSpikeRendererMemoryUsage() { const processMemoryInfo = await process.getProcessMemoryInfo(); const currentMemoryUsage = Math.max( - processMemoryInfo.residentSet, + processMemoryInfo.residentSet ?? 0, processMemoryInfo.private ); - const previewMemoryUsage = Math.max( + + const previousMemoryUsage = Math.max( previousRendererProcessMemoryInfo.private, - previousRendererProcessMemoryInfo.residentSet + previousRendererProcessMemoryInfo.residentSet ?? 0 ); const isSpiking = - currentMemoryUsage - previewMemoryUsage >= + currentMemoryUsage - previousMemoryUsage >= RENDERER_MEMORY_USAGE_DIFF_IN_KILOBYTES_CONSIDERED_AS_SPIKE; const isHighMemoryUsage = @@ -168,6 +169,19 @@ export function setupRendererProcessStatsLogger() { setInterval(logRendererProcessStats, LOGGING_INTERVAL_IN_MICROSECONDS); } +export async function logRendererProcessMemoryUsage(message: string) { + const processMemoryInfo = await process.getProcessMemoryInfo(); + const processMemory = Math.max( + processMemoryInfo.private, + processMemoryInfo.residentSet ?? 0 + ); + ElectronLog.log( + 'renderer ProcessMemory', + message, + convertBytesToHumanReadable(processMemory * 1024) + ); +} + const getNormalizedProcessMemoryInfo = async ( processMemoryInfo: Electron.ProcessMemoryInfo ) => { diff --git a/ui b/ui index 0d34202c4..c56da8716 160000 --- a/ui +++ b/ui @@ -1 +1 @@ -Subproject commit 0d34202c4121003defea9839355f5c03d238d2c9 +Subproject commit c56da87161ba582ae21407b2d3a19508b50c8b9b diff --git a/yarn.lock b/yarn.lock index 8dd73a05c..a406a638e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1199,6 +1199,13 @@ crc@^3.8.0: dependencies: buffer "^5.1.0" +cross-env@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" + integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw== + dependencies: + cross-spawn "^7.0.1" + cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"