Browse Source

cleanup dead code

Abhinav 1 year ago
parent
commit
86d61060b7
78 changed files with 276 additions and 918 deletions
  1. 1 1
      apps/photos/src/components/AuthenticateUserModal.tsx
  2. 2 2
      apps/photos/src/components/Collections/CollectionDownloadProgress.tsx
  3. 1 1
      apps/photos/src/components/Collections/CollectionShare/publicShare/manage/linkPassword/setPassword.tsx
  4. 1 1
      apps/photos/src/components/Collections/index.tsx
  5. 1 1
      apps/photos/src/components/FixLargeThumbnail.tsx
  6. 1 1
      apps/photos/src/components/MachineLearning/ImageViews.tsx
  7. 1 1
      apps/photos/src/components/MachineLearning/MlDebug-disabled.tsx
  8. 3 3
      apps/photos/src/components/Sidebar/DebugSection.tsx
  9. 1 1
      apps/photos/src/components/Sidebar/Preferences/LanguageSelector.tsx
  10. 3 3
      apps/photos/src/components/Sidebar/Preferences/index.tsx
  11. 1 1
      apps/photos/src/components/Sidebar/userDetailsSection.tsx
  12. 1 1
      apps/photos/src/components/TwoFactor/Modal/Manage.tsx
  13. 1 1
      apps/photos/src/components/TwoFactor/Modal/index.tsx
  14. 9 9
      apps/photos/src/components/Upload/Uploader.tsx
  15. 2 2
      apps/photos/src/components/WatchFolder/index.tsx
  16. 1 1
      apps/photos/src/components/pages/gallery/PlanSelector/card/index.tsx
  17. 3 3
      apps/photos/src/pages/_app.tsx
  18. 1 1
      apps/photos/src/pages/deduplicate/index.tsx
  19. 10 6
      apps/photos/src/pages/gallery/index.tsx
  20. 5 5
      apps/photos/src/pages/index.tsx
  21. 1 1
      apps/photos/src/pages/shared-albums/index.tsx
  22. 5 1
      apps/photos/src/services/billingService.ts
  23. 9 2
      apps/photos/src/services/cache/cacheStorageFactory.ts
  24. 18 20
      apps/photos/src/services/clipService.ts
  25. 3 3
      apps/photos/src/services/collectionService.ts
  26. 1 1
      apps/photos/src/services/downloadManager.ts
  27. 0 26
      apps/photos/src/services/electron/cache.ts
  28. 0 78
      apps/photos/src/services/electron/common.ts
  29. 0 27
      apps/photos/src/services/electron/ffmpeg.ts
  30. 0 48
      apps/photos/src/services/electron/fs.ts
  31. 0 42
      apps/photos/src/services/electron/safeStorage.tsx
  32. 0 36
      apps/photos/src/services/electron/update.ts
  33. 2 2
      apps/photos/src/services/embeddingService.ts
  34. 2 2
      apps/photos/src/services/entityService.ts
  35. 29 37
      apps/photos/src/services/export/index.ts
  36. 1 1
      apps/photos/src/services/export/migration.ts
  37. 11 2
      apps/photos/src/services/ffmpeg/ffmpegFactory.ts
  38. 2 2
      apps/photos/src/services/fileService.ts
  39. 5 20
      apps/photos/src/services/imageProcessor.ts
  40. 25 86
      apps/photos/src/services/importService.ts
  41. 2 2
      apps/photos/src/services/machineLearning/machineLearningFactory.ts
  42. 1 1
      apps/photos/src/services/machineLearning/mlWorkManager.ts
  43. 1 1
      apps/photos/src/services/migrateThumbnailService.ts
  44. 1 1
      apps/photos/src/services/publicCollectionDownloadManager.ts
  45. 2 2
      apps/photos/src/services/publicCollectionService.ts
  46. 1 1
      apps/photos/src/services/trashService.ts
  47. 4 3
      apps/photos/src/services/upload/thumbnailService.ts
  48. 2 2
      apps/photos/src/services/upload/uploadManager.ts
  49. 2 2
      apps/photos/src/services/userService.ts
  50. 1 1
      apps/photos/src/services/wasmHeicConverter/wasmHEICConverterService.ts
  51. 13 19
      apps/photos/src/services/watchFolder/watchFolderService.ts
  52. 3 3
      apps/photos/src/services/workerElectronCache/client.ts
  53. 0 100
      apps/photos/src/types/electron/index.ts
  54. 1 1
      apps/photos/src/utils/billing/index.ts
  55. 3 3
      apps/photos/src/utils/collection/index.ts
  56. 1 1
      apps/photos/src/utils/comlink/ComlinkConvertWorker.ts
  57. 0 25
      apps/photos/src/utils/comlink/ComlinkCryptoWorker.ts
  58. 1 1
      apps/photos/src/utils/comlink/ComlinkFFmpegWorker.ts
  59. 1 1
      apps/photos/src/utils/comlink/ComlinkMLWorker.ts
  60. 0 27
      apps/photos/src/utils/comlink/comlinkWorker.ts
  61. 1 1
      apps/photos/src/utils/common/apiUtil.ts
  62. 3 3
      apps/photos/src/utils/common/key.ts
  63. 6 5
      apps/photos/src/utils/crypto/index.ts
  64. 8 7
      apps/photos/src/utils/file/index.ts
  65. 1 1
      apps/photos/src/utils/machineLearning/faceCrop.ts
  66. 1 1
      apps/photos/src/utils/machineLearning/index.ts
  67. 1 1
      apps/photos/src/utils/magicMetadata/index.ts
  68. 0 48
      apps/photos/src/utils/storage/cache.ts
  69. 0 40
      apps/photos/src/utils/storage/index.ts
  70. 0 12
      apps/photos/src/utils/storage/localForage.ts
  71. 0 68
      apps/photos/src/utils/storage/localStorage.ts
  72. 1 1
      apps/photos/src/utils/storage/mlStorage.ts
  73. 0 32
      apps/photos/src/utils/storage/sessionStorage.ts
  74. 5 6
      apps/photos/src/utils/ui/index.tsx
  75. 1 1
      apps/photos/src/utils/user/family.ts
  76. 3 3
      apps/photos/src/utils/user/index.ts
  77. 39 6
      packages/shared/crypto/internal/crypto.worker.ts
  78. 3 3
      packages/shared/crypto/internal/libsodium.ts

+ 1 - 1
apps/photos/src/components/AuthenticateUserModal.tsx

@@ -1,6 +1,6 @@
 import React, { useContext, useEffect, useState } from 'react';
 
-import { getData, LS_KEYS } from 'utils/storage/localStorage';
+import { getData, LS_KEYS } from '@ente/shared/storage/localStorage';
 import { AppContext } from 'pages/_app';
 import { KeyAttributes, User } from 'types/user';
 import VerifyMasterPasswordForm, {

+ 2 - 2
apps/photos/src/components/Collections/CollectionDownloadProgress.tsx

@@ -4,7 +4,7 @@ import isElectron from 'is-electron';
 import { AppContext } from 'pages/_app';
 import { GalleryContext } from 'pages/gallery';
 import { useContext } from 'react';
-import ElectronService from 'services/electron/common';
+import ElectronAPIs from '@ente/shared/electron';
 
 export interface CollectionDownloadProgressAttributes {
     success: number;
@@ -100,7 +100,7 @@ export const CollectionDownloadProgress: React.FC<CollectionDownloadProgressProp
                 (attr) => attr.collectionID === collectionID
             );
             if (isElectron()) {
-                ElectronService.openDirectory(attributes.downloadDirPath);
+                ElectronAPIs.openDirectory(attributes.downloadDirPath);
             } else {
                 if (attributes.isHidden) {
                     galleryContext.openHiddenSection(() => {

+ 1 - 1
apps/photos/src/components/Collections/CollectionShare/publicShare/manage/linkPassword/setPassword.tsx

@@ -4,7 +4,7 @@ import SingleInputForm, {
 } from '@ente/shared/components/SingleInputForm';
 import React from 'react';
 import { t } from 'i18next';
-import ComlinkCryptoWorker from 'utils/comlink/ComlinkCryptoWorker';
+import ComlinkCryptoWorker from '@ente/shared/crypto';
 
 export function PublicLinkSetPassword({
     open,

+ 1 - 1
apps/photos/src/components/Collections/index.tsx

@@ -14,7 +14,7 @@ import {
 } from 'utils/collection';
 import { useLocalState } from '@ente/shared/hooks/useLocalState';
 import { sortCollectionSummaries } from 'services/collectionService';
-import { LS_KEYS } from 'utils/storage/localStorage';
+import { LS_KEYS } from '@ente/shared/storage/localStorage';
 import {
     CollectionDownloadProgress,
     CollectionDownloadProgressAttributes,

+ 1 - 1
apps/photos/src/components/FixLargeThumbnail.tsx

@@ -6,7 +6,7 @@ import {
     getLargeThumbnailFiles,
     replaceThumbnail,
 } from 'services/migrateThumbnailService';
-import { getData, LS_KEYS, setData } from 'utils/storage/localStorage';
+import { getData, LS_KEYS, setData } from '@ente/shared/storage/localStorage';
 import { logError } from '@ente/shared/sentry';
 import { t } from 'i18next';
 

+ 1 - 1
apps/photos/src/components/MachineLearning/ImageViews.tsx

@@ -3,7 +3,7 @@ import { Skeleton, styled } from '@mui/material';
 
 import { imageBitmapToBlob } from 'utils/image';
 import { logError } from '@ente/shared/sentry';
-import { getBlobFromCache } from 'utils/storage/cache';
+import { getBlobFromCache } from '@ente/shared/storage/cacheStorage/helpers';
 
 export const FaceCropsRow = styled('div')`
     & > img {

+ 1 - 1
apps/photos/src/components/MachineLearning/MlDebug-disabled.tsx

@@ -1,7 +1,7 @@
 export {};
 
 // import React, { useState, useEffect, useContext, ChangeEvent } from 'react';
-// import { getData, LS_KEYS } from 'utils/storage/localStorage';
+// import { getData, LS_KEYS } from '@ente/shared/storage/localStorage';
 // import { useRouter } from 'next/router';
 // import { ComlinkWorker } from 'utils/comlink';
 // import { AppContext } from 'pages/_app';

+ 3 - 3
apps/photos/src/components/Sidebar/DebugSection.tsx

@@ -7,7 +7,7 @@ import { t } from 'i18next';
 import { addLogLine } from '@ente/shared/logging';
 import { getDebugLogs } from '@ente/shared/logging/web';
 import isElectron from 'is-electron';
-import ElectronService from 'services/electron/common';
+import ElectronAPIs from '@ente/shared/electron';
 import Typography from '@mui/material/Typography';
 import { isInternalUser } from 'utils/user';
 import { testUpload } from '../../../tests/upload.test';
@@ -24,7 +24,7 @@ export default function DebugSection() {
     useEffect(() => {
         const main = async () => {
             if (isElectron()) {
-                const appVersion = await ElectronService.getAppVersion();
+                const appVersion = await ElectronAPIs.getAppVersion();
                 setAppVersion(appVersion);
             }
         };
@@ -48,7 +48,7 @@ export default function DebugSection() {
     const downloadDebugLogs = () => {
         addLogLine('exporting logs');
         if (isElectron()) {
-            ElectronService.openLogDirectory();
+            ElectronAPIs.openLogDirectory();
         } else {
             const logs = getDebugLogs();
 

+ 1 - 1
apps/photos/src/components/Sidebar/Preferences/LanguageSelector.tsx

@@ -4,7 +4,7 @@ import { useLocalState } from '@ente/shared/hooks/useLocalState';
 import { t } from 'i18next';
 import { useRouter } from 'next/router';
 import { getBestPossibleUserLocale } from '@ente/shared/i18n/utils';
-import { LS_KEYS } from 'utils/storage/localStorage';
+import { LS_KEYS } from '@ente/shared/storage/localStorage';
 
 const getLocaleDisplayName = (l: Language) => {
     switch (l) {

+ 3 - 3
apps/photos/src/components/Sidebar/Preferences/index.tsx

@@ -10,9 +10,9 @@ import AdvancedSettings from '../AdvancedSettings';
 import MapSettings from '../MapSetting';
 import { LanguageSelector } from './LanguageSelector';
 import { EnteMenuItem } from 'components/Menu/EnteMenuItem';
-import { LS_KEYS } from 'utils/storage/localStorage';
+import { LS_KEYS } from '@ente/shared/storage/localStorage';
 import { useLocalState } from '@ente/shared/hooks/useLocalState';
-import ElectronService from 'services/electron/common';
+import ElectronAPIs from '@ente/shared/electron';
 import InMemoryStore, { MS_KEYS } from 'services/InMemoryStore';
 import { logError } from '@ente/shared/sentry';
 
@@ -46,7 +46,7 @@ export default function Preferences({ open, onClose, onRootClose }) {
     const toggleOptOutOfCrashReports = async () => {
         try {
             if (isElectron()) {
-                await ElectronService.updateOptOutOfCrashReports(
+                await ElectronAPIs.updateOptOutOfCrashReports(
                     !optOutOfCrashReports
                 );
             }

+ 1 - 1
apps/photos/src/components/Sidebar/userDetailsSection.tsx

@@ -2,7 +2,7 @@ import React, { useContext, useEffect, useMemo, useState } from 'react';
 import SubscriptionCard from './SubscriptionCard';
 import { getUserDetailsV2 } from 'services/userService';
 import { UserDetails } from 'types/user';
-import { getData, LS_KEYS, setData } from 'utils/storage/localStorage';
+import { getData, LS_KEYS, setData } from '@ente/shared/storage/localStorage';
 import { useLocalState } from '@ente/shared/hooks/useLocalState';
 import Typography from '@mui/material/Typography';
 import SubscriptionStatus from './SubscriptionStatus';

+ 1 - 1
apps/photos/src/components/TwoFactor/Modal/Manage.tsx

@@ -5,7 +5,7 @@ import { AppContext } from 'pages/_app';
 import { PHOTOS_PAGES as PAGES } from '@ente/shared/constants/pages';
 import router from 'next/router';
 import { disableTwoFactor } from '@ente/accounts/api/user';
-import { setData, LS_KEYS, getData } from 'utils/storage/localStorage';
+import { setData, LS_KEYS, getData } from '@ente/shared/storage/localStorage';
 import { Button, Grid } from '@mui/material';
 
 interface Iprops {

+ 1 - 1
apps/photos/src/components/TwoFactor/Modal/index.tsx

@@ -1,7 +1,7 @@
 import { useEffect, useState } from 'react';
 import { getTwoFactorStatus } from 'services/userService';
 import { SetLoading } from 'types/gallery';
-import { getData, LS_KEYS, setData } from 'utils/storage/localStorage';
+import { getData, LS_KEYS, setData } from '@ente/shared/storage/localStorage';
 import { t } from 'i18next';
 
 import TwoFactorModalSetupSection from './Setup';

+ 9 - 9
apps/photos/src/components/Upload/Uploader.tsx

@@ -44,7 +44,6 @@ import {
     UPLOAD_STRATEGY,
     PICKED_UPLOAD_TYPE,
 } from 'constants/upload';
-import importService from 'services/importService';
 import {
     getDownloadAppMessage,
     getRootLevelFileWithFolderNotAllowMessage,
@@ -66,6 +65,7 @@ import {
 } from 'services/publicCollectionService';
 import { UploadTypeSelectorIntent } from 'types/gallery';
 import { getOrCreateAlbum } from 'utils/collection';
+import ElectronAPIs from '@ente/shared/electron';
 
 const FIRST_ALBUM_NAME = 'My First Album';
 
@@ -179,7 +179,7 @@ export default function Uploader(props: Props) {
             setUploadProgressView(true);
         }
 
-        if (isElectron() && ImportService.checkAllElectronAPIsExists()) {
+        if (isElectron()) {
             ImportService.getPendingUploads().then(
                 ({ files: electronFiles, collectionName, type }) => {
                     addLogLine(
@@ -234,7 +234,7 @@ export default function Uploader(props: Props) {
                         for (const file of props.dragAndDropFiles) {
                             if (file.name.endsWith('.zip')) {
                                 const zipFiles =
-                                    await importService.getElectronFilesFromGoogleZip(
+                                    await ElectronAPIs.getElectronFilesFromGoogleZip(
                                         (file as any).path
                                     );
                                 addLogLine(
@@ -529,13 +529,13 @@ export default function Uploader(props: Props) {
             ) {
                 await ImportService.setToUploadCollection(collections);
                 if (zipPaths.current) {
-                    await ImportService.setToUploadFiles(
+                    ElectronAPIs.setToUploadFiles(
                         PICKED_UPLOAD_TYPE.ZIPS,
                         zipPaths.current
                     );
                     zipPaths.current = null;
                 }
-                await ImportService.setToUploadFiles(
+                ElectronAPIs.setToUploadFiles(
                     PICKED_UPLOAD_TYPE.FILES,
                     filesWithCollectionToUploadIn.map(
                         ({ file }) => (file as ElectronFile).path
@@ -722,11 +722,11 @@ export default function Uploader(props: Props) {
         let files: ElectronFile[];
         pickedUploadType.current = type;
         if (type === PICKED_UPLOAD_TYPE.FILES) {
-            files = await ImportService.showUploadFilesDialog();
+            files = await ElectronAPIs.showUploadFilesDialog();
         } else if (type === PICKED_UPLOAD_TYPE.FOLDERS) {
-            files = await ImportService.showUploadDirsDialog();
+            files = await ElectronAPIs.showUploadDirsDialog();
         } else {
-            const response = await ImportService.showUploadZipDialog();
+            const response = await ElectronAPIs.showUploadZipDialog();
             files = response.files;
             zipPaths.current = response.zipPaths;
         }
@@ -755,7 +755,7 @@ export default function Uploader(props: Props) {
     };
 
     const handleUpload = (type) => () => {
-        if (isElectron() && importService.checkAllElectronAPIsExists()) {
+        if (isElectron()) {
             handleDesktopUpload(type);
         } else {
             handleWebUpload(type);

+ 2 - 2
apps/photos/src/components/WatchFolder/index.tsx

@@ -10,7 +10,7 @@ import DialogTitleWithCloseButton from '@ente/shared/components/DialogBox/TitleW
 import UploadStrategyChoiceModal from 'components/Upload/UploadStrategyChoiceModal';
 import { UPLOAD_STRATEGY } from 'constants/upload';
 import { getImportSuggestion } from 'utils/upload';
-import electronFSService from 'services/electron/fs';
+import ElectronAPIs from '@ente/shared/electron';
 import { PICKED_UPLOAD_TYPE } from 'constants/upload';
 
 interface Iprops {
@@ -50,7 +50,7 @@ export default function WatchFolder({ open, onClose }: Iprops) {
 
     const addFolderForWatching = async (path: string) => {
         setInputFolderPath(path);
-        const files = await electronFSService.getDirFiles(path);
+        const files = await ElectronAPIs.getDirFiles(path);
         const analysisResult = getImportSuggestion(
             PICKED_UPLOAD_TYPE.FOLDERS,
             files

+ 1 - 1
apps/photos/src/components/pages/gallery/PlanSelector/card/index.tsx

@@ -20,7 +20,7 @@ import { logError } from '@ente/shared/sentry';
 import { AppContext } from 'pages/_app';
 import { Link, Stack } from '@mui/material';
 import { useLocalState } from '@ente/shared/hooks/useLocalState';
-import { LS_KEYS } from 'utils/storage/localStorage';
+import { LS_KEYS } from '@ente/shared/storage/localStorage';
 import { getLocalUserDetails } from 'utils/user';
 import { PLAN_PERIOD } from 'constants/gallery';
 import FreeSubscriptionPlanSelectorCard from './free';

+ 3 - 3
apps/photos/src/pages/_app.tsx

@@ -41,7 +41,7 @@ import { CustomError } from '@ente/shared/error';
 import { addLogLine } from '@ente/shared/logging';
 import { clearLogsIfLocalStorageLimitExceeded } from '@ente/shared/logging/web';
 import isElectron from 'is-electron';
-import ElectronUpdateService from 'services/electron/update';
+import ElectronAPIs from '@ente/shared/electron';
 import {
     getUpdateAvailableForDownloadMessage,
     getUpdateReadyToInstallMessage,
@@ -52,7 +52,6 @@ import {
     SetNotificationAttributes,
 } from 'types/Notification';
 import ArrowForward from '@mui/icons-material/ArrowForward';
-import { AppUpdateInfo } from 'types/electron';
 import { CacheProvider } from '@emotion/react';
 import {
     APP_TITLES,
@@ -76,6 +75,7 @@ import { User } from '@ente/shared/user/types';
 import { useLocalState } from '@ente/shared/hooks/useLocalState';
 import { PHOTOS_PAGES as PAGES } from '@ente/shared/constants/pages';
 import { getTheme } from '@ente/shared/themes';
+import { AppUpdateInfo } from '@ente/shared/electron/types';
 
 const redirectMap = new Map([
     [REDIRECTS.ROADMAP, getRoadmapRedirectURL],
@@ -193,7 +193,7 @@ export default function App(props: EnteAppProps) {
                     });
                 }
             };
-            ElectronUpdateService.registerUpdateEventListener(showUpdateDialog);
+            ElectronAPIs.registerUpdateEventListener(showUpdateDialog);
         }
     }, []);
 

+ 1 - 1
apps/photos/src/pages/deduplicate/index.tsx

@@ -22,7 +22,7 @@ import Router from 'next/router';
 import DeduplicateOptions from 'components/pages/dedupe/SelectedFileOptions';
 import { PHOTOS_PAGES as PAGES } from '@ente/shared/constants/pages';
 import router from 'next/router';
-import { getKey, SESSION_KEYS } from 'utils/storage/sessionStorage';
+import { getKey, SESSION_KEYS } from '@ente/shared/storage/sessionStorage';
 import { styled } from '@mui/material';
 import { getLatestCollections } from 'services/collectionService';
 import EnteSpinner from '@ente/shared/components/EnteSpinner';

+ 10 - 6
apps/photos/src/pages/gallery/index.tsx

@@ -7,7 +7,11 @@ import {
     useState,
 } from 'react';
 import { useRouter } from 'next/router';
-import { clearKeys, getKey, SESSION_KEYS } from 'utils/storage/sessionStorage';
+import {
+    clearKeys,
+    getKey,
+    SESSION_KEYS,
+} from '@ente/shared/storage/sessionStorage';
 import { getLocalFiles, syncFiles } from 'services/fileService';
 import { styled, Typography } from '@mui/material';
 import {
@@ -32,7 +36,7 @@ import {
     justSignedUp,
     setIsFirstLogin,
     setJustSignedUp,
-} from 'utils/storage';
+} from '@ente/shared/storage/localStorage/helpers';
 import {
     isTokenValid,
     syncMapEnabled,
@@ -103,11 +107,11 @@ import { ITEM_TYPE, TimeStampListItem } from 'components/PhotoList';
 import UploadInputs from 'components/UploadSelectorInputs';
 import useFileInput from '@ente/shared/hooks/useFileInput';
 import { FamilyData, User } from 'types/user';
-import { getData, LS_KEYS } from 'utils/storage/localStorage';
+import { getData, LS_KEYS } from '@ente/shared/storage/localStorage';
 import { CenteredFlex } from 'components/Container';
 import { checkConnectivity } from 'utils/common';
 import { SYNC_INTERVAL_IN_MICROSECONDS } from 'constants/gallery';
-import ElectronService from 'services/electron/common';
+import ElectronAPIs from '@ente/shared/electron';
 import uploadManager from 'services/upload/uploadManager';
 import { getToken } from 'utils/common/key';
 import ExportModal from 'components/ExportModal';
@@ -337,14 +341,14 @@ export default function Gallery() {
             syncInterval.current = setInterval(() => {
                 syncWithRemote(false, true);
             }, SYNC_INTERVAL_IN_MICROSECONDS);
-            ElectronService.registerForegroundEventListener(() => {
+            ElectronAPIs.registerForegroundEventListener(() => {
                 syncWithRemote(false, true);
             });
         };
         main();
         return () => {
             clearInterval(syncInterval.current);
-            ElectronService.registerForegroundEventListener(() => {});
+            ElectronAPIs.registerForegroundEventListener(() => {});
             ClipService.removeOnFileUploadListener();
         };
     }, []);

+ 5 - 5
apps/photos/src/pages/index.tsx

@@ -4,19 +4,19 @@ import { styled, Button, Typography, TypographyProps } from '@mui/material';
 import { AppContext } from './_app';
 import Login from '@ente/accounts/components/Login';
 import { useRouter } from 'next/router';
-import { getData, LS_KEYS } from 'utils/storage/localStorage';
+import { getData, LS_KEYS } from '@ente/shared/storage/localStorage';
 import SignUp from '@ente/accounts/components/SignUp';
 import EnteSpinner from '@ente/shared/components/EnteSpinner';
 import { t } from 'i18next';
 
-import localForage from 'utils/storage/localForage';
+import localForage from '@ente/shared/storage/localForage';
 import { logError } from '@ente/shared/sentry';
 import { PHOTOS_PAGES as PAGES } from '@ente/shared/constants/pages';
 import { EnteLogo } from '@ente/shared/components/EnteLogo';
 import isElectron from 'is-electron';
-import safeStorageService from 'services/electron/safeStorage';
+import ElectronAPIs from '@ente/shared/electron';
 import { saveKeyInSessionStore } from 'utils/crypto';
-import { getKey, SESSION_KEYS } from 'utils/storage/sessionStorage';
+import { getKey, SESSION_KEYS } from '@ente/shared/storage/sessionStorage';
 import { getAlbumsURL } from 'utils/common/apiUtil';
 import { Trans } from 'react-i18next';
 import { APPS } from '@ente/shared/apps/constants';
@@ -132,7 +132,7 @@ export default function LandingPage() {
         const user = getData(LS_KEYS.USER);
         let key = getKey(SESSION_KEYS.ENCRYPTION_KEY);
         if (!key && isElectron()) {
-            key = await safeStorageService.getEncryptionKey();
+            key = await ElectronAPIs.getEncryptionKey();
             if (key) {
                 await saveKeyInSessionStore(
                     SESSION_KEYS.ENCRYPTION_KEY,

+ 1 - 1
apps/photos/src/pages/shared-albums/index.tsx

@@ -51,7 +51,7 @@ import { logoutUser } from '@ente/accounts/services/user';
 import UploadButton from 'components/Upload/UploadButton';
 import bs58 from 'bs58';
 import AddPhotoAlternateOutlined from '@mui/icons-material/AddPhotoAlternateOutlined';
-import ComlinkCryptoWorker from 'utils/comlink/ComlinkCryptoWorker';
+import ComlinkCryptoWorker from '@ente/shared/crypto';
 import { UploadTypeSelectorIntent } from 'types/gallery';
 import FileDownloadOutlinedIcon from '@mui/icons-material/FileDownloadOutlined';
 import MoreHoriz from '@mui/icons-material/MoreHoriz';

+ 5 - 1
apps/photos/src/services/billingService.ts

@@ -1,6 +1,10 @@
 import { getEndpoint, getPaymentsURL } from 'utils/common/apiUtil';
 import { getToken } from 'utils/common/key';
-import { setData, LS_KEYS, removeData } from 'utils/storage/localStorage';
+import {
+    setData,
+    LS_KEYS,
+    removeData,
+} from '@ente/shared/storage/localStorage';
 import HTTPService from './HTTPService';
 import { logError } from '@ente/shared/sentry';
 import { getPaymentToken } from './userService';

+ 9 - 2
apps/photos/src/services/cache/cacheStorageFactory.ts

@@ -1,5 +1,5 @@
 import { LimitedCacheStorage } from 'types/cache/index';
-import { ElectronCacheStorage } from 'services/electron/cache';
+import ElectronAPIs from '@ente/shared/electron';
 import { runningInElectron, runningInWorker } from 'utils/common';
 import { WorkerElectronCacheStorageService } from 'services/workerElectronCache/service';
 
@@ -14,7 +14,14 @@ class cacheStorageFactory {
                 }
                 return this.workerElectronCacheStorageServiceInstance;
             } else {
-                return ElectronCacheStorage;
+                return {
+                    open(cacheName) {
+                        return ElectronAPIs.openDiskCache(cacheName);
+                    },
+                    delete(cacheName) {
+                        return ElectronAPIs.deleteDiskCache(cacheName);
+                    },
+                };
             }
         } else {
             return transformBrowserCacheStorageToLimitedCacheStorage(caches);

+ 18 - 20
apps/photos/src/services/clipService.ts

@@ -1,24 +1,24 @@
-import { EnteFile } from 'types/file';
 import {
     putEmbedding,
     getLatestEmbeddings,
     getLocalEmbeddings,
 } from './embeddingService';
 import { getAllLocalFiles, getLocalFiles } from './fileService';
-import { ElectronAPIs } from 'types/electron';
 import downloadManager from './downloadManager';
-import { getToken } from 'utils/common/key';
-import { Embedding, Model } from 'types/embedding';
-import ComlinkCryptoWorker from 'utils/comlink/ComlinkCryptoWorker';
 import { logError } from '@ente/shared/sentry';
 import { addLogLine } from '@ente/shared/logging';
-import { CustomError } from 'utils/error';
-import { LS_KEYS, getData } from 'utils/storage/localStorage';
-import { getPersonalFiles } from 'utils/file';
 import isElectron from 'is-electron';
 import { Events, eventBus } from './events';
 import PQueue from 'p-queue';
+import { EnteFile } from 'types/file';
+import ElectronAPIs from '@ente/shared/electron';
+import { CustomError } from '@ente/shared/error';
+import { LS_KEYS, getData } from '@ente/shared/storage/localStorage';
+import { getPersonalFiles } from 'utils/file';
 import { FILE_TYPE } from 'constants/file';
+import ComlinkCryptoWorker from '@ente/shared/crypto';
+import { Embedding, Model } from 'types/embedding';
+import { getToken } from '@ente/shared/storage/localStorage/helpers';
 
 const CLIP_EMBEDDING_LENGTH = 512;
 
@@ -28,22 +28,20 @@ export interface ClipExtractionStatus {
 }
 
 class ClipServiceImpl {
-    private electronAPIs: ElectronAPIs;
-    private embeddingExtractionInProgress: AbortController = null;
+    private embeddingExtractionInProgress: AbortController | null = null;
     private reRunNeeded = false;
     private clipExtractionStatus: ClipExtractionStatus = {
         pending: 0,
         indexed: 0,
     };
-    private onUpdateHandler: (status: ClipExtractionStatus) => void = null;
+    private onUpdateHandler: ((status: ClipExtractionStatus) => void) | null =
+        null;
     private liveEmbeddingExtractionQueue: PQueue;
-    private onFileUploadedHandler: (arg: {
-        enteFile: EnteFile;
-        localFile: globalThis.File;
-    }) => void = null;
+    private onFileUploadedHandler:
+        | ((arg: { enteFile: EnteFile; localFile: globalThis.File }) => void)
+        | null = null;
 
     constructor() {
-        this.electronAPIs = globalThis['ElectronAPIs'];
         this.liveEmbeddingExtractionQueue = new PQueue({
             concurrency: 1,
         });
@@ -104,7 +102,7 @@ class ClipServiceImpl {
         if (!isElectron()) {
             return false;
         }
-        const platform = await this.electronAPIs.getPlatform();
+        const platform = await ElectronAPIs.getPlatform();
         return platform !== 'windows';
     };
 
@@ -150,7 +148,7 @@ class ClipServiceImpl {
 
     getTextEmbedding = async (text: string): Promise<Float32Array> => {
         try {
-            return this.electronAPIs.computeTextEmbedding(text);
+            return ElectronAPIs.computeTextEmbedding(text);
         } catch (e) {
             logError(e, 'failed to compute text embedding');
             throw e;
@@ -249,7 +247,7 @@ class ClipServiceImpl {
         const file = await localFile
             .arrayBuffer()
             .then((buffer) => new Uint8Array(buffer));
-        const embedding = await this.electronAPIs.computeImageEmbedding(file);
+        const embedding = await ElectronAPIs.computeImageEmbedding(file);
         return embedding;
     };
 
@@ -297,7 +295,7 @@ class ClipServiceImpl {
         } else {
             thumb = await downloadManager.downloadThumb(token, file);
         }
-        const embedding = await this.electronAPIs.computeImageEmbedding(thumb);
+        const embedding = await ElectronAPIs.computeImageEmbedding(thumb);
         return embedding;
     };
 

+ 3 - 3
apps/photos/src/services/collectionService.ts

@@ -1,6 +1,6 @@
 import { getEndpoint } from 'utils/common/apiUtil';
-import { getData, LS_KEYS } from 'utils/storage/localStorage';
-import localForage from 'utils/storage/localForage';
+import { getData, LS_KEYS } from '@ente/shared/storage/localStorage';
+import localForage from '@ente/shared/storage/localForage';
 
 import { getActualKey, getToken } from 'utils/common/key';
 import { getPublicKey } from './userService';
@@ -64,7 +64,7 @@ import {
     isDefaultHiddenCollection,
     getHiddenCollections,
 } from 'utils/collection';
-import ComlinkCryptoWorker from 'utils/comlink/ComlinkCryptoWorker';
+import ComlinkCryptoWorker from '@ente/shared/crypto';
 import { getLocalFiles } from './fileService';
 import { REQUEST_BATCH_SIZE } from 'constants/api';
 import { batch } from 'utils/common';

+ 1 - 1
apps/photos/src/services/downloadManager.ts

@@ -11,7 +11,7 @@ import { EnteFile } from 'types/file';
 import { logError } from '@ente/shared/sentry';
 import { FILE_TYPE } from 'constants/file';
 import { CustomError } from 'utils/error';
-import ComlinkCryptoWorker from 'utils/comlink/ComlinkCryptoWorker';
+import ComlinkCryptoWorker from '@ente/shared/crypto';
 import { CacheStorageService } from './cache/cacheStorageService';
 import { CACHES } from 'constants/cache';
 import { Remote } from 'comlink';

+ 0 - 26
apps/photos/src/services/electron/cache.ts

@@ -1,26 +0,0 @@
-import { LimitedCache, LimitedCacheStorage } from 'types/cache';
-import { ElectronAPIs } from 'types/electron';
-
-class ElectronCacheStorageService implements LimitedCacheStorage {
-    private electronAPIs: ElectronAPIs;
-    private allElectronAPIsExist: boolean = false;
-
-    constructor() {
-        this.electronAPIs = globalThis['ElectronAPIs'];
-        this.allElectronAPIsExist = !!this.electronAPIs?.openDiskCache;
-    }
-
-    async open(cacheName: string): Promise<LimitedCache> {
-        if (this.allElectronAPIsExist) {
-            return await this.electronAPIs.openDiskCache(cacheName);
-        }
-    }
-
-    async delete(cacheName: string): Promise<boolean> {
-        if (this.allElectronAPIsExist) {
-            return await this.electronAPIs.deleteDiskCache(cacheName);
-        }
-    }
-}
-
-export const ElectronCacheStorage = new ElectronCacheStorageService();

+ 0 - 78
apps/photos/src/services/electron/common.ts

@@ -1,78 +0,0 @@
-import isElectron from 'is-electron';
-import { ElectronAPIs } from 'types/electron';
-
-class ElectronService {
-    private electronAPIs: ElectronAPIs;
-
-    constructor() {
-        this.electronAPIs = globalThis['ElectronAPIs'];
-    }
-
-    checkIsBundledApp() {
-        return isElectron() && !!this.electronAPIs?.openDiskCache;
-    }
-
-    logToDisk(msg: string) {
-        if (this.electronAPIs?.logToDisk) {
-            this.electronAPIs.logToDisk(msg);
-        }
-    }
-
-    openLogDirectory() {
-        if (this.electronAPIs?.openLogDirectory) {
-            this.electronAPIs.openLogDirectory();
-        }
-    }
-
-    getSentryUserID() {
-        if (this.electronAPIs?.getSentryUserID) {
-            return this.electronAPIs.getSentryUserID();
-        }
-    }
-    getAppVersion() {
-        if (this.electronAPIs?.getAppVersion) {
-            return this.electronAPIs.getAppVersion();
-        }
-    }
-    logRendererProcessMemoryUsage(message: string) {
-        if (this.electronAPIs?.logRendererProcessMemoryUsage) {
-            return this.electronAPIs.logRendererProcessMemoryUsage(message);
-        }
-    }
-    registerForegroundEventListener(onForeground: () => void) {
-        if (this.electronAPIs?.registerForegroundEventListener) {
-            this.electronAPIs.registerForegroundEventListener(onForeground);
-        }
-    }
-
-    checkExistsAndCreateDir(dirPath: string) {
-        if (this.electronAPIs?.checkExistsAndCreateDir) {
-            this.electronAPIs.checkExistsAndCreateDir(dirPath);
-        }
-    }
-
-    openDirectory(dirPath: string) {
-        if (this.electronAPIs?.openDirectory) {
-            this.electronAPIs.openDirectory(dirPath);
-        }
-    }
-
-    selectDirectory() {
-        if (this.electronAPIs?.selectDirectory) {
-            return this.electronAPIs.selectDirectory();
-        }
-    }
-
-    updateOptOutOfCrashReports(optOut: boolean) {
-        if (this.electronAPIs?.updateOptOutOfCrashReports) {
-            return this.electronAPIs.updateOptOutOfCrashReports(optOut);
-        }
-    }
-    getPlatform() {
-        if (this.electronAPIs?.getPlatform) {
-            return this.electronAPIs.getPlatform();
-        }
-    }
-}
-
-export default new ElectronService();

+ 0 - 27
apps/photos/src/services/electron/ffmpeg.ts

@@ -1,27 +0,0 @@
-import { IFFmpeg } from 'services/ffmpeg/ffmpegFactory';
-import { ElectronAPIs } from 'types/electron';
-import { ElectronFile } from 'types/upload';
-
-export class ElectronFFmpeg implements IFFmpeg {
-    private electronAPIs: ElectronAPIs;
-
-    constructor() {
-        this.electronAPIs = globalThis['ElectronAPIs'];
-    }
-
-    async run(
-        cmd: string[],
-        inputFile: ElectronFile | File,
-        outputFilename: string,
-        dontTimeout?: boolean
-    ) {
-        if (this.electronAPIs?.runFFmpegCmd) {
-            return this.electronAPIs.runFFmpegCmd(
-                cmd,
-                inputFile,
-                outputFilename,
-                dontTimeout
-            );
-        }
-    }
-}

+ 0 - 48
apps/photos/src/services/electron/fs.ts

@@ -1,48 +0,0 @@
-import { ElectronAPIs } from 'types/electron';
-import { logError } from '@ente/shared/sentry';
-
-class ElectronFSService {
-    private electronAPIs: ElectronAPIs;
-
-    constructor() {
-        this.electronAPIs = globalThis['ElectronAPIs'];
-    }
-
-    getDirFiles(dirPath: string) {
-        if (this.electronAPIs.getDirFiles) {
-            return this.electronAPIs.getDirFiles(dirPath);
-        }
-    }
-
-    async isFolder(folderPath: string) {
-        try {
-            const isFolder = await this.electronAPIs.isFolder(folderPath);
-            return isFolder;
-        } catch (e) {
-            logError(e, 'error while checking if is Folder');
-        }
-    }
-
-    async saveMediaFile(
-        filePath: string,
-        fileStream: ReadableStream<Uint8Array>
-    ) {
-        try {
-            await this.electronAPIs.saveStreamToDisk(filePath, fileStream);
-        } catch (e) {
-            logError(e, 'error while saving media file');
-            throw e;
-        }
-    }
-
-    deleteFile(filePath: string) {
-        try {
-            this.electronAPIs.deleteFile(filePath);
-        } catch (e) {
-            logError(e, 'error while deleting file');
-            throw e;
-        }
-    }
-}
-
-export default new ElectronFSService();

+ 0 - 42
apps/photos/src/services/electron/safeStorage.tsx

@@ -1,42 +0,0 @@
-import { ElectronAPIs } from 'types/electron';
-import { logError } from '@ente/shared/sentry';
-
-class SafeStorageService {
-    private electronAPIs: ElectronAPIs;
-    private allElectronAPIsExist: boolean = false;
-    constructor() {
-        this.electronAPIs = globalThis['ElectronAPIs'];
-        this.allElectronAPIsExist = !!this.electronAPIs?.getEncryptionKey;
-    }
-
-    async getEncryptionKey() {
-        try {
-            if (this.allElectronAPIsExist) {
-                return (await this.electronAPIs.getEncryptionKey()) as string;
-            }
-        } catch (e) {
-            logError(e, 'getEncryptionKey failed');
-        }
-    }
-
-    async setEncryptionKey(encryptionKey: string) {
-        try {
-            if (this.allElectronAPIsExist) {
-                return await this.electronAPIs.setEncryptionKey(encryptionKey);
-            }
-        } catch (e) {
-            logError(e, 'setEncryptionKey failed');
-        }
-    }
-
-    async clearElectronStore() {
-        try {
-            if (this.allElectronAPIsExist) {
-                return this.electronAPIs.clearElectronStore();
-            }
-        } catch (e) {
-            logError(e, 'clearElectronStore failed');
-        }
-    }
-}
-export default new SafeStorageService();

+ 0 - 36
apps/photos/src/services/electron/update.ts

@@ -1,36 +0,0 @@
-import { AppUpdateInfo, ElectronAPIs } from 'types/electron';
-
-class ElectronUpdateService {
-    private electronAPIs: ElectronAPIs;
-
-    constructor() {
-        this.electronAPIs = globalThis['ElectronAPIs'];
-    }
-
-    registerUpdateEventListener(
-        showUpdateDialog: (updateInfo: AppUpdateInfo) => void
-    ) {
-        if (this.electronAPIs?.registerUpdateEventListener) {
-            this.electronAPIs.registerUpdateEventListener(showUpdateDialog);
-        }
-    }
-
-    updateAndRestart() {
-        if (this.electronAPIs?.updateAndRestart) {
-            this.electronAPIs.updateAndRestart();
-        }
-    }
-
-    skipAppUpdate(version: string) {
-        if (this.electronAPIs?.skipAppUpdate) {
-            this.electronAPIs.skipAppUpdate(version);
-        }
-    }
-    muteUpdateNotification(version: string) {
-        if (this.electronAPIs?.muteUpdateNotification) {
-            this.electronAPIs.muteUpdateNotification(version);
-        }
-    }
-}
-
-export default new ElectronUpdateService();

+ 2 - 2
apps/photos/src/services/embeddingService.ts

@@ -4,11 +4,11 @@ import {
     GetEmbeddingDiffResponse,
     PutEmbeddingRequest,
 } from 'types/embedding';
-import ComlinkCryptoWorker from 'utils/comlink/ComlinkCryptoWorker';
+import ComlinkCryptoWorker from '@ente/shared/crypto';
 import { getEndpoint } from 'utils/common/apiUtil';
 import { addLogLine } from '@ente/shared/logging';
 import { logError } from '@ente/shared/sentry';
-import localForage from 'utils/storage/localForage';
+import localForage from '@ente/shared/storage/localForage';
 import { getAllLocalFiles } from './fileService';
 import HTTPService from './HTTPService';
 import { getToken } from 'utils/common/key';

+ 2 - 2
apps/photos/src/services/entityService.ts

@@ -1,9 +1,9 @@
 import { getToken } from 'utils/common/key';
-import localForage from 'utils/storage/localForage';
+import localForage from '@ente/shared/storage/localForage';
 import HTTPService from './HTTPService';
 import { getEndpoint } from 'utils/common/apiUtil';
 import { logError } from '@ente/shared/sentry';
-import ComlinkCryptoWorker from 'utils/comlink/ComlinkCryptoWorker';
+import ComlinkCryptoWorker from '@ente/shared/crypto';
 import { getActualKey } from 'utils/common/key';
 import {
     EntityType,

+ 29 - 37
apps/photos/src/services/export/index.ts

@@ -23,7 +23,7 @@ import {
     getCollectionIDFromFileUID,
 } from 'utils/export';
 import { logError } from '@ente/shared/sentry';
-import { getData, LS_KEYS, setData } from 'utils/storage/localStorage';
+import { getData, LS_KEYS, setData } from '@ente/shared/storage/localStorage';
 import { getAllLocalCollections } from '../collectionService';
 import downloadManager from '../downloadManager';
 import { getAllLocalFiles } from '../fileService';
@@ -51,7 +51,6 @@ import {
 import { User } from 'types/user';
 import { FILE_TYPE } from 'constants/file';
 import { ExportStage } from 'constants/export';
-import { ElectronAPIs } from 'types/electron';
 import { CustomError } from 'utils/error';
 import { addLogLine } from '@ente/shared/logging';
 import { eventBus, Events } from '../events';
@@ -61,7 +60,7 @@ import {
     getNonEmptyPersonalCollections,
 } from 'utils/collection';
 import { migrateExport } from './migration';
-import ElectronFSService from '../electron/fs';
+import ElectronAPIs from '@ente/shared/electron';
 
 const EXPORT_RECORD_FILE_NAME = 'export_status.json';
 
@@ -76,7 +75,6 @@ export const NULL_EXPORT_RECORD: ExportRecord = {
 };
 
 class ExportService {
-    private electronAPIs: ElectronAPIs;
     private exportSettings: ExportSettings;
     private exportInProgress: RequestCanceller = null;
     private reRunNeeded = false;
@@ -95,10 +93,6 @@ class ExportService {
         failed: 0,
     };
 
-    constructor() {
-        this.electronAPIs = globalThis['ElectronAPIs'];
-    }
-
     getExportSettings(): ExportSettings {
         try {
             if (this.exportSettings) {
@@ -166,12 +160,12 @@ class ExportService {
 
     async changeExportDirectory() {
         try {
-            const newRootDir = await this.electronAPIs.selectDirectory();
+            const newRootDir = await ElectronAPIs.selectDirectory();
             if (!newRootDir) {
                 throw Error(CustomError.SELECT_FOLDER_ABORTED);
             }
             const newExportDir = `${newRootDir}/${ENTE_EXPORT_DIRECTORY}`;
-            await this.electronAPIs.checkExistsAndCreateDir(newExportDir);
+            await ElectronAPIs.checkExistsAndCreateDir(newExportDir);
             return newExportDir;
         } catch (e) {
             if (e.message !== CustomError.SELECT_FOLDER_ABORTED) {
@@ -183,7 +177,7 @@ class ExportService {
 
     async openExportDirectory(exportFolder: string) {
         try {
-            await this.electronAPIs.openDirectory(exportFolder);
+            await ElectronAPIs.openDirectory(exportFolder);
         } catch (e) {
             logError(e, 'openExportDirectory failed');
         }
@@ -529,7 +523,7 @@ class ExportService {
                         newCollectionExportName
                     );
                     try {
-                        await this.electronAPIs.rename(
+                        await ElectronAPIs.rename(
                             oldCollectionExportPath,
                             newCollectionExportPath
                         );
@@ -614,13 +608,11 @@ class ExportService {
                     );
                     try {
                         // delete the collection metadata folder
-                        await this.electronAPIs.deleteFolder(
+                        await ElectronAPIs.deleteFolder(
                             getMetadataFolderExportPath(collectionExportPath)
                         );
                         // delete the collection folder
-                        await this.electronAPIs.deleteFolder(
-                            collectionExportPath
-                        );
+                        await ElectronAPIs.deleteFolder(collectionExportPath);
                     } catch (e) {
                         await this.addCollectionExportedRecord(
                             exportFolder,
@@ -703,10 +695,10 @@ class ExportService {
                         exportDir,
                         collectionExportName
                     );
-                    await this.electronAPIs.checkExistsAndCreateDir(
+                    await ElectronAPIs.checkExistsAndCreateDir(
                         collectionExportPath
                     );
-                    await this.electronAPIs.checkExistsAndCreateDir(
+                    await ElectronAPIs.checkExistsAndCreateDir(
                         getMetadataFolderExportPath(collectionExportPath)
                     );
                     await this.downloadAndSave(
@@ -786,7 +778,7 @@ class ExportService {
                                 `moving image file ${imageExportPath} to trash folder`
                             );
                             if (this.exists(imageExportPath)) {
-                                await this.electronAPIs.moveFile(
+                                await ElectronAPIs.moveFile(
                                     imageExportPath,
                                     getTrashedFileExportPath(
                                         exportDir,
@@ -799,7 +791,7 @@ class ExportService {
                                 getMetadataFileExportPath(imageExportPath);
 
                             if (this.exists(imageMetadataFileExportPath)) {
-                                await this.electronAPIs.moveFile(
+                                await ElectronAPIs.moveFile(
                                     imageMetadataFileExportPath,
                                     getTrashedFileExportPath(
                                         exportDir,
@@ -816,7 +808,7 @@ class ExportService {
                                 `moving video file ${videoExportPath} to trash folder`
                             );
                             if (this.exists(videoExportPath)) {
-                                await this.electronAPIs.moveFile(
+                                await ElectronAPIs.moveFile(
                                     videoExportPath,
                                     getTrashedFileExportPath(
                                         exportDir,
@@ -827,7 +819,7 @@ class ExportService {
                             const videoMetadataFileExportPath =
                                 getMetadataFileExportPath(videoExportPath);
                             if (this.exists(videoMetadataFileExportPath)) {
-                                await this.electronAPIs.moveFile(
+                                await ElectronAPIs.moveFile(
                                     videoMetadataFileExportPath,
                                     getTrashedFileExportPath(
                                         exportDir,
@@ -848,7 +840,7 @@ class ExportService {
                                 `moving file ${fileExportPath} to ${trashedFilePath} trash folder`
                             );
                             if (this.exists(fileExportPath)) {
-                                await this.electronAPIs.moveFile(
+                                await ElectronAPIs.moveFile(
                                     fileExportPath,
                                     trashedFilePath
                                 );
@@ -856,7 +848,7 @@ class ExportService {
                             const metadataFileExportPath =
                                 getMetadataFileExportPath(fileExportPath);
                             if (this.exists(metadataFileExportPath)) {
-                                await this.electronAPIs.moveFile(
+                                await ElectronAPIs.moveFile(
                                     metadataFileExportPath,
                                     getTrashedFileExportPath(
                                         exportDir,
@@ -995,7 +987,7 @@ class ExportService {
         try {
             const exportRecord = await this.getExportRecord(folder);
             const newRecord: ExportRecord = { ...exportRecord, ...newData };
-            await this.electronAPIs.saveFileToDisk(
+            await ElectronAPIs.saveFileToDisk(
                 `${folder}/${EXPORT_RECORD_FILE_NAME}`,
                 JSON.stringify(newRecord, null, 2)
             );
@@ -1016,7 +1008,7 @@ class ExportService {
             if (!this.exists(exportRecordJSONPath)) {
                 return this.createEmptyExportRecord(exportRecordJSONPath);
             }
-            const recordFile = await this.electronAPIs.readTextFile(
+            const recordFile = await ElectronAPIs.readTextFile(
                 exportRecordJSONPath
             );
             try {
@@ -1054,8 +1046,8 @@ class ExportService {
             exportFolder,
             collectionExportName
         );
-        await this.electronAPIs.checkExistsAndCreateDir(collectionExportPath);
-        await this.electronAPIs.checkExistsAndCreateDir(
+        await ElectronAPIs.checkExistsAndCreateDir(collectionExportPath);
+        await ElectronAPIs.checkExistsAndCreateDir(
             getMetadataFolderExportPath(collectionExportPath)
         );
 
@@ -1102,7 +1094,7 @@ class ExportService {
                         fileExportName,
                         file
                     );
-                    await ElectronFSService.saveMediaFile(
+                    await ElectronAPIs.saveStreamToDisk(
                         getFileExportPath(collectionExportPath, fileExportName),
                         updatedFileStream
                     );
@@ -1150,7 +1142,7 @@ class ExportService {
                 imageExportName,
                 file
             );
-            await ElectronFSService.saveMediaFile(
+            await ElectronAPIs.saveStreamToDisk(
                 getFileExportPath(collectionExportPath, imageExportName),
                 imageStream
             );
@@ -1162,12 +1154,12 @@ class ExportService {
                 file
             );
             try {
-                await ElectronFSService.saveMediaFile(
+                await ElectronAPIs.saveStreamToDisk(
                     getFileExportPath(collectionExportPath, videoExportName),
                     videoStream
                 );
             } catch (e) {
-                ElectronFSService.deleteFile(
+                ElectronAPIs.deleteFile(
                     getFileExportPath(collectionExportPath, imageExportName)
                 );
                 throw e;
@@ -1183,7 +1175,7 @@ class ExportService {
         fileExportName: string,
         file: EnteFile
     ) {
-        await this.electronAPIs.saveFileToDisk(
+        await ElectronAPIs.saveFileToDisk(
             getFileMetadataExportPath(collectionExportPath, fileExportName),
             getGoogleLikeMetadataFile(fileExportName, file)
         );
@@ -1194,15 +1186,15 @@ class ExportService {
     };
 
     exists = (path: string) => {
-        return this.electronAPIs.exists(path);
+        return ElectronAPIs.exists(path);
     };
 
     rename = (oldPath: string, newPath: string) => {
-        return this.electronAPIs.rename(oldPath, newPath);
+        return ElectronAPIs.rename(oldPath, newPath);
     };
 
     checkExistsAndCreateDir = (path: string) => {
-        return this.electronAPIs.checkExistsAndCreateDir(path);
+        return ElectronAPIs.checkExistsAndCreateDir(path);
     };
 
     exportFolderExists = (exportFolder: string) => {
@@ -1224,7 +1216,7 @@ class ExportService {
 
     private createEmptyExportRecord = async (exportRecordJSONPath: string) => {
         const exportRecord: ExportRecord = NULL_EXPORT_RECORD;
-        await this.electronAPIs.saveFileToDisk(
+        await ElectronAPIs.saveFileToDisk(
             exportRecordJSONPath,
             JSON.stringify(exportRecord, null, 2)
         );

+ 1 - 1
apps/photos/src/services/export/migration.ts

@@ -26,7 +26,7 @@ import {
 } from 'utils/file';
 import { addLocalLog, addLogLine } from '@ente/shared/logging';
 import { logError } from '@ente/shared/sentry';
-import { getData, LS_KEYS } from 'utils/storage/localStorage';
+import { getData, LS_KEYS } from '@ente/shared/storage/localStorage';
 import exportService from './index';
 import { Collection } from 'types/collection';
 import {

+ 11 - 2
apps/photos/src/services/ffmpeg/ffmpegFactory.ts

@@ -1,5 +1,5 @@
+import ElectronAPIs from '@ente/shared/electron';
 import isElectron from 'is-electron';
-import { ElectronFFmpeg } from 'services/electron/ffmpeg';
 import { ElectronFile } from 'types/upload';
 import ComlinkFFmpegWorker from 'utils/comlink/ComlinkFFmpegWorker';
 
@@ -17,7 +17,16 @@ class FFmpegFactory {
     async getFFmpegClient() {
         if (!this.client) {
             if (isElectron()) {
-                this.client = new ElectronFFmpeg();
+                this.client = {
+                    run(cmd, inputFile, outputFilename, dontTimeout) {
+                        return ElectronAPIs.runFFmpegCmd(
+                            cmd,
+                            inputFile,
+                            outputFilename,
+                            dontTimeout
+                        );
+                    },
+                };
             } else {
                 this.client = await ComlinkFFmpegWorker.getInstance();
             }

+ 2 - 2
apps/photos/src/services/fileService.ts

@@ -1,5 +1,5 @@
 import { getEndpoint } from 'utils/common/apiUtil';
-import localForage from 'utils/storage/localForage';
+import localForage from '@ente/shared/storage/localForage';
 
 import { getToken } from 'utils/common/key';
 import { Collection } from 'types/collection';
@@ -22,7 +22,7 @@ import {
 import { SetFiles } from 'types/gallery';
 import { BulkUpdateMagicMetadataRequest } from 'types/magicMetadata';
 import { addLogLine } from '@ente/shared/logging';
-import ComlinkCryptoWorker from 'utils/comlink/ComlinkCryptoWorker';
+import ComlinkCryptoWorker from '@ente/shared/crypto';
 import {
     getCollectionLastSyncTime,
     setCollectionLastSyncTime,

+ 5 - 20
apps/photos/src/services/electron/imageProcessor.ts → apps/photos/src/services/imageProcessor.ts

@@ -1,28 +1,16 @@
-import { ElectronAPIs } from 'types/electron';
+import ElectronAPIs from '@ente/shared/electron';
+import { addLogLine } from '@ente/shared/logging';
+import { logError } from '@ente/shared/sentry';
 import { ElectronFile } from 'types/upload';
 import { CustomError } from 'utils/error';
 import { convertBytesToHumanReadable } from 'utils/file/size';
-import { addLogLine } from '@ente/shared/logging';
-import { logError } from '@ente/shared/sentry';
 
 class ElectronImageProcessorService {
-    private electronAPIs: ElectronAPIs;
-    constructor() {
-        this.electronAPIs = globalThis['ElectronAPIs'];
-    }
-
-    generateImageThumbnailAPIExists() {
-        return !!this.electronAPIs?.generateImageThumbnail;
-    }
-
     async convertToJPEG(fileBlob: Blob, filename: string): Promise<Blob> {
         try {
-            if (!this.electronAPIs?.convertToJPEG) {
-                throw new Error('convertToJPEG API not available');
-            }
             const startTime = Date.now();
             const inputFileData = new Uint8Array(await fileBlob.arrayBuffer());
-            const convertedFileData = await this.electronAPIs.convertToJPEG(
+            const convertedFileData = await ElectronAPIs.convertToJPEG(
                 inputFileData,
                 filename
             );
@@ -51,11 +39,8 @@ class ElectronImageProcessorService {
         maxSize: number
     ): Promise<Uint8Array> {
         try {
-            if (!this.electronAPIs?.generateImageThumbnail) {
-                throw new Error('generateImageThumbnail API not available');
-            }
             const startTime = Date.now();
-            const thumb = await this.electronAPIs.generateImageThumbnail(
+            const thumb = await ElectronAPIs.generateImageThumbnail(
                 inputFile,
                 maxDimension,
                 maxSize

+ 25 - 86
apps/photos/src/services/importService.ts

@@ -1,8 +1,8 @@
 import { PICKED_UPLOAD_TYPE } from 'constants/upload';
 import { Collection } from 'types/collection';
-import { ElectronAPIs } from 'types/electron';
 import { ElectronFile, FileWithCollection } from 'types/upload';
 import { logError } from '@ente/shared/sentry';
+import ElectronAPIs from '@ente/shared/electron';
 
 interface PendingUploads {
     files: ElectronFile[];
@@ -10,53 +10,12 @@ interface PendingUploads {
     type: PICKED_UPLOAD_TYPE;
 }
 
-interface selectZipResult {
-    files: ElectronFile[];
-    zipPaths: string[];
-}
 class ImportService {
-    electronAPIs: ElectronAPIs;
-    private allElectronAPIsExist: boolean = false;
-
-    constructor() {
-        this.electronAPIs = globalThis['ElectronAPIs'];
-        this.allElectronAPIsExist = !!this.electronAPIs?.getPendingUploads;
-    }
-
-    async getElectronFilesFromGoogleZip(
-        zipPath: string
-    ): Promise<ElectronFile[]> {
-        if (this.allElectronAPIsExist) {
-            return this.electronAPIs.getElectronFilesFromGoogleZip(zipPath);
-        }
-    }
-
-    checkAllElectronAPIsExists = () => this.allElectronAPIsExist;
-
-    async showUploadFilesDialog(): Promise<ElectronFile[]> {
-        if (this.allElectronAPIsExist) {
-            return this.electronAPIs.showUploadFilesDialog();
-        }
-    }
-
-    async showUploadDirsDialog(): Promise<ElectronFile[]> {
-        if (this.allElectronAPIsExist) {
-            return this.electronAPIs.showUploadDirsDialog();
-        }
-    }
-
-    async showUploadZipDialog(): Promise<selectZipResult> {
-        if (this.allElectronAPIsExist) {
-            return this.electronAPIs.showUploadZipDialog();
-        }
-    }
     async getPendingUploads(): Promise<PendingUploads> {
         try {
-            if (this.allElectronAPIsExist) {
-                const pendingUploads =
-                    (await this.electronAPIs.getPendingUploads()) as PendingUploads;
-                return pendingUploads;
-            }
+            const pendingUploads =
+                (await ElectronAPIs.getPendingUploads()) as PendingUploads;
+            return pendingUploads;
         } catch (e) {
             if (e?.message?.includes('ENOENT: no such file or directory')) {
                 // ignore
@@ -68,9 +27,8 @@ class ImportService {
     }
 
     async setToUploadCollection(collections: Collection[]) {
-        if (this.allElectronAPIsExist) {
-            let collectionName: string = null;
-            /* collection being one suggest one of two things
+        let collectionName: string = null;
+        /* collection being one suggest one of two things
                 1. Either the user has upload to a single existing collection
                 2. Created a new single collection to upload to 
                     may have had multiple folder, but chose to upload
@@ -79,52 +37,33 @@ class ImportService {
                 helps the info of user choosing this options
                 and on next upload we can directly start uploading to this collection 
             */
-            if (collections.length === 1) {
-                collectionName = collections[0].name;
-            }
-            this.electronAPIs.setToUploadCollection(collectionName);
-        }
-    }
-
-    async setToUploadFiles(
-        type: PICKED_UPLOAD_TYPE.FILES | PICKED_UPLOAD_TYPE.ZIPS,
-        filePaths: string[]
-    ) {
-        if (this.allElectronAPIsExist) {
-            this.electronAPIs.setToUploadFiles(type, filePaths);
+        if (collections.length === 1) {
+            collectionName = collections[0].name;
         }
+        ElectronAPIs.setToUploadCollection(collectionName);
     }
 
     updatePendingUploads(files: FileWithCollection[]) {
-        if (this.allElectronAPIsExist) {
-            const filePaths = [];
-            for (const fileWithCollection of files) {
-                if (fileWithCollection.isLivePhoto) {
-                    filePaths.push(
-                        (
-                            fileWithCollection.livePhotoAssets
-                                .image as ElectronFile
-                        ).path,
-                        (
-                            fileWithCollection.livePhotoAssets
-                                .video as ElectronFile
-                        ).path
-                    );
-                } else {
-                    filePaths.push(
-                        (fileWithCollection.file as ElectronFile).path
-                    );
-                }
+        const filePaths = [];
+        for (const fileWithCollection of files) {
+            if (fileWithCollection.isLivePhoto) {
+                filePaths.push(
+                    (fileWithCollection.livePhotoAssets.image as ElectronFile)
+                        .path,
+                    (fileWithCollection.livePhotoAssets.video as ElectronFile)
+                        .path
+                );
+            } else {
+                filePaths.push((fileWithCollection.file as ElectronFile).path);
             }
-            this.setToUploadFiles(PICKED_UPLOAD_TYPE.FILES, filePaths);
         }
+        ElectronAPIs.setToUploadFiles(PICKED_UPLOAD_TYPE.FILES, filePaths);
     }
+
     cancelRemainingUploads() {
-        if (this.allElectronAPIsExist) {
-            this.electronAPIs.setToUploadCollection(null);
-            this.electronAPIs.setToUploadFiles(PICKED_UPLOAD_TYPE.ZIPS, []);
-            this.electronAPIs.setToUploadFiles(PICKED_UPLOAD_TYPE.FILES, []);
-        }
+        ElectronAPIs.setToUploadCollection(null);
+        ElectronAPIs.setToUploadFiles(PICKED_UPLOAD_TYPE.ZIPS, []);
+        ElectronAPIs.setToUploadFiles(PICKED_UPLOAD_TYPE.FILES, []);
     }
 }
 

+ 2 - 2
apps/photos/src/services/machineLearning/machineLearningFactory.ts

@@ -30,8 +30,8 @@ import mobileFaceNetEmbeddingService from './mobileFaceNetEmbeddingService';
 import dbscanClusteringService from './dbscanClusteringService';
 import ssdMobileNetV2Service from './ssdMobileNetV2Service';
 import imageSceneService from './imageSceneService';
-import { getDedicatedCryptoWorker } from 'utils/comlink/ComlinkCryptoWorker';
-import { ComlinkWorker } from 'utils/comlink/comlinkWorker';
+import { getDedicatedCryptoWorker } from '@ente/shared/crypto';
+import { ComlinkWorker } from '@ente/shared/worker/comlinkWorker';
 import { DedicatedCryptoWorker } from 'worker/crypto.worker';
 import { addLogLine } from '@ente/shared/logging';
 

+ 1 - 1
apps/photos/src/services/machineLearning/mlWorkManager.ts

@@ -9,7 +9,7 @@ import { getMLSyncJobConfig } from 'utils/machineLearning/config';
 import { logError } from '@ente/shared/sentry';
 import mlIDbStorage from 'utils/storage/mlIDbStorage';
 import { MLSyncJobResult, MLSyncJob } from './mlSyncJob';
-import { ComlinkWorker } from 'utils/comlink/comlinkWorker';
+import { ComlinkWorker } from '@ente/shared/worker/comlinkWorker';
 import { DedicatedMLWorker } from 'worker/ml.worker';
 import { getDedicatedMLWorker } from 'utils/comlink/ComlinkMLWorker';
 import { addLogLine } from '@ente/shared/logging';

+ 1 - 1
apps/photos/src/services/migrateThumbnailService.ts

@@ -13,7 +13,7 @@ import { UploadURL } from 'types/upload';
 import { S3FileAttributes } from 'types/file';
 import { Remote } from 'comlink';
 import { DedicatedCryptoWorker } from 'worker/crypto.worker';
-import ComlinkCryptoWorker from 'utils/comlink/ComlinkCryptoWorker';
+import ComlinkCryptoWorker from '@ente/shared/crypto';
 
 const ENDPOINT = getEndpoint();
 const REPLACE_THUMBNAIL_THRESHOLD = 500 * 1024; // 500KB

+ 1 - 1
apps/photos/src/services/publicCollectionDownloadManager.ts

@@ -13,7 +13,7 @@ import { EnteFile } from 'types/file';
 import { logError } from '@ente/shared/sentry';
 import { FILE_TYPE } from 'constants/file';
 import { CustomError } from 'utils/error';
-import ComlinkCryptoWorker from 'utils/comlink/ComlinkCryptoWorker';
+import ComlinkCryptoWorker from '@ente/shared/crypto';
 import { CACHES } from 'constants/cache';
 import { CacheStorageService } from './cache/cacheStorageService';
 import { LimitedCache } from 'types/cache';

+ 2 - 2
apps/photos/src/services/publicCollectionService.ts

@@ -1,5 +1,5 @@
 import { getEndpoint } from 'utils/common/apiUtil';
-import localForage from 'utils/storage/localForage';
+import localForage from '@ente/shared/storage/localForage';
 import { Collection, CollectionPublicMagicMetadata } from 'types/collection';
 import HTTPService from './HTTPService';
 import { logError } from '@ente/shared/sentry';
@@ -12,7 +12,7 @@ import {
 } from 'types/publicCollection';
 import { REPORT_REASON } from 'constants/publicCollection';
 import { CustomError, parseSharingErrorCodes } from 'utils/error';
-import ComlinkCryptoWorker from 'utils/comlink/ComlinkCryptoWorker';
+import ComlinkCryptoWorker from '@ente/shared/crypto';
 
 const ENDPOINT = getEndpoint();
 const PUBLIC_COLLECTION_FILES_TABLE = 'public-collection-files';

+ 1 - 1
apps/photos/src/services/trashService.ts

@@ -4,7 +4,7 @@ import { getEndpoint } from 'utils/common/apiUtil';
 import { getToken } from 'utils/common/key';
 import { decryptFile, sortTrashFiles } from 'utils/file';
 import { logError } from '@ente/shared/sentry';
-import localForage from 'utils/storage/localForage';
+import localForage from '@ente/shared/storage/localForage';
 import { getCollection } from './collectionService';
 
 import HTTPService from './HTTPService';

+ 4 - 3
apps/photos/src/services/upload/thumbnailService.ts

@@ -3,7 +3,7 @@ import { CustomError, errorWithContext } from 'utils/error';
 import { logError } from '@ente/shared/sentry';
 import { BLACK_THUMBNAIL_BASE64 } from 'constants/upload';
 import * as FFmpegService from 'services/ffmpeg/ffmpegService';
-import ElectronImageProcessorService from 'services/electron/imageProcessor';
+import ElectronAPIs from '@ente/shared/electron';
 import { convertBytesToHumanReadable } from 'utils/file/size';
 import { ElectronFile, FileTypeInfo } from 'types/upload';
 import { getUint8ArrayView } from '../readerService';
@@ -11,6 +11,7 @@ import { addLogLine } from '@ente/shared/logging';
 import { getFileNameSize } from '@ente/shared/logging/web';
 import HeicConversionService from 'services/heicConversionService';
 import { isFileHEIC } from 'utils/file';
+import isElectron from 'is-electron';
 
 const MAX_THUMBNAIL_DIMENSION = 720;
 const MIN_COMPRESSION_PERCENTAGE_SIZE_DIFF = 10;
@@ -83,9 +84,9 @@ async function generateImageThumbnail(
     file: File | ElectronFile,
     fileTypeInfo: FileTypeInfo
 ) {
-    if (ElectronImageProcessorService.generateImageThumbnailAPIExists()) {
+    if (isElectron()) {
         try {
-            return await ElectronImageProcessorService.generateImageThumbnail(
+            return await ElectronAPIs.generateImageThumbnail(
                 file,
                 MAX_THUMBNAIL_DIMENSION,
                 MAX_THUMBNAIL_SIZE

+ 2 - 2
apps/photos/src/services/upload/uploadManager.ts

@@ -31,13 +31,13 @@ import watchFolderService from 'services/watchFolder/watchFolderService';
 import { ProgressUpdater } from 'types/upload/ui';
 import uploadCancelService from './uploadCancelService';
 import { DedicatedCryptoWorker } from 'worker/crypto.worker';
-import { ComlinkWorker } from 'utils/comlink/comlinkWorker';
+import { ComlinkWorker } from '@ente/shared/worker/comlinkWorker';
 import { Remote } from 'comlink';
 import {
     getLocalPublicFiles,
     getPublicCollectionUID,
 } from 'services/publicCollectionService';
-import { getDedicatedCryptoWorker } from 'utils/comlink/ComlinkCryptoWorker';
+import { getDedicatedCryptoWorker } from '@ente/shared/crypto';
 import { getDisableCFUploadProxyFlag } from 'services/userService';
 
 const MAX_CONCURRENT_UPLOADS = 4;

+ 2 - 2
apps/photos/src/services/userService.ts

@@ -4,7 +4,7 @@ import {
     isDevDeployment,
 } from 'utils/common/apiUtil';
 import { getData, LS_KEYS } from '@ente/shared/storage/localStorage';
-import localForage from 'utils/storage/localForage';
+import localForage from '@ente/shared/storage/localForage';
 import { getToken } from 'utils/common/key';
 import HTTPService from './HTTPService';
 import { getRecoveryKey } from 'utils/crypto';
@@ -18,7 +18,7 @@ import {
 import { ApiError } from 'utils/error';
 import { getLocalFamilyData, isPartOfFamily } from 'utils/user/family';
 import { AxiosResponse, HttpStatusCode } from 'axios';
-import { setLocalMapEnabled } from 'utils/storage';
+import { setLocalMapEnabled } from '@ente/shared/storage/localStorage/helpers';
 import { putAttributes } from '@ente/accounts/api/user';
 import { logoutUser } from '@ente/accounts/services/user';
 

+ 1 - 1
apps/photos/src/services/wasmHeicConverter/wasmHEICConverterService.ts

@@ -4,7 +4,7 @@ import { retryAsyncFunction } from 'utils/network';
 import { logError } from '@ente/shared/sentry';
 import { addLogLine } from '@ente/shared/logging';
 import { DedicatedConvertWorker } from 'worker/convert.worker';
-import { ComlinkWorker } from 'utils/comlink/comlinkWorker';
+import { ComlinkWorker } from '@ente/shared/worker/comlinkWorker';
 import { convertBytesToHumanReadable } from 'utils/file/size';
 import { getDedicatedConvertWorker } from 'utils/comlink/ComlinkConvertWorker';
 

+ 13 - 19
apps/photos/src/services/watchFolder/watchFolderService.ts

@@ -9,7 +9,6 @@ import {
     WatchMapping,
     WatchMappingSyncedFile,
 } from 'types/watchFolder';
-import { ElectronAPIs } from 'types/electron';
 import debounce from 'debounce-promise';
 import {
     diskFileAddedCallback,
@@ -22,9 +21,9 @@ import uploadManager from 'services/upload/uploadManager';
 import { addLocalLog, addLogLine } from '@ente/shared/logging';
 import { getValidFilesToUpload } from 'utils/watch';
 import { groupFilesBasedOnCollectionID } from 'utils/file';
+import ElectronAPIs from '@ente/shared/electron';
 
 class watchFolderService {
-    private electronAPIs: ElectronAPIs;
     private allElectronAPIsExist: boolean = false;
     private eventQueue: EventQueueItem[] = [];
     private currentEvent: EventQueueItem;
@@ -40,11 +39,6 @@ class watchFolderService {
     private syncWithRemote: () => void;
     private setWatchFolderServiceIsRunning: (isRunning: boolean) => void;
 
-    constructor() {
-        this.electronAPIs = globalThis['ElectronAPIs'];
-        this.allElectronAPIsExist = !!this.electronAPIs?.getWatchMappings;
-    }
-
     isUploadRunning() {
         return this.uploadRunning;
     }
@@ -88,7 +82,7 @@ class watchFolderService {
 
             for (const mapping of mappings) {
                 const filesOnDisk: ElectronFile[] =
-                    await this.electronAPIs.getDirFiles(mapping.folderPath);
+                    await ElectronAPIs.getDirFiles(mapping.folderPath);
 
                 this.uploadDiffOfFiles(mapping, filesOnDisk);
                 this.trashDiffOfFiles(mapping, filesOnDisk);
@@ -155,11 +149,11 @@ class watchFolderService {
     ): Promise<WatchMapping[]> {
         const notDeletedMappings = [];
         for (const mapping of mappings) {
-            const mappingExists = await this.electronAPIs.isFolder(
+            const mappingExists = await ElectronAPIs.isFolder(
                 mapping.folderPath
             );
             if (!mappingExists) {
-                this.electronAPIs.removeWatchMapping(mapping.folderPath);
+                ElectronAPIs.removeWatchMapping(mapping.folderPath);
             } else {
                 notDeletedMappings.push(mapping);
             }
@@ -178,7 +172,7 @@ class watchFolderService {
 
     private setupWatcherFunctions() {
         if (this.allElectronAPIsExist) {
-            this.electronAPIs.registerWatcherFunctions(
+            ElectronAPIs.registerWatcherFunctions(
                 diskFileAddedCallback,
                 diskFileRemovedCallback,
                 diskFolderRemovedCallback
@@ -193,7 +187,7 @@ class watchFolderService {
     ) {
         if (this.allElectronAPIsExist) {
             try {
-                await this.electronAPIs.addWatchMapping(
+                await ElectronAPIs.addWatchMapping(
                     rootFolderName,
                     folderPath,
                     uploadStrategy
@@ -208,7 +202,7 @@ class watchFolderService {
     async removeWatchMapping(folderPath: string) {
         if (this.allElectronAPIsExist) {
             try {
-                await this.electronAPIs.removeWatchMapping(folderPath);
+                await ElectronAPIs.removeWatchMapping(folderPath);
             } catch (e) {
                 logError(e, 'error while removing watch mapping');
             }
@@ -218,7 +212,7 @@ class watchFolderService {
     getWatchMappings(): WatchMapping[] {
         if (this.allElectronAPIsExist) {
             try {
-                return this.electronAPIs.getWatchMappings() ?? [];
+                return ElectronAPIs.getWatchMappings() ?? [];
             } catch (e) {
                 logError(e, 'error while getting watch mappings');
                 return [];
@@ -395,7 +389,7 @@ class watchFolderService {
                         ...this.currentlySyncedMapping.syncedFiles,
                         ...syncedFiles,
                     ];
-                    this.electronAPIs.updateWatchMappingSyncedFiles(
+                    ElectronAPIs.updateWatchMappingSyncedFiles(
                         this.currentlySyncedMapping.folderPath,
                         this.currentlySyncedMapping.syncedFiles
                     );
@@ -405,7 +399,7 @@ class watchFolderService {
                         ...this.currentlySyncedMapping.ignoredFiles,
                         ...ignoredFiles,
                     ];
-                    this.electronAPIs.updateWatchMappingIgnoredFiles(
+                    ElectronAPIs.updateWatchMappingIgnoredFiles(
                         this.currentlySyncedMapping.folderPath,
                         this.currentlySyncedMapping.ignoredFiles
                     );
@@ -521,7 +515,7 @@ class watchFolderService {
                 this.currentlySyncedMapping.syncedFiles.filter(
                     (file) => !filePathsToRemove.has(file.path)
                 );
-            this.electronAPIs.updateWatchMappingSyncedFiles(
+            ElectronAPIs.updateWatchMappingSyncedFiles(
                 this.currentlySyncedMapping.folderPath,
                 this.currentlySyncedMapping.syncedFiles
             );
@@ -613,7 +607,7 @@ class watchFolderService {
 
     async selectFolder(): Promise<string> {
         try {
-            const folderPath = await this.electronAPIs.selectDirectory();
+            const folderPath = await ElectronAPIs.selectDirectory();
             return folderPath;
         } catch (e) {
             logError(e, 'error while selecting folder');
@@ -641,7 +635,7 @@ class watchFolderService {
 
     async isFolder(folderPath: string) {
         try {
-            const isFolder = await this.electronAPIs.isFolder(folderPath);
+            const isFolder = await ElectronAPIs.isFolder(folderPath);
             return isFolder;
         } catch (e) {
             logError(e, 'error while checking if folder exists');

+ 3 - 3
apps/photos/src/services/workerElectronCache/client.ts

@@ -1,4 +1,4 @@
-import { ElectronCacheStorage } from 'services/electron/cache';
+import ElectronAPIs from '@ente/shared/electron';
 import * as Comlink from 'comlink';
 import {
     LimitedCache,
@@ -14,7 +14,7 @@ export class WorkerElectronCacheStorageClient
     implements ProxiedLimitedCacheStorage
 {
     async open(cacheName: string) {
-        const cache = await ElectronCacheStorage.open(cacheName);
+        const cache = await ElectronAPIs.openDiskCache(cacheName);
         return Comlink.proxy({
             match: Comlink.proxy(transformMatch(cache.match.bind(cache))),
             put: Comlink.proxy(transformPut(cache.put.bind(cache))),
@@ -23,7 +23,7 @@ export class WorkerElectronCacheStorageClient
     }
 
     async delete(cacheName: string) {
-        return await ElectronCacheStorage.delete(cacheName);
+        return await ElectronAPIs.deleteDiskCache(cacheName);
     }
 }
 

+ 0 - 100
apps/photos/src/types/electron/index.ts

@@ -1,100 +0,0 @@
-import { LimitedCache } from 'types/cache';
-import { ElectronFile } from 'types/upload';
-import { WatchMapping } from 'types/watchFolder';
-
-export interface AppUpdateInfo {
-    autoUpdatable: boolean;
-    version: string;
-}
-
-export interface ElectronAPIs {
-    exists: (path: string) => boolean;
-    checkExistsAndCreateDir: (dirPath: string) => Promise<void>;
-    saveStreamToDisk: (
-        path: string,
-        fileStream: ReadableStream<any>
-    ) => Promise<void>;
-    saveFileToDisk: (path: string, file: any) => Promise<void>;
-    selectDirectory: () => Promise<string>;
-    sendNotification: (content: string) => void;
-    readTextFile: (path: string) => Promise<string>;
-    showUploadFilesDialog: () => Promise<ElectronFile[]>;
-    showUploadDirsDialog: () => Promise<ElectronFile[]>;
-    getPendingUploads: () => Promise<{
-        files: ElectronFile[];
-        collectionName: string;
-        type: string;
-    }>;
-    setToUploadFiles: (type: string, filePaths: string[]) => void;
-    showUploadZipDialog: () => Promise<{
-        zipPaths: string[];
-        files: ElectronFile[];
-    }>;
-    getElectronFilesFromGoogleZip: (
-        filePath: string
-    ) => Promise<ElectronFile[]>;
-    setToUploadCollection: (collectionName: string) => void;
-    getDirFiles: (dirPath: string) => Promise<ElectronFile[]>;
-    getWatchMappings: () => WatchMapping[];
-    updateWatchMappingSyncedFiles: (
-        folderPath: string,
-        files: WatchMapping['syncedFiles']
-    ) => void;
-    updateWatchMappingIgnoredFiles: (
-        folderPath: string,
-        files: WatchMapping['ignoredFiles']
-    ) => void;
-    addWatchMapping: (
-        collectionName: string,
-        folderPath: string,
-        uploadStrategy: number
-    ) => Promise<void>;
-    removeWatchMapping: (folderPath: string) => Promise<void>;
-    registerWatcherFunctions: (
-        addFile: (file: ElectronFile) => Promise<void>,
-        removeFile: (path: string) => Promise<void>,
-        removeFolder: (folderPath: string) => Promise<void>
-    ) => void;
-    isFolder: (dirPath: string) => Promise<boolean>;
-    clearElectronStore: () => void;
-    setEncryptionKey: (encryptionKey: string) => Promise<void>;
-    getEncryptionKey: () => Promise<string>;
-    openDiskCache: (cacheName: string) => Promise<LimitedCache>;
-    deleteDiskCache: (cacheName: string) => Promise<boolean>;
-    logToDisk: (msg: string) => void;
-    convertToJPEG: (
-        fileData: Uint8Array,
-        filename: string
-    ) => Promise<Uint8Array>;
-    openLogDirectory: () => void;
-    registerUpdateEventListener: (
-        showUpdateDialog: (updateInfo: AppUpdateInfo) => void
-    ) => void;
-    updateAndRestart: () => void;
-    skipAppUpdate: (version: string) => void;
-    getSentryUserID: () => Promise<string>;
-    getAppVersion: () => Promise<string>;
-    runFFmpegCmd: (
-        cmd: string[],
-        inputFile: File | ElectronFile,
-        outputFileName: string,
-        dontTimeout?: boolean
-    ) => Promise<File>;
-    muteUpdateNotification: (version: string) => void;
-    generateImageThumbnail: (
-        inputFile: File | ElectronFile,
-        maxDimension: number,
-        maxSize: number
-    ) => Promise<Uint8Array>;
-    logRendererProcessMemoryUsage: (message: string) => Promise<void>;
-    registerForegroundEventListener: (onForeground: () => void) => void;
-    openDirectory: (dirPath: string) => Promise<void>;
-    moveFile: (oldPath: string, newPath: string) => Promise<void>;
-    deleteFolder: (path: string) => Promise<void>;
-    deleteFile: (path: string) => void;
-    rename: (oldPath: string, newPath: string) => Promise<void>;
-    updateOptOutOfCrashReports: (optOut: boolean) => Promise<void>;
-    computeImageEmbedding: (imageData: Uint8Array) => Promise<Float32Array>;
-    computeTextEmbedding: (text: string) => Promise<Float32Array>;
-    getPlatform: () => Promise<'mac' | 'windows' | 'linux'>;
-}

+ 1 - 1
apps/photos/src/utils/billing/index.ts

@@ -4,7 +4,7 @@ import billingService from 'services/billingService';
 import { Plan, Subscription } from 'types/billing';
 import { NextRouter } from 'next/router';
 import { SetLoading } from 'types/gallery';
-import { getData, LS_KEYS } from '../storage/localStorage';
+import { getData, LS_KEYS } from '@ente/shared/storage/localStorage';
 import { logError } from '@ente/shared/sentry';
 import { SetDialogBoxAttributes } from 'types/dialogBox';
 import { openLink } from 'utils/common';

+ 3 - 3
apps/photos/src/utils/collection/index.ts

@@ -17,7 +17,7 @@ import { getAllLocalFiles, getLocalFiles } from 'services/fileService';
 import { EnteFile } from 'types/file';
 import { CustomError } from 'utils/error';
 import { User } from 'types/user';
-import { getData, LS_KEYS } from 'utils/storage/localStorage';
+import { getData, LS_KEYS } from '@ente/shared/storage/localStorage';
 import { logError } from '@ente/shared/sentry';
 import {
     COLLECTION_ROLE,
@@ -45,7 +45,7 @@ import bs58 from 'bs58';
 import { t } from 'i18next';
 import isElectron from 'is-electron';
 import { SetCollectionDownloadProgressAttributes } from 'types/gallery';
-import ElectronService from 'services/electron/common';
+import ElectronAPIs from '@ente/shared/electron';
 import {
     getCollectionExportPath,
     getUniqueCollectionExportName,
@@ -186,7 +186,7 @@ async function downloadCollectionFiles(
         downloadDirPath: null,
     };
     if (isElectron()) {
-        const selectedDir = await ElectronService.selectDirectory();
+        const selectedDir = await ElectronAPIs.selectDirectory();
         if (!selectedDir) {
             return;
         }

+ 1 - 1
apps/photos/src/utils/comlink/ComlinkConvertWorker.ts

@@ -1,7 +1,7 @@
 import { Remote } from 'comlink';
 import { runningInBrowser } from 'utils/common';
 import { DedicatedConvertWorker } from 'worker/convert.worker';
-import { ComlinkWorker } from './comlinkWorker';
+import { ComlinkWorker } from '@ente/shared/worker/comlinkWorker';
 
 class ComlinkConvertWorker {
     private comlinkWorkerInstance: Remote<DedicatedConvertWorker>;

+ 0 - 25
apps/photos/src/utils/comlink/ComlinkCryptoWorker.ts

@@ -1,25 +0,0 @@
-import { Remote } from 'comlink';
-import { DedicatedCryptoWorker } from 'worker/crypto.worker';
-import { ComlinkWorker } from './comlinkWorker';
-
-class ComlinkCryptoWorker {
-    private comlinkWorkerInstance: Promise<Remote<DedicatedCryptoWorker>>;
-
-    async getInstance() {
-        if (!this.comlinkWorkerInstance) {
-            const comlinkWorker = getDedicatedCryptoWorker();
-            this.comlinkWorkerInstance = comlinkWorker.remote;
-        }
-        return this.comlinkWorkerInstance;
-    }
-}
-
-export const getDedicatedCryptoWorker = () => {
-    const cryptoComlinkWorker = new ComlinkWorker<typeof DedicatedCryptoWorker>(
-        'ente-crypto-worker',
-        new Worker(new URL('worker/crypto.worker.ts', import.meta.url))
-    );
-    return cryptoComlinkWorker;
-};
-
-export default new ComlinkCryptoWorker();

+ 1 - 1
apps/photos/src/utils/comlink/ComlinkFFmpegWorker.ts

@@ -1,6 +1,6 @@
 import { Remote } from 'comlink';
 import { DedicatedFFmpegWorker } from 'worker/ffmpeg.worker';
-import { ComlinkWorker } from './comlinkWorker';
+import { ComlinkWorker } from '@ente/shared/worker/comlinkWorker';
 
 class ComlinkFFmpegWorker {
     private comlinkWorkerInstance: Promise<Remote<DedicatedFFmpegWorker>>;

+ 1 - 1
apps/photos/src/utils/comlink/ComlinkMLWorker.ts

@@ -1,6 +1,6 @@
 import { runningInBrowser } from 'utils/common';
 import { DedicatedMLWorker } from 'worker/ml.worker';
-import { ComlinkWorker } from './comlinkWorker';
+import { ComlinkWorker } from '@ente/shared/worker/comlinkWorker';
 
 export const getDedicatedMLWorker = (name: string) => {
     if (runningInBrowser()) {

+ 0 - 27
apps/photos/src/utils/comlink/comlinkWorker.ts

@@ -1,27 +0,0 @@
-import { expose, Remote, wrap } from 'comlink';
-import { WorkerElectronCacheStorageClient } from 'services/workerElectronCache/client';
-import { addLocalLog } from '@ente/shared/logging';
-
-export class ComlinkWorker<T extends new () => InstanceType<T>> {
-    public remote: Promise<Remote<InstanceType<T>>>;
-    private worker: Worker;
-    private name: string;
-
-    constructor(name: string, worker: Worker) {
-        this.name = name;
-        this.worker = worker;
-
-        this.worker.onerror = (errorEvent) => {
-            console.error('Got error event from worker', errorEvent);
-        };
-        addLocalLog(() => `Initiated ${this.name}`);
-        const comlink = wrap<T>(this.worker);
-        this.remote = new comlink() as Promise<Remote<InstanceType<T>>>;
-        expose(WorkerElectronCacheStorageClient, this.worker);
-    }
-
-    public terminate() {
-        this.worker.terminate();
-        addLocalLog(() => `Terminated ${this.name}`);
-    }
-}

+ 1 - 1
apps/photos/src/utils/common/apiUtil.ts

@@ -1,4 +1,4 @@
-import { getData, LS_KEYS } from 'utils/storage/localStorage';
+import { getData, LS_KEYS } from '@ente/shared/storage/localStorage';
 
 export const getEndpoint = () => {
     let endpoint = getData(LS_KEYS.API_ENDPOINT);

+ 3 - 3
apps/photos/src/utils/common/key.ts

@@ -1,7 +1,7 @@
 import { B64EncryptionResult } from 'types/crypto';
-import ComlinkCryptoWorker from 'utils/comlink/ComlinkCryptoWorker';
-import { getData, LS_KEYS } from 'utils/storage/localStorage';
-import { getKey, SESSION_KEYS } from 'utils/storage/sessionStorage';
+import ComlinkCryptoWorker from '@ente/shared/crypto';
+import { getData, LS_KEYS } from '@ente/shared/storage/localStorage';
+import { getKey, SESSION_KEYS } from '@ente/shared/storage/sessionStorage';
 import { CustomError } from '../error';
 
 export const getActualKey = async () => {

+ 6 - 5
apps/photos/src/utils/crypto/index.ts

@@ -1,12 +1,13 @@
 import { KeyAttributes, SRPSetupAttributes } from 'types/user';
-import { SESSION_KEYS, setKey } from 'utils/storage/sessionStorage';
-import { getData, LS_KEYS, setData } from 'utils/storage/localStorage';
+import { SESSION_KEYS, setKey } from '@ente/shared/storage/sessionStorage';
+import { getData, LS_KEYS, setData } from '@ente/shared/storage/localStorage';
 import { getActualKey, getToken } from 'utils/common/key';
 import { setRecoveryKey } from '@ente/accounts/api/user';
 import { logError } from '@ente/shared/sentry';
 import isElectron from 'is-electron';
-import safeStorageService from 'services/electron/safeStorage';
-import ComlinkCryptoWorker from 'utils/comlink/ComlinkCryptoWorker';
+import ElectronAPIs from '@ente/shared/electron';
+
+import ComlinkCryptoWorker from '@ente/shared/crypto';
 import { PasswordStrength } from 'constants/crypto';
 import zxcvbn from 'zxcvbn';
 import { SRP, SrpClient } from 'fast-srp-hap';
@@ -125,7 +126,7 @@ export const saveKeyInSessionStore = async (
         !fromDesktop &&
         keyType === SESSION_KEYS.ENCRYPTION_KEY
     ) {
-        safeStorageService.setEncryptionKey(key);
+        ElectronAPIs.setEncryptionKey(key);
     }
 };
 

+ 8 - 7
apps/photos/src/utils/file/index.ts

@@ -13,7 +13,7 @@ import { getFileType } from 'services/typeDetectionService';
 import DownloadManager from 'services/downloadManager';
 import { logError } from '@ente/shared/sentry';
 import { User } from 'types/user';
-import { getData, LS_KEYS } from 'utils/storage/localStorage';
+import { getData, LS_KEYS } from '@ente/shared/storage/localStorage';
 import { updateFileCreationDateInEXIF } from 'services/upload/exifService';
 import {
     TYPE_JPEG,
@@ -33,7 +33,7 @@ import { isArchivedFile, updateMagicMetadata } from 'utils/magicMetadata';
 import { addLocalLog, addLogLine } from '@ente/shared/logging';
 import { CustomError } from 'utils/error';
 import { convertBytesToHumanReadable } from './size';
-import ComlinkCryptoWorker from 'utils/comlink/ComlinkCryptoWorker';
+import ComlinkCryptoWorker from '@ente/shared/crypto';
 import {
     deleteFromTrash,
     trashFiles,
@@ -41,13 +41,14 @@ import {
     updateFilePublicMagicMetadata,
 } from 'services/fileService';
 import isElectron from 'is-electron';
-import imageProcessor from 'services/electron/imageProcessor';
 import { isPlaybackPossible } from 'utils/photoFrame';
 import { FileTypeInfo } from 'types/upload';
 import { moveToHiddenCollection } from 'services/collectionService';
 
-import ElectronFSService from 'services/electron/fs';
+import ElectronFSService from '@ente/shared/electron';
 import { getFileExportPath, getUniqueFileExportName } from 'utils/export';
+import imageProcessor from 'services/imageProcessor';
+import ElectronAPIs from '@ente/shared/electron';
 
 const WAIT_TIME_IMAGE_CONVERSION = 30 * 1000;
 
@@ -712,7 +713,7 @@ export async function downloadFileDesktop(
             livePhoto.imageNameTitle
         );
         const imageStream = generateStreamFromArrayBuffer(livePhoto.image);
-        await ElectronFSService.saveMediaFile(
+        await ElectronAPIs.saveStreamToDisk(
             getFileExportPath(downloadPath, imageExportName),
             imageStream
         );
@@ -722,7 +723,7 @@ export async function downloadFileDesktop(
                 livePhoto.videoNameTitle
             );
             const videoStream = generateStreamFromArrayBuffer(livePhoto.video);
-            await ElectronFSService.saveMediaFile(
+            await ElectronAPIs.saveStreamToDisk(
                 getFileExportPath(downloadPath, videoExportName),
                 videoStream
             );
@@ -737,7 +738,7 @@ export async function downloadFileDesktop(
             downloadPath,
             file.metadata.title
         );
-        await ElectronFSService.saveMediaFile(
+        await ElectronAPIs.saveStreamToDisk(
             getFileExportPath(downloadPath, fileExportName),
             updatedFileStream
         );

+ 1 - 1
apps/photos/src/utils/machineLearning/faceCrop.ts

@@ -13,7 +13,7 @@ import {
 } from 'types/machineLearning';
 import { cropWithRotation, imageBitmapToBlob } from 'utils/image';
 import { addLogLine } from '@ente/shared/logging';
-import { getBlobFromCache } from 'utils/storage/cache';
+import { getBlobFromCache } from '@ente/shared/storage/cacheStorage/helpers';
 import { enlargeBox } from '.';
 import { Box } from '../../../thirdparty/face-api/classes';
 import { getAlignedFaceBox } from './faceAlign';

+ 1 - 1
apps/photos/src/utils/machineLearning/index.ts

@@ -24,7 +24,7 @@ import {
 // import { mlFilesStore, mlPeopleStore } from 'utils/storage/mlStorage';
 import { getRenderableImage } from 'utils/file';
 import { imageBitmapToBlob } from 'utils/image';
-import { cached } from 'utils/storage/cache';
+import { cached } from '@ente/shared/storage/cacheStorage/helpers';
 import mlIDbStorage from 'utils/storage/mlIDbStorage';
 import { Box, Point } from '../../../thirdparty/face-api/classes';
 import {

+ 1 - 1
apps/photos/src/utils/magicMetadata/index.ts

@@ -1,7 +1,7 @@
 import { Collection } from 'types/collection';
 import { EnteFile } from 'types/file';
 import { MagicMetadataCore, VISIBILITY_STATE } from 'types/magicMetadata';
-import ComlinkCryptoWorker from 'utils/comlink/ComlinkCryptoWorker';
+import ComlinkCryptoWorker from '@ente/shared/crypto';
 
 export function isArchivedFile(item: EnteFile): boolean {
     if (!item || !item.magicMetadata || !item.magicMetadata.data) {

+ 0 - 48
apps/photos/src/utils/storage/cache.ts

@@ -1,48 +0,0 @@
-import { CACHES } from 'constants/cache';
-import { CacheStorageService } from 'services/cache/cacheStorageService';
-import { logError } from '@ente/shared/sentry';
-
-export async function cached(
-    cacheName: string,
-    id: string,
-    get: () => Promise<Blob>
-): Promise<Blob> {
-    const cache = await CacheStorageService.open(cacheName);
-    const cacheResponse = await cache.match(id);
-
-    let result: Blob;
-    if (cacheResponse) {
-        result = await cacheResponse.blob();
-    } else {
-        result = await get();
-
-        try {
-            await cache.put(id, new Response(result));
-        } catch (e) {
-            // TODO: handle storage full exception.
-            console.error('Error while storing file to cache: ', id);
-        }
-    }
-
-    return result;
-}
-
-export async function getBlobFromCache(
-    cacheName: string,
-    url: string
-): Promise<Blob> {
-    const cache = await CacheStorageService.open(cacheName);
-    const response = await cache.match(url);
-
-    return response.blob();
-}
-
-export async function deleteAllCache() {
-    try {
-        await CacheStorageService.delete(CACHES.THUMBS);
-        await CacheStorageService.delete(CACHES.FACE_CROPS);
-        await CacheStorageService.delete(CACHES.FILES);
-    } catch (e) {
-        logError(e, 'deleteAllCache failed'); // log and ignore
-    }
-}

+ 0 - 40
apps/photos/src/utils/storage/index.ts

@@ -1,40 +0,0 @@
-import { Language } from '@ente/shared/i18n/locale';
-import { getData, LS_KEYS, setData } from './localStorage';
-
-export const isFirstLogin = () =>
-    getData(LS_KEYS.IS_FIRST_LOGIN)?.status ?? false;
-
-export function setIsFirstLogin(status) {
-    setData(LS_KEYS.IS_FIRST_LOGIN, { status });
-}
-
-export const justSignedUp = () =>
-    getData(LS_KEYS.JUST_SIGNED_UP)?.status ?? false;
-
-export function setJustSignedUp(status) {
-    setData(LS_KEYS.JUST_SIGNED_UP, { status });
-}
-
-export function getLivePhotoInfoShownCount() {
-    return getData(LS_KEYS.LIVE_PHOTO_INFO_SHOWN_COUNT)?.count ?? 0;
-}
-
-export function setLivePhotoInfoShownCount(count) {
-    setData(LS_KEYS.LIVE_PHOTO_INFO_SHOWN_COUNT, { count });
-}
-
-export function getUserLocale(): Language {
-    return getData(LS_KEYS.LOCALE)?.value;
-}
-
-export function getLocalMapEnabled(): boolean {
-    return getData(LS_KEYS.MAP_ENABLED)?.value ?? false;
-}
-
-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;
-}

+ 0 - 12
apps/photos/src/utils/storage/localForage.ts

@@ -1,12 +0,0 @@
-import { runningInBrowser } from 'utils/common';
-
-import localForage from 'localforage';
-
-if (runningInBrowser()) {
-    localForage.config({
-        name: 'ente-files',
-        version: 1.0,
-        storeName: 'files',
-    });
-}
-export default localForage;

+ 0 - 68
apps/photos/src/utils/storage/localStorage.ts

@@ -1,68 +0,0 @@
-import { logError } from '@ente/shared/sentry';
-
-export enum LS_KEYS {
-    USER = 'user',
-    SESSION = 'session',
-    KEY_ATTRIBUTES = 'keyAttributes',
-    ORIGINAL_KEY_ATTRIBUTES = 'originalKeyAttributes',
-    SUBSCRIPTION = 'subscription',
-    FAMILY_DATA = 'familyData',
-    PLANS = 'plans',
-    IS_FIRST_LOGIN = 'isFirstLogin',
-    JUST_SIGNED_UP = 'justSignedUp',
-    SHOW_BACK_BUTTON = 'showBackButton',
-    EXPORT = 'export',
-    AnonymizedUserID = 'anonymizedUserID',
-    THUMBNAIL_FIX_STATE = 'thumbnailFixState',
-    LIVE_PHOTO_INFO_SHOWN_COUNT = 'livePhotoInfoShownCount',
-    LOGS = 'logs',
-    USER_DETAILS = 'userDetails',
-    COLLECTION_SORT_BY = 'collectionSortBy',
-    THEME = 'theme',
-    WAIT_TIME = 'waitTime',
-    API_ENDPOINT = 'apiEndpoint',
-    LOCALE = 'locale',
-    MAP_ENABLED = 'mapEnabled',
-    SRP_SETUP_ATTRIBUTES = 'srpSetupAttributes',
-    SRP_ATTRIBUTES = 'srpAttributes',
-    OPT_OUT_OF_CRASH_REPORTS = 'optOutOfCrashReports',
-    CF_PROXY_DISABLED = 'cfProxyDisabled',
-}
-
-export const setData = (key: LS_KEYS, value: object) => {
-    if (typeof localStorage === 'undefined') {
-        return null;
-    }
-    localStorage.setItem(key, JSON.stringify(value));
-};
-
-export const removeData = (key: LS_KEYS) => {
-    if (typeof localStorage === 'undefined') {
-        return null;
-    }
-    localStorage.removeItem(key);
-};
-
-export const getData = (key: LS_KEYS) => {
-    try {
-        if (
-            typeof localStorage === 'undefined' ||
-            typeof key === 'undefined' ||
-            typeof localStorage.getItem(key) === 'undefined' ||
-            localStorage.getItem(key) === 'undefined'
-        ) {
-            return null;
-        }
-        const data = localStorage.getItem(key);
-        return data && JSON.parse(data);
-    } catch (e) {
-        logError(e, 'Failed to Parse JSON for key ' + key);
-    }
-};
-
-export const clearData = () => {
-    if (typeof localStorage === 'undefined') {
-        return null;
-    }
-    localStorage.clear();
-};

+ 1 - 1
apps/photos/src/utils/storage/mlStorage.ts

@@ -1,3 +1,4 @@
+import localForage from 'localforage';
 import { EnteFile } from 'types/file';
 import {
     Face,
@@ -5,7 +6,6 @@ import {
     MLIndex,
     MLSyncContext,
 } from 'types/machineLearning';
-import localForage from './localForage';
 
 export const mlFilesStore = localForage.createInstance({
     driver: localForage.INDEXEDDB,

+ 0 - 32
apps/photos/src/utils/storage/sessionStorage.ts

@@ -1,32 +0,0 @@
-export enum SESSION_KEYS {
-    ENCRYPTION_KEY = 'encryptionKey',
-    KEY_ENCRYPTION_KEY = 'keyEncryptionKey',
-}
-
-export const setKey = (key: SESSION_KEYS, value: object) => {
-    if (typeof sessionStorage === 'undefined') {
-        return null;
-    }
-    sessionStorage.setItem(key, JSON.stringify(value));
-};
-
-export const getKey = (key: SESSION_KEYS) => {
-    if (typeof sessionStorage === 'undefined') {
-        return null;
-    }
-    return JSON.parse(sessionStorage.getItem(key));
-};
-
-export const removeKey = (key: SESSION_KEYS) => {
-    if (typeof sessionStorage === 'undefined') {
-        return null;
-    }
-    sessionStorage.removeItem(key);
-};
-
-export const clearKeys = () => {
-    if (typeof sessionStorage === 'undefined') {
-        return null;
-    }
-    sessionStorage.clear();
-};

+ 5 - 6
apps/photos/src/utils/ui/index.tsx

@@ -3,14 +3,14 @@ import { DialogBoxAttributes } from 'types/dialogBox';
 import { downloadApp } from 'utils/common';
 import { t } from 'i18next';
 
-import ElectronUpdateService from 'services/electron/update';
-import { AppUpdateInfo } from 'types/electron';
+import ElectronAPIs from '@ente/shared/electron';
 import InfoOutlined from '@mui/icons-material/InfoRounded';
 import { Trans } from 'react-i18next';
 import { Subscription } from 'types/billing';
 import { logoutUser } from '@ente/accounts/services/user';
 import { Link } from '@mui/material';
 import { OPEN_STREET_MAP_LINK } from 'components/Sidebar/EnableMap';
+import { AppUpdateInfo } from '@ente/shared/electron/types';
 export const getDownloadAppMessage = (): DialogBoxAttributes => {
     return {
         title: t('DOWNLOAD_APP'),
@@ -58,15 +58,14 @@ export const getUpdateReadyToInstallMessage = (
     title: t('UPDATE_AVAILABLE'),
     content: t('UPDATE_INSTALLABLE_MESSAGE'),
     proceed: {
-        action: () => ElectronUpdateService.updateAndRestart(),
+        action: () => ElectronAPIs.updateAndRestart(),
         text: t('INSTALL_NOW'),
         variant: 'accent',
     },
     close: {
         text: t('INSTALL_ON_NEXT_LAUNCH'),
         variant: 'secondary',
-        action: () =>
-            ElectronUpdateService.muteUpdateNotification(updateInfo.version),
+        action: () => ElectronAPIs.muteUpdateNotification(updateInfo.version),
     },
 });
 
@@ -79,7 +78,7 @@ export const getUpdateAvailableForDownloadMessage = (
     close: {
         text: t('IGNORE_THIS_VERSION'),
         variant: 'secondary',
-        action: () => ElectronUpdateService.skipAppUpdate(updateInfo.version),
+        action: () => ElectronAPIs.skipAppUpdate(updateInfo.version),
     },
     proceed: {
         action: downloadApp,

+ 1 - 1
apps/photos/src/utils/user/family.ts

@@ -1,6 +1,6 @@
 import { FamilyData, FamilyMember, User } from 'types/user';
 import { logError } from '@ente/shared/sentry';
-import { getData, LS_KEYS } from 'utils/storage/localStorage';
+import { getData, LS_KEYS } from '@ente/shared/storage/localStorage';
 
 export function getLocalFamilyData(): FamilyData {
     return getData(LS_KEYS.FAMILY_DATA);

+ 3 - 3
apps/photos/src/utils/user/index.ts

@@ -1,7 +1,7 @@
 import isElectron from 'is-electron';
 import { UserDetails } from 'types/user';
-import { getData, LS_KEYS, setData } from 'utils/storage/localStorage';
-import ElectronService from 'services/electron/common';
+import { getData, LS_KEYS, setData } from '@ente/shared/storage/localStorage';
+import ElectronAPIs from '@ente/shared/electron';
 import { Buffer } from 'buffer';
 
 export function makeID(length) {
@@ -19,7 +19,7 @@ export function makeID(length) {
 
 export async function getSentryUserID() {
     if (isElectron()) {
-        return await ElectronService.getSentryUserID();
+        return await ElectronAPIs.getSentryUserID();
     } else {
         let anonymizeUserID = getData(LS_KEYS.AnonymizedUserID)?.id;
         if (!anonymizeUserID) {

+ 39 - 6
packages/shared/crypto/internal/crypto.worker.ts

@@ -1,7 +1,9 @@
 import * as Comlink from 'comlink';
 import { StateAddress } from 'libsodium-wrappers';
-import * as libsodium from './libsodium';
+import * as libsodium from '@ente/shared/crypto/internal/libsodium';
 
+const textDecoder = new TextDecoder();
+const textEncoder = new TextEncoder();
 export class DedicatedCryptoWorker {
     async decryptMetadata(
         encryptedMetadata: string,
@@ -13,7 +15,7 @@ export class DedicatedCryptoWorker {
             await libsodium.fromB64(header),
             key
         );
-        return JSON.parse(new TextDecoder().decode(encodedMetadata));
+        return JSON.parse(textDecoder.decode(encodedMetadata));
     }
 
     async decryptThumbnail(
@@ -24,14 +26,27 @@ export class DedicatedCryptoWorker {
         return libsodium.decryptChaChaOneShot(fileData, header, key);
     }
 
+    async decryptEmbedding(
+        encryptedEmbedding: string,
+        header: string,
+        key: string
+    ) {
+        const encodedEmbedding = await libsodium.decryptChaChaOneShot(
+            await libsodium.fromB64(encryptedEmbedding),
+            await libsodium.fromB64(header),
+            key
+        );
+        return Float32Array.from(
+            JSON.parse(textDecoder.decode(encodedEmbedding))
+        );
+    }
+
     async decryptFile(fileData: Uint8Array, header: Uint8Array, key: string) {
         return libsodium.decryptChaCha(fileData, header, key);
     }
 
     async encryptMetadata(metadata: Object, key: string) {
-        const encodedMetadata = new TextEncoder().encode(
-            JSON.stringify(metadata)
-        );
+        const encodedMetadata = textEncoder.encode(JSON.stringify(metadata));
 
         const { file: encryptedMetadata } =
             await libsodium.encryptChaChaOneShot(encodedMetadata, key);
@@ -49,6 +64,24 @@ export class DedicatedCryptoWorker {
         return libsodium.encryptChaChaOneShot(fileData, key);
     }
 
+    async encryptEmbedding(embedding: Float32Array, key: string) {
+        const encodedEmbedding = textEncoder.encode(
+            JSON.stringify(Array.from(embedding))
+        );
+        const { file: encryptEmbedding } = await libsodium.encryptChaChaOneShot(
+            encodedEmbedding,
+            key
+        );
+        const { encryptedData, ...other } = encryptEmbedding;
+        return {
+            file: {
+                encryptedData: await libsodium.toB64(encryptedData),
+                ...other,
+            },
+            key,
+        };
+    }
+
     async encryptFile(fileData: Uint8Array) {
         return libsodium.encryptChaCha(fileData);
     }
@@ -179,4 +212,4 @@ export class DedicatedCryptoWorker {
     }
 }
 
-Comlink.expose(DedicatedCryptoWorker);
+Comlink.expose(DedicatedCryptoWorker, self);

+ 3 - 3
packages/shared/crypto/internal/libsodium.ts

@@ -1,7 +1,7 @@
 import sodium, { StateAddress } from 'libsodium-wrappers';
-import { ENCRYPTION_CHUNK_SIZE } from '../constants';
-import { B64EncryptionResult } from '../types';
-import { CustomError } from '@ente/shared/error';
+import { ENCRYPTION_CHUNK_SIZE } from 'constants/crypto';
+import { B64EncryptionResult } from 'types/crypto';
+import { CustomError } from 'utils/error';
 
 export async function decryptChaChaOneShot(
     data: Uint8Array,