From 322c78511978b7eb44b9589b771e731d82d07f9f Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Sat, 5 Jul 2025 21:38:46 -0600 Subject: [PATCH 01/12] begin corrections for builds in specific environments (dev/test/prod) --- CHANGELOG.md | 5 ++++- package.json | 10 +++++----- vite.config.common.mts | 15 +++++++++++++-- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c9eb2a7..5c580d79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed +- Set the environment variables correctly (so simulator deep link domain is right). ### Changed -- Photo is pinned to profile mode +- Photo is pinned to profile mode. +- NODE_ENV is now mandatory. ## [1.0.2] - 2025.06.20 - 276e0a741bc327de3380c4e508cccb7fee58c06d diff --git a/package.json b/package.json index a2152348..033f596e 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "name": "Time Safari Team" }, "scripts": { - "dev": "vite --config vite.config.dev.mts --host", + "dev": "NODE_ENV=dev vite --config vite.config.web.mts --host", "serve": "vite preview", "build": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.mts", "lint": "eslint --ext .js,.ts,.vue --ignore-path .gitignore src", @@ -23,7 +23,7 @@ "clean:electron": "rimraf dist-electron", "build:pywebview": "vite build --config vite.config.pywebview.mts", "build:electron": "npm run clean:electron && tsc -p tsconfig.electron.json && vite build --config vite.config.electron.mts && node scripts/build-electron.js", - "build:capacitor": "vite build --mode capacitor --config vite.config.capacitor.mts", + "build:capacitor": "vite build --config vite.config.capacitor.mts", "build:web": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.web.mts", "electron:dev": "npm run build && electron .", "electron:start": "electron .", @@ -35,9 +35,9 @@ "build:electron-prod": "NODE_ENV=production npm run build:electron", "pywebview:dev": "vite build --config vite.config.pywebview.mts && .venv/bin/python src/pywebview/main.py", "pywebview:build": "vite build --config vite.config.pywebview.mts && .venv/bin/python src/pywebview/main.py", - "pywebview:package-linux": "vite build --mode pywebview --config vite.config.pywebview.mts && .venv/bin/python -m PyInstaller --name TimeSafari --add-data 'dist:www' src/pywebview/main.py", - "pywebview:package-win": "vite build --mode pywebview --config vite.config.pywebview.mts && .venv/Scripts/python -m PyInstaller --name TimeSafari --add-data 'dist;www' src/pywebview/main.py", - "pywebview:package-mac": "vite build --mode pywebview --config vite.config.pywebview.mts && .venv/bin/python -m PyInstaller --name TimeSafari --add-data 'dist:www' src/pywebview/main.py", + "pywebview:package-linux": "vite build --config vite.config.pywebview.mts && .venv/bin/python -m PyInstaller --name TimeSafari --add-data 'dist:www' src/pywebview/main.py", + "pywebview:package-win": "vite build --config vite.config.pywebview.mts && .venv/Scripts/python -m PyInstaller --name TimeSafari --add-data 'dist;www' src/pywebview/main.py", + "pywebview:package-mac": "vite build --config vite.config.pywebview.mts && .venv/bin/python -m PyInstaller --name TimeSafari --add-data 'dist:www' src/pywebview/main.py", "fastlane:ios:beta": "cd ios && fastlane beta", "fastlane:ios:release": "cd ios && fastlane release", "fastlane:android:beta": "cd android && fastlane beta", diff --git a/vite.config.common.mts b/vite.config.common.mts index 6b238be9..3ab5b12a 100644 --- a/vite.config.common.mts +++ b/vite.config.common.mts @@ -5,13 +5,24 @@ import { loadAppConfig } from "./vite.config.utils.mts"; import path from "path"; import { fileURLToPath } from 'url'; +export type BuildMode = 'web' | 'electron' | 'capacitor' | 'pywebview'; +export type BuildEnv = 'dev' | 'test' | 'prod'; + // Load environment variables -dotenv.config(); +if (process.env.NODE_ENV === 'dev' || process.env.NODE_ENV === 'test' || process.env.NODE_ENV === 'prod') { + console.log(`NODE_ENV=${process.env.NODE_ENV}`); +} else { + console.error("NODE_ENV is not set. Invoke with NODE_ENV=dev|test|prod"); + throw new Error("NODE_ENV is not set. Invoke with NODE_ENV=dev|test|prod"); + // process.exit(1); +} + +dotenv.config({ path: `.env.${process.env.NODE_ENV}` }); const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); -export async function createBuildConfig(mode: string): Promise { +export async function createBuildConfig(mode: BuildMode): Promise { const appConfig = await loadAppConfig(); const isElectron = mode === "electron"; const isCapacitor = mode === "capacitor"; -- 2.30.2 From b6c932b22c8d2e2b9c1a2e8a655a0ebaffae56da Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Sat, 5 Jul 2025 21:45:05 -0600 Subject: [PATCH 02/12] rename env names to match proposed build names --- .env.development => .env.dev | 0 .env.production => .env.prod | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename .env.development => .env.dev (100%) rename .env.production => .env.prod (100%) diff --git a/.env.development b/.env.dev similarity index 100% rename from .env.development rename to .env.dev diff --git a/.env.production b/.env.prod similarity index 100% rename from .env.production rename to .env.prod -- 2.30.2 From 43c5a281532d9c2a839da7a12b44055556c58d34 Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Sat, 5 Jul 2025 21:51:09 -0600 Subject: [PATCH 03/12] remove vite.config files that are split into platform files --- package.json | 1 - vite.config.mts | 71 ------------------------------------------------- vite.config.ts | 53 ------------------------------------ 3 files changed, 125 deletions(-) delete mode 100644 vite.config.mts delete mode 100644 vite.config.ts diff --git a/package.json b/package.json index 033f596e..60405826 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,6 @@ "scripts": { "dev": "NODE_ENV=dev vite --config vite.config.web.mts --host", "serve": "vite preview", - "build": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.mts", "lint": "eslint --ext .js,.ts,.vue --ignore-path .gitignore src", "lint-fix": "eslint --ext .js,.ts,.vue --ignore-path .gitignore --fix src", "prebuild": "eslint --ext .js,.ts,.vue --ignore-path .gitignore src && node sw_combine.js && node scripts/copy-wasm.js", diff --git a/vite.config.mts b/vite.config.mts deleted file mode 100644 index 3aa22ce0..00000000 --- a/vite.config.mts +++ /dev/null @@ -1,71 +0,0 @@ -import { defineConfig } from "vite"; -import vue from "@vitejs/plugin-vue"; -import path from "path"; -import { fileURLToPath } from 'url'; - -const __dirname = path.dirname(fileURLToPath(import.meta.url)); - -export default defineConfig({ - plugins: [vue()], - resolve: { - alias: { - '@': path.resolve(__dirname, './src'), - 'nostr-tools': path.resolve(__dirname, 'node_modules/nostr-tools'), - 'nostr-tools/nip06': path.resolve(__dirname, 'node_modules/nostr-tools/nip06'), - 'nostr-tools/core': path.resolve(__dirname, 'node_modules/nostr-tools/core'), - stream: 'stream-browserify', - util: 'util', - crypto: 'crypto-browserify', - assert: 'assert/', - http: 'stream-http', - https: 'https-browserify', - url: 'url/', - zlib: 'browserify-zlib', - path: 'path-browserify', - fs: false, - tty: 'tty-browserify', - net: false, - dns: false, - child_process: false, - os: false - }, - mainFields: ['module', 'jsnext:main', 'jsnext', 'main'], - }, - optimizeDeps: { - include: ['nostr-tools', 'nostr-tools/nip06', 'nostr-tools/core'], - esbuildOptions: { - define: { - global: 'globalThis' - } - } - }, - build: { - sourcemap: true, - target: 'esnext', - chunkSizeWarningLimit: 1000, - commonjsOptions: { - include: [/node_modules/], - transformMixedEsModules: true - }, - rollupOptions: { - external: [ - 'stream', 'util', 'crypto', 'http', 'https', 'url', 'zlib', - 'path', 'fs', 'tty', 'assert', 'net', 'dns', 'child_process', 'os' - ], - output: { - globals: { - stream: 'stream', - util: 'util', - crypto: 'crypto', - http: 'http', - https: 'https', - url: 'url', - zlib: 'zlib', - path: 'path', - assert: 'assert', - tty: 'tty' - } - } - } - } -}); \ No newline at end of file diff --git a/vite.config.ts b/vite.config.ts deleted file mode 100644 index 61a62e08..00000000 --- a/vite.config.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { defineConfig } from "vite"; -import vue from "@vitejs/plugin-vue"; -import path from "path"; - -export default defineConfig({ - plugins: [vue()], - server: { - headers: { - 'Cross-Origin-Opener-Policy': 'same-origin', - 'Cross-Origin-Embedder-Policy': 'require-corp' - } - }, - resolve: { - alias: { - '@': path.resolve(__dirname, './src'), - 'nostr-tools': path.resolve(__dirname, 'node_modules/nostr-tools'), - 'nostr-tools/nip06': path.resolve(__dirname, 'node_modules/nostr-tools/nip06'), - 'nostr-tools/core': path.resolve(__dirname, 'node_modules/nostr-tools/core'), - stream: 'stream-browserify', - util: 'util', - crypto: 'crypto-browserify' - }, - mainFields: ['module', 'jsnext:main', 'jsnext', 'main'], - }, - optimizeDeps: { - include: ['nostr-tools', 'nostr-tools/nip06', 'nostr-tools/core', '@jlongster/sql.js'], - esbuildOptions: { - define: { - global: 'globalThis' - } - } - }, - build: { - sourcemap: true, - target: 'esnext', - chunkSizeWarningLimit: 1000, - commonjsOptions: { - include: [/node_modules/], - transformMixedEsModules: true - }, - rollupOptions: { - external: ['stream', 'util', 'crypto'], - output: { - globals: { - stream: 'stream', - util: 'util', - crypto: 'crypto' - } - } - } - }, - assetsInclude: ['**/*.wasm'] -}); \ No newline at end of file -- 2.30.2 From 36469a7fd2b4abca6c288fa71c8e759fdb7e9d52 Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Sat, 5 Jul 2025 21:55:11 -0600 Subject: [PATCH 04/12] remove unused deploy-specific file (now handled by NODE_ENV) --- vite.config.dev.mts | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 vite.config.dev.mts diff --git a/vite.config.dev.mts b/vite.config.dev.mts deleted file mode 100644 index 8011f589..00000000 --- a/vite.config.dev.mts +++ /dev/null @@ -1,4 +0,0 @@ -import { defineConfig } from "vite"; -import { createBuildConfig } from "./vite.config.common.mts"; - -export default defineConfig(async () => createBuildConfig('development')); \ No newline at end of file -- 2.30.2 From 538c2a43697f85ed117c838f6aa0ea8d1fd76451 Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Sun, 6 Jul 2025 09:22:49 -0600 Subject: [PATCH 05/12] change each package.json build command to be consistent, with action first, followed by platform --- package.json | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index 60405826..8aa5fad5 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,8 @@ "name": "Time Safari Team" }, "scripts": { - "dev": "NODE_ENV=dev vite --config vite.config.web.mts --host", - "serve": "vite preview", + "start:web": "vite --config vite.config.web.mts --host", + "serve:web": "vite preview", "lint": "eslint --ext .js,.ts,.vue --ignore-path .gitignore src", "lint-fix": "eslint --ext .js,.ts,.vue --ignore-path .gitignore --fix src", "prebuild": "eslint --ext .js,.ts,.vue --ignore-path .gitignore src && node sw_combine.js && node scripts/copy-wasm.js", @@ -24,25 +24,19 @@ "build:electron": "npm run clean:electron && tsc -p tsconfig.electron.json && vite build --config vite.config.electron.mts && node scripts/build-electron.js", "build:capacitor": "vite build --config vite.config.capacitor.mts", "build:web": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.web.mts", - "electron:dev": "npm run build && electron .", - "electron:start": "electron .", + "start:electron": "electron .", "clean:android": "adb uninstall app.timesafari.app || true", "build:android": "npm run clean:android && rm -rf dist && npm run build:web && npm run build:capacitor && cd android && ./gradlew clean && ./gradlew assembleDebug && cd .. && npx cap sync android && npx capacitor-assets generate --android && npx cap open android", - "electron:build-linux": "npm run build:electron && electron-builder --linux AppImage", - "electron:build-linux-deb": "npm run build:electron && electron-builder --linux deb", - "electron:build-linux-prod": "NODE_ENV=production npm run build:electron && electron-builder --linux AppImage", + "build:electron-linux": "npm run build:electron && electron-builder --linux AppImage", + "build:electron-linux-deb": "npm run build:electron && electron-builder --linux deb", + "build:electron-linux-prod": "NODE_ENV=production npm run build:electron && electron-builder --linux AppImage", "build:electron-prod": "NODE_ENV=production npm run build:electron", - "pywebview:dev": "vite build --config vite.config.pywebview.mts && .venv/bin/python src/pywebview/main.py", - "pywebview:build": "vite build --config vite.config.pywebview.mts && .venv/bin/python src/pywebview/main.py", - "pywebview:package-linux": "vite build --config vite.config.pywebview.mts && .venv/bin/python -m PyInstaller --name TimeSafari --add-data 'dist:www' src/pywebview/main.py", - "pywebview:package-win": "vite build --config vite.config.pywebview.mts && .venv/Scripts/python -m PyInstaller --name TimeSafari --add-data 'dist;www' src/pywebview/main.py", - "pywebview:package-mac": "vite build --config vite.config.pywebview.mts && .venv/bin/python -m PyInstaller --name TimeSafari --add-data 'dist:www' src/pywebview/main.py", - "fastlane:ios:beta": "cd ios && fastlane beta", - "fastlane:ios:release": "cd ios && fastlane release", - "fastlane:android:beta": "cd android && fastlane beta", - "fastlane:android:release": "cd android && fastlane release", - "electron:build-mac": "npm run build:electron-prod && electron-builder --mac", - "electron:build-mac-universal": "npm run build:electron-prod && electron-builder --mac --universal" + "build-start:pywebview": "vite build --config vite.config.pywebview.mts && .venv/bin/python src/pywebview/main.py", + "package:pywebview-linux": "vite build --config vite.config.pywebview.mts && .venv/bin/python -m PyInstaller --name TimeSafari --add-data 'dist:www' src/pywebview/main.py", + "package:pywebview-win": "vite build --config vite.config.pywebview.mts && .venv/Scripts/python -m PyInstaller --name TimeSafari --add-data 'dist;www' src/pywebview/main.py", + "package:pywebview-mac": "vite build --config vite.config.pywebview.mts && .venv/bin/python -m PyInstaller --name TimeSafari --add-data 'dist:www' src/pywebview/main.py", + "build:electron-mac": "npm run build:electron-prod && electron-builder --mac", + "build:electron-mac-universal": "npm run build:electron-prod && electron-builder --mac --universal" }, "dependencies": { "@capacitor-community/sqlite": "6.0.2", -- 2.30.2 From cbe8c2e4277ee8e239975da10397fc8b71107191 Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Sun, 6 Jul 2025 09:24:37 -0600 Subject: [PATCH 06/12] order build commands alphabetically in package.json --- package.json | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index 8aa5fad5..d7972df1 100644 --- a/package.json +++ b/package.json @@ -6,37 +6,37 @@ "name": "Time Safari Team" }, "scripts": { - "start:web": "vite --config vite.config.web.mts --host", - "serve:web": "vite preview", - "lint": "eslint --ext .js,.ts,.vue --ignore-path .gitignore src", - "lint-fix": "eslint --ext .js,.ts,.vue --ignore-path .gitignore --fix src", - "prebuild": "eslint --ext .js,.ts,.vue --ignore-path .gitignore src && node sw_combine.js && node scripts/copy-wasm.js", - "test:all": "npm run test:prerequisites && npm run build && npm run test:web && npm run test:mobile", - "test:prerequisites": "node scripts/check-prerequisites.js", - "test:web": "npx playwright test -c playwright.config-local.ts --trace on", - "test:mobile": "npm run build:capacitor && npm run test:android && npm run test:ios", - "test:android": "node scripts/test-android.js", - "test:ios": "node scripts/test-ios.js", - "check:android-device": "adb devices | grep -w 'device' || (echo 'No Android device connected' && exit 1)", - "check:ios-device": "xcrun xctrace list devices 2>&1 | grep -w 'Booted' || (echo 'No iOS simulator running' && exit 1)", - "clean:electron": "rimraf dist-electron", - "build:pywebview": "vite build --config vite.config.pywebview.mts", - "build:electron": "npm run clean:electron && tsc -p tsconfig.electron.json && vite build --config vite.config.electron.mts && node scripts/build-electron.js", - "build:capacitor": "vite build --config vite.config.capacitor.mts", - "build:web": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.web.mts", - "start:electron": "electron .", - "clean:android": "adb uninstall app.timesafari.app || true", + "build-start:pywebview": "vite build --config vite.config.pywebview.mts && .venv/bin/python src/pywebview/main.py", "build:android": "npm run clean:android && rm -rf dist && npm run build:web && npm run build:capacitor && cd android && ./gradlew clean && ./gradlew assembleDebug && cd .. && npx cap sync android && npx capacitor-assets generate --android && npx cap open android", + "build:capacitor": "vite build --config vite.config.capacitor.mts", + "build:electron": "npm run clean:electron && tsc -p tsconfig.electron.json && vite build --config vite.config.electron.mts && node scripts/build-electron.js", "build:electron-linux": "npm run build:electron && electron-builder --linux AppImage", "build:electron-linux-deb": "npm run build:electron && electron-builder --linux deb", "build:electron-linux-prod": "NODE_ENV=production npm run build:electron && electron-builder --linux AppImage", + "build:electron-mac": "npm run build:electron-prod && electron-builder --mac", + "build:electron-mac-universal": "npm run build:electron-prod && electron-builder --mac --universal", "build:electron-prod": "NODE_ENV=production npm run build:electron", - "build-start:pywebview": "vite build --config vite.config.pywebview.mts && .venv/bin/python src/pywebview/main.py", + "build:pywebview": "vite build --config vite.config.pywebview.mts", + "build:web": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.web.mts", + "check:android-device": "adb devices | grep -w 'device' || (echo 'No Android device connected' && exit 1)", + "check:ios-device": "xcrun xctrace list devices 2>&1 | grep -w 'Booted' || (echo 'No iOS simulator running' && exit 1)", + "clean:android": "adb uninstall app.timesafari.app || true", + "clean:electron": "rimraf dist-electron", + "lint": "eslint --ext .js,.ts,.vue --ignore-path .gitignore src", + "lint-fix": "eslint --ext .js,.ts,.vue --ignore-path .gitignore --fix src", "package:pywebview-linux": "vite build --config vite.config.pywebview.mts && .venv/bin/python -m PyInstaller --name TimeSafari --add-data 'dist:www' src/pywebview/main.py", - "package:pywebview-win": "vite build --config vite.config.pywebview.mts && .venv/Scripts/python -m PyInstaller --name TimeSafari --add-data 'dist;www' src/pywebview/main.py", "package:pywebview-mac": "vite build --config vite.config.pywebview.mts && .venv/bin/python -m PyInstaller --name TimeSafari --add-data 'dist:www' src/pywebview/main.py", - "build:electron-mac": "npm run build:electron-prod && electron-builder --mac", - "build:electron-mac-universal": "npm run build:electron-prod && electron-builder --mac --universal" + "package:pywebview-win": "vite build --config vite.config.pywebview.mts && .venv/Scripts/python -m PyInstaller --name TimeSafari --add-data 'dist;www' src/pywebview/main.py", + "prebuild": "eslint --ext .js,.ts,.vue --ignore-path .gitignore src && node sw_combine.js && node scripts/copy-wasm.js", + "serve:web": "vite preview", + "start:electron": "electron .", + "start:web": "vite --config vite.config.web.mts --host", + "test:all": "npm run test:prerequisites && npm run build && npm run test:web && npm run test:mobile", + "test:android": "node scripts/test-android.js", + "test:ios": "node scripts/test-ios.js", + "test:mobile": "npm run build:capacitor && npm run test:android && npm run test:ios", + "test:prerequisites": "node scripts/check-prerequisites.js", + "test:web": "npx playwright test -c playwright.config-local.ts --trace on" }, "dependencies": { "@capacitor-community/sqlite": "6.0.2", -- 2.30.2 From 65877627c71d87b271183a977fcb97f3ab2ad1eb Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Sun, 6 Jul 2025 09:28:42 -0600 Subject: [PATCH 07/12] refactor documentation --- .gitignore | 7 ++----- README.md | 36 +++------------------------------ BUILDING.md => doc/BUILDING.md | 20 +++++++++--------- doc/database-migration-guide.md | 26 ++++++++++++++++++++++++ 4 files changed, 40 insertions(+), 49 deletions(-) rename BUILDING.md => doc/BUILDING.md (99%) diff --git a/.gitignore b/.gitignore index b92c212a..5294961a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ signature.bin # generated during `npm run build` sw_scripts-combined.js *.pem +tsconfig.node.tsbuildinfo verified.txt myenv @@ -40,19 +41,15 @@ pnpm-debug.log* playwright-tests dist-electron-packages .ruby-version -+.env # Test files generated by scripts test-ios.js & test-android.js .generated/ -.env.default vendor/ -# Build logs build_logs/ # PWA icon files generated by capacitor-assets icons - -android/app/src/main/res/ \ No newline at end of file +android/app/src/main/res/ diff --git a/README.md b/README.md index d673c279..711f8818 100644 --- a/README.md +++ b/README.md @@ -3,49 +3,22 @@ [Time Safari](https://timesafari.org/) allows people to ease into collaboration: start with expressions of gratitude and expand to crowd-fund with time & money, then record and see the impact of contributions. -## Database Migration Status - -**Current Status**: The application is undergoing a migration from Dexie (IndexedDB) to SQLite using absurd-sql. This migration is in **Phase 2** with a well-defined migration fence in place. - -### Migration Progress -- ✅ **SQLite Database Service**: Fully implemented with absurd-sql -- ✅ **Platform Service Layer**: Unified database interface across platforms -- ✅ **Settings Migration**: Core user settings transferred -- ✅ **Account Migration**: Identity and key management -- 🔄 **Contact Migration**: User contact data (via import interface) -- 📋 **Code Cleanup**: Remove unused Dexie imports - -### Migration Fence -The migration is controlled by a **migration fence** that separates legacy Dexie code from the new SQLite implementation. See [Migration Fence Definition](doc/migration-fence-definition.md) for complete details. - -**Key Points**: -- Legacy Dexie database is disabled by default (`USE_DEXIE_DB = false`) -- All database operations go through `PlatformService` -- Migration tools provide controlled access to both databases -- Clear separation between legacy and new code - -### Migration Documentation -- [Migration Guide](doc/migration-to-wa-sqlite.md) - Complete migration process -- [Migration Fence Definition](doc/migration-fence-definition.md) - Fence boundaries and rules -- [Database Migration Guide](doc/database-migration-guide.md) - User-facing migration tools - ## Roadmap -See [project.task.yaml](project.task.yaml) for current priorities. -(Numbers at the beginning of lines are estimated hours. See [taskyaml.org](https://taskyaml.org/) for details.) +See [ClickUp](https://sharing.clickup.com/9014278710/l/h/8cmnyhp-174/10573fec74e2ba0) for current priorities. ## Setup & Building Quick start: -* For setup, we recommend [pkgx](https://pkgx.dev), which installs what you need (either automatically or with the `dev` command). Core dependencies are typescript & npm; when building for other platforms, you'll need other things such as those in the pkgx.yaml & BUILDING.md files. +* For setup, we recommend [pkgx](https://pkgx.dev), which installs what you need (either automatically or with the `dev` command). Core dependencies are typescript & npm; when building for other platforms, you'll need other things such as those in the pkgx.yaml & doc/BUILDING.md files. ```bash npm install npm run dev ``` -See [BUILDING.md](BUILDING.md) for more details. +See [BUILDING.md](doc/BUILDING.md) for more details. ## Tests @@ -97,9 +70,6 @@ The application uses a platform-agnostic database layer: **Development Guidelines**: - Always use `PlatformService` for database operations -- Never import Dexie directly in application code -- Test with `USE_DEXIE_DB = false` for new features -- Use migration tools for data transfer between systems ### Kudos diff --git a/BUILDING.md b/doc/BUILDING.md similarity index 99% rename from BUILDING.md rename to doc/BUILDING.md index 04531f01..393a6f20 100644 --- a/BUILDING.md +++ b/doc/BUILDING.md @@ -11,17 +11,6 @@ For a quick dev environment setup, use [pkgx](https://pkgx.dev). - Git - For desktop builds: Additional build tools based on your OS -## Forks - -If you have forked this to make your own app, you'll want to customize the iOS & Android files. You can either edit existing ones, or you can remove the `ios` and `android` directories and regenerate them before the `npx cap sync` step in each setup. - - ```bash - npx cap add android - npx cap add ios - ``` - -You'll also want to edit the deep link configuration (see below). - ## Initial Setup Install dependencies: @@ -479,3 +468,12 @@ You must add the following intent filter to the `android/app/src/main/AndroidMan ``` ... though when we tried that most recently it failed to 'build' the APK with: http(s) scheme and host attribute are missing, but are required for Android App Links [AppLinkUrlError] + +## Forks + +If you have forked this to make your own app, you'll want to customize the iOS & Android files. You can either edit existing ones, or you can remove the `ios` and `android` directories and regenerate them before the `npx cap sync` step in each setup. + + ```bash + npx cap add android + npx cap add ios + ``` diff --git a/doc/database-migration-guide.md b/doc/database-migration-guide.md index fe17287e..179e1fda 100644 --- a/doc/database-migration-guide.md +++ b/doc/database-migration-guide.md @@ -27,6 +27,32 @@ The Database Migration feature allows you to compare and migrate data between De - Clear success and error messaging - Export functionality for comparison data +## Database Migration Status + +**Current Status**: The application is undergoing a migration from Dexie (IndexedDB) to SQLite using absurd-sql. This migration is in **Phase 2** with a well-defined migration fence in place. + +### Migration Progress +- ✅ **SQLite Database Service**: Fully implemented with absurd-sql +- ✅ **Platform Service Layer**: Unified database interface across platforms +- ✅ **Settings Migration**: Core user settings transferred +- ✅ **Account Migration**: Identity and key management +- 🔄 **Contact Migration**: User contact data (via import interface) +- 📋 **Code Cleanup**: Remove unused Dexie imports + +### Migration Fence +The migration is controlled by a **migration fence** that separates legacy Dexie code from the new SQLite implementation. See [Migration Fence Definition](doc/migration-fence-definition.md) for complete details. + +**Key Points**: +- Legacy Dexie database is disabled by default (`USE_DEXIE_DB = false`) +- All database operations go through `PlatformService` +- Migration tools provide controlled access to both databases +- Clear separation between legacy and new code + +### Migration Documentation +- [Migration Guide](doc/migration-to-wa-sqlite.md) - Complete migration process +- [Migration Fence Definition](doc/migration-fence-definition.md) - Fence boundaries and rules +- [Database Migration Guide](doc/database-migration-guide.md) - User-facing migration tools + ## Prerequisites ### Enable Dexie Database -- 2.30.2 From 5905ae871a235b68e0e2a6cab63958a10002d863 Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Sun, 6 Jul 2025 13:13:35 -0600 Subject: [PATCH 08/12] Refactor build files, separating & consolidating & renaming as needed. --- .env.staging => .env.test | 4 +- README.md | 2 +- doc/BUILDING.md | 28 ++--- TASK_storage.md => doc/TASK_storage.md | 0 playwright.config-local.ts | 4 +- playwright.config.ts | 2 +- src/components/DataExportSection.vue | 4 +- src/vite.config.utils.js | 55 --------- ....utils.mts => vite.config.common-utils.mts | 108 +++++++++--------- vite.config.common.mts | 16 +-- vite.config.web.mts | 6 +- 11 files changed, 89 insertions(+), 140 deletions(-) rename .env.staging => .env.test (78%) rename TASK_storage.md => doc/TASK_storage.md (100%) delete mode 100644 src/vite.config.utils.js rename vite.config.utils.mts => vite.config.common-utils.mts (52%) diff --git a/.env.staging b/.env.test similarity index 78% rename from .env.staging rename to .env.test index a01c323c..e69bc581 100644 --- a/.env.staging +++ b/.env.test @@ -1,9 +1,9 @@ # Only the variables that start with VITE_ are seen in the application import.meta.env in Vue. -# iOS doesn't like spaces in the app title. + TIME_SAFARI_APP_TITLE="TimeSafari_Test" VITE_APP_SERVER=https://test.timesafari.app -# This is the claim ID for actions in the BVC project, with the JWT ID on this environment (not production). +# This is the claim ID for actions in the BVC project. VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZYYPS272F VITE_DEFAULT_ENDORSER_API_SERVER=https://test-api.endorser.ch diff --git a/README.md b/README.md index 711f8818..ff2fa563 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Quick start: ```bash npm install -npm run dev +NODE_ENV=dev npm run start:web ``` See [BUILDING.md](doc/BUILDING.md) for more details. diff --git a/doc/BUILDING.md b/doc/BUILDING.md index 393a6f20..b8a166c2 100644 --- a/doc/BUILDING.md +++ b/doc/BUILDING.md @@ -22,7 +22,7 @@ Install dependencies: ## Web Dev Locally ```bash - npm run dev + NODE_ENV=dev npm run start:web ``` ## Web Build for Server @@ -31,7 +31,7 @@ Install dependencies: ```bash rm -rf dist - npm run build:web + NODE_ENV=prod npm run build:web ``` The built files will be in the `dist` directory. @@ -41,7 +41,7 @@ Install dependencies: You'll likely want to use test locations for the Endorser & image & partner servers; see "DEFAULT_ENDORSER_API_SERVER" & "DEFAULT_IMAGE_API_SERVER" & "DEFAULT_PARTNER_API_SERVER" below. ```bash - npm run serve + NODE_ENV=dev npm run serve:web ``` ### Compile and minify for test & production @@ -52,7 +52,7 @@ Install dependencies: * Update the ClickUp tasks & CHANGELOG.md & the version in package.json, run `npm install`. -* Run a build to make sure package-lock version is updated, linting works, etc: `npm install && npm run build` +* Run a build to make sure package-lock version is updated, linting works, etc: `npm install && npm run build:web` * Commit everything (since the commit hash is used the app). @@ -63,7 +63,7 @@ Install dependencies: * For test, build the app (because test server is not yet set up to build): ```bash -TIME_SAFARI_APP_TITLE="TimeSafari_Test" VITE_APP_SERVER=https://test.timesafari.app VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZYYPS272F VITE_DEFAULT_ENDORSER_API_SERVER=https://test-api.endorser.ch VITE_DEFAULT_IMAGE_API_SERVER=https://test-image-api.timesafari.app VITE_DEFAULT_PARTNER_API_SERVER=https://test-partner-api.endorser.ch VITE_DEFAULT_PUSH_SERVER=https://test.timesafari.app VITE_PASSKEYS_ENABLED=true npm run build:web +NODE_ENV=test TIME_SAFARI_APP_TITLE="TimeSafari_Test" VITE_APP_SERVER=https://test.timesafari.app VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZYYPS272F VITE_DEFAULT_ENDORSER_API_SERVER=https://test-api.endorser.ch VITE_DEFAULT_IMAGE_API_SERVER=https://test-image-api.timesafari.app VITE_DEFAULT_PARTNER_API_SERVER=https://test-partner-api.endorser.ch VITE_DEFAULT_PUSH_SERVER=https://test.timesafari.app VITE_PASSKEYS_ENABLED=true npm run build:web ``` ... and transfer to the test server: @@ -205,10 +205,10 @@ docker run -d \ ```bash # For AppImage (recommended) - npm run electron:build-linux + npm run build:electron-linux # For .deb package - npm run electron:build-linux-deb + npm run build:electron-linux-deb ``` 3. The packaged applications will be in `dist-electron-packages/`: @@ -220,19 +220,19 @@ docker run -d \ 1. Build the electron app in production mode: ```bash - npm run build:web + NODE_ENV=prod npm run build:web npm run build:electron - npm run electron:build-mac + npm run build:electron-mac ``` 2. Package the Electron app for macOS: ```bash # For Intel Macs - npm run electron:build-mac + npm run build:electron-mac # For Universal build (Intel + Apple Silicon) - npm run electron:build-mac-universal + npm run build:electron-mac-universal ``` 3. The packaged applications will be in `dist-electron-packages/`: @@ -254,7 +254,7 @@ For public distribution on macOS, you need to code sign and notarize your app: 2. Build with signing: ```bash - npm run electron:build-mac + npm run build:electron-mac ``` ### Running the Packaged App @@ -293,10 +293,10 @@ For testing the Electron build before packaging: ```bash # Build and run in development mode (includes DevTools) -npm run electron:dev +npm run build:electron # Build in production mode and test -npm run build:electron-prod && npm run electron:start +npm run build:electron-prod && npm run start:electron ``` ## Mobile Builds (Capacitor) diff --git a/TASK_storage.md b/doc/TASK_storage.md similarity index 100% rename from TASK_storage.md rename to doc/TASK_storage.md diff --git a/playwright.config-local.ts b/playwright.config-local.ts index 29f4cf64..16f466a9 100644 --- a/playwright.config-local.ts +++ b/playwright.config-local.ts @@ -101,7 +101,7 @@ export default defineConfig({ /** * This could be an array of servers, meaning we could start the Endorser server as well: * { - * command: "cd ../endorser-ch; NODE_ENV=test-local npm run dev", + * command: "cd ../endorser-ch; NODE_ENV=test-local npm run start:web", * url: 'http://localhost:3000', * reuseExistingServer: !process.env.CI, * }, @@ -112,7 +112,7 @@ export default defineConfig({ */ webServer: { command: - "VITE_APP_SERVER=http://localhost:8081 VITE_DEFAULT_ENDORSER_API_SERVER=http://localhost:3000 VITE_DEFAULT_PARTNER_API_SERVER=http://localhost:3000 VITE_DEFAULT_IMAGE_API_SERVER=https://test-image-api.timesafari.app VITE_PASSKEYS_ENABLED=true npm run dev -- --port=8081", + "VITE_APP_SERVER=http://localhost:8081 VITE_DEFAULT_ENDORSER_API_SERVER=http://localhost:3000 VITE_DEFAULT_PARTNER_API_SERVER=http://localhost:3000 VITE_DEFAULT_IMAGE_API_SERVER=https://test-image-api.timesafari.app VITE_PASSKEYS_ENABLED=true npm run start:web -- --port=8081", url: "http://localhost:8081", reuseExistingServer: !process.env.CI, }, diff --git a/playwright.config.ts b/playwright.config.ts index 5fdf7351..0fe5feb4 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -74,7 +74,7 @@ export default defineConfig({ /* Run your local dev server before starting the tests */ // webServer: { // command: - // "VITE_PASSKEYS_ENABLED=true VITE_DEFAULT_ENDORSER_API_SERVER=http://localhost:3000 npm run dev", + // "VITE_PASSKEYS_ENABLED=true VITE_DEFAULT_ENDORSER_API_SERVER=http://localhost:3000 npm run start:web", // url: "http://localhost:8080", // reuseExistingServer: !process.env.CI, // }, diff --git a/src/components/DataExportSection.vue b/src/components/DataExportSection.vue index 842b2201..19e6014a 100644 --- a/src/components/DataExportSection.vue +++ b/src/components/DataExportSection.vue @@ -50,8 +50,8 @@ backup and database export, with platform-specific download instructions. * * v-if="platformCapabilities.isMobile && !platformCapabilities.isIOS" class="list-disc list-outside ml-4" > - On Android: You will be prompted to choose a location to save your - backup file. + On Android: You will be prompted to choose an app for sharing your + backup file. To save on your phone, you will need a file manager app. diff --git a/src/vite.config.utils.js b/src/vite.config.utils.js deleted file mode 100644 index 719edfc7..00000000 --- a/src/vite.config.utils.js +++ /dev/null @@ -1,55 +0,0 @@ -import * as path from "path"; -import { promises as fs } from "fs"; -import { fileURLToPath } from "url"; - -export async function loadAppConfig() { - const packageJson = await loadPackageJson(); - const appName = process.env.TIME_SAFARI_APP_TITLE || packageJson.name; - const __dirname = path.dirname(fileURLToPath(import.meta.url)); - - return { - pwaConfig: { - manifest: { - name: appName, - short_name: appName, - icons: [ - { - src: "./img/icons/android-chrome-192x192.png", - sizes: "192x192", - type: "image/png", - }, - { - src: "./img/icons/android-chrome-512x512.png", - sizes: "512x512", - type: "image/png", - }, - { - src: "./img/icons/android-chrome-maskable-192x192.png", - sizes: "192x192", - type: "image/png", - purpose: "maskable", - }, - { - src: "./img/icons/android-chrome-maskable-512x512.png", - sizes: "512x512", - type: "image/png", - purpose: "maskable", - }, - ], - }, - }, - aliasConfig: { - "@": path.resolve(path.dirname(__dirname), "src"), - buffer: path.resolve(path.dirname(__dirname), "node_modules", "buffer"), - "dexie-export-import/dist/import": - "dexie-export-import/dist/import/index.js", - }, - }; -} - -async function loadPackageJson() { - const __dirname = path.dirname(fileURLToPath(import.meta.url)); - const packageJsonPath = path.resolve(path.dirname(__dirname), "package.json"); - const packageJsonData = await fs.readFile(packageJsonPath, "utf-8"); - return JSON.parse(packageJsonData); -} diff --git a/vite.config.utils.mts b/vite.config.common-utils.mts similarity index 52% rename from vite.config.utils.mts rename to vite.config.common-utils.mts index b5a1ed97..ef95f8be 100644 --- a/vite.config.utils.mts +++ b/vite.config.common-utils.mts @@ -45,71 +45,73 @@ interface PWAConfig { } interface AppConfig { - pwaConfig: PWAConfig; aliasConfig: { [key: string]: string; }; } export async function loadAppConfig(): Promise { - const packageJson = await loadPackageJson(); - const appName = process.env.TIME_SAFARI_APP_TITLE || packageJson.name; - return { - pwaConfig: { - registerType: "autoUpdate", - strategies: "injectManifest", - srcDir: ".", - filename: "sw_scripts-combined.js", - manifest: { - name: appName, - short_name: appName, - theme_color: "#4a90e2", - background_color: "#ffffff", - icons: [ - { - src: "./img/icons/android-chrome-192x192.png", - sizes: "192x192", - type: "image/png", - }, - { - src: "./img/icons/android-chrome-512x512.png", - sizes: "512x512", - type: "image/png", - }, - { - src: "./img/icons/android-chrome-maskable-192x192.png", - sizes: "192x192", - type: "image/png", - purpose: "maskable", - }, - { - src: "./img/icons/android-chrome-maskable-512x512.png", - sizes: "512x512", - type: "image/png", - purpose: "maskable", - }, - ], - share_target: { - action: "/share-target", - method: "POST", - enctype: "multipart/form-data", - params: { - files: [ - { - name: "photo", - accept: ["image/*"], - }, - ], - }, - }, - }, - }, aliasConfig: { "@": path.resolve(__dirname, "src"), buffer: path.resolve(__dirname, "node_modules", "buffer"), "dexie-export-import/dist/import": "dexie-export-import/dist/import/index.js", }, + } +} + +export async function loadPwaConfig(): Promise { + const packageJson = await loadPackageJson(); + const appName = process.env.TIME_SAFARI_APP_TITLE || packageJson.name; + + return { + registerType: "autoUpdate", + strategies: "injectManifest", + srcDir: ".", + filename: "sw_scripts-combined.js", + manifest: { + name: appName, + short_name: appName, + theme_color: "#4a90e2", + background_color: "#ffffff", + icons: [ + { + src: "./img/icons/android-chrome-192x192.png", + sizes: "192x192", + type: "image/png", + }, + { + src: "./img/icons/android-chrome-512x512.png", + sizes: "512x512", + type: "image/png", + }, + { + src: "./img/icons/android-chrome-maskable-192x192.png", + sizes: "192x192", + type: "image/png", + purpose: "maskable", + }, + { + src: "./img/icons/android-chrome-maskable-512x512.png", + sizes: "512x512", + type: "image/png", + purpose: "maskable", + }, + ], + share_target: { + action: "/share-target", + method: "POST", + enctype: "multipart/form-data", + params: { + files: [ + { + name: "photo", + accept: ["image/*"], + }, + ], + }, + }, + }, }; } \ No newline at end of file diff --git a/vite.config.common.mts b/vite.config.common.mts index 3ab5b12a..e87b3ba7 100644 --- a/vite.config.common.mts +++ b/vite.config.common.mts @@ -1,7 +1,7 @@ import { defineConfig, UserConfig, Plugin } from "vite"; import vue from "@vitejs/plugin-vue"; import dotenv from "dotenv"; -import { loadAppConfig } from "./vite.config.utils.mts"; +import { loadAppConfig } from "./vite.config.common-utils.mts"; import path from "path"; import { fileURLToPath } from 'url'; @@ -9,7 +9,11 @@ export type BuildMode = 'web' | 'electron' | 'capacitor' | 'pywebview'; export type BuildEnv = 'dev' | 'test' | 'prod'; // Load environment variables -if (process.env.NODE_ENV === 'dev' || process.env.NODE_ENV === 'test' || process.env.NODE_ENV === 'prod') { +if ( + process.env.NODE_ENV === 'dev' + || process.env.NODE_ENV === 'test' + || process.env.NODE_ENV === 'prod' + ) { console.log(`NODE_ENV=${process.env.NODE_ENV}`); } else { console.error("NODE_ENV is not set. Invoke with NODE_ENV=dev|test|prod"); @@ -30,13 +34,11 @@ export async function createBuildConfig(mode: BuildMode): Promise { // Explicitly set platform and disable PWA for Electron process.env.VITE_PLATFORM = mode; - process.env.VITE_PWA_ENABLED = isElectron ? 'false' : 'true'; + process.env.VITE_PWA_ENABLED = (isElectron || isPyWebView || isCapacitor) + ? 'false' + : 'true'; process.env.VITE_DISABLE_PWA = isElectron ? 'true' : 'false'; - if (isElectron || isPyWebView || isCapacitor) { - process.env.VITE_PWA_ENABLED = 'false'; - } - return { base: isElectron || isPyWebView ? "./" : "/", plugins: [vue()], diff --git a/vite.config.web.mts b/vite.config.web.mts index 0ea84351..a2f987f2 100644 --- a/vite.config.web.mts +++ b/vite.config.web.mts @@ -1,17 +1,17 @@ import { defineConfig, mergeConfig } from "vite"; import { VitePWA } from "vite-plugin-pwa"; import { createBuildConfig } from "./vite.config.common.mts"; -import { loadAppConfig } from "./vite.config.utils.mts"; +import { loadPwaConfig } from "./vite.config.common-utils.mts"; export default defineConfig(async () => { const baseConfig = await createBuildConfig('web'); - const appConfig = await loadAppConfig(); + const pwaConfig = await loadPwaConfig(); return mergeConfig(baseConfig, { plugins: [ VitePWA({ registerType: 'autoUpdate', - manifest: appConfig.pwaConfig?.manifest, + manifest: pwaConfig.manifest, devOptions: { enabled: false }, -- 2.30.2 From 2bd191e25546a87dfcd8c96f8d29ef591e7ba806 Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Sun, 6 Jul 2025 14:41:20 -0600 Subject: [PATCH 09/12] Move remaining strings for Environment & Platform to type-checked values. --- .env.dev => .env.development | 0 .env.prod => .env.production | 0 .env.test => .env.testing | 0 index.html | 12 ++++--- package.json | 4 +-- src/electron/preload.js | 13 +++---- src/interfaces/build.ts | 21 ++++++++++++ src/main.web.ts | 6 ++-- src/registerServiceWorker.ts | 5 +-- src/services/PlatformServiceFactory.ts | 11 +++--- src/services/api.ts | 3 +- src/utils/logger.ts | 13 +++---- src/views/DeepLinkRedirectView.vue | 3 +- tsconfig.node.json | 2 +- vite.config.capacitor.mts | 3 +- vite.config.common.mts | 47 +++++++++++++------------- vite.config.electron.mts | 3 +- vite.config.pywebview.mts | 3 +- vite.config.web.mts | 3 +- 19 files changed, 95 insertions(+), 57 deletions(-) rename .env.dev => .env.development (100%) rename .env.prod => .env.production (100%) rename .env.test => .env.testing (100%) create mode 100644 src/interfaces/build.ts diff --git a/.env.dev b/.env.development similarity index 100% rename from .env.dev rename to .env.development diff --git a/.env.prod b/.env.production similarity index 100% rename from .env.prod rename to .env.production diff --git a/.env.test b/.env.testing similarity index 100% rename from .env.test rename to .env.testing diff --git a/index.html b/index.html index ea64cda3..5a583580 100644 --- a/index.html +++ b/index.html @@ -15,17 +15,21 @@ diff --git a/package.json b/package.json index d7972df1..9f7ec9ce 100644 --- a/package.json +++ b/package.json @@ -12,10 +12,10 @@ "build:electron": "npm run clean:electron && tsc -p tsconfig.electron.json && vite build --config vite.config.electron.mts && node scripts/build-electron.js", "build:electron-linux": "npm run build:electron && electron-builder --linux AppImage", "build:electron-linux-deb": "npm run build:electron && electron-builder --linux deb", - "build:electron-linux-prod": "NODE_ENV=production npm run build:electron && electron-builder --linux AppImage", + "build:electron-linux-prod": "NODE_ENV=prod npm run build:electron && electron-builder --linux AppImage", "build:electron-mac": "npm run build:electron-prod && electron-builder --mac", "build:electron-mac-universal": "npm run build:electron-prod && electron-builder --mac --universal", - "build:electron-prod": "NODE_ENV=production npm run build:electron", + "build:electron-prod": "NODE_ENV=prod npm run build:electron", "build:pywebview": "vite build --config vite.config.pywebview.mts", "build:web": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.web.mts", "check:android-device": "adb devices | grep -w 'device' || (echo 'No Android device connected' && exit 1)", diff --git a/src/electron/preload.js b/src/electron/preload.js index 2b37f099..efe49fb1 100644 --- a/src/electron/preload.js +++ b/src/electron/preload.js @@ -1,9 +1,10 @@ const { contextBridge, ipcRenderer } = require("electron"); +import { NodeEnv, BuildPlatform } from "@/interfaces/build"; const logger = { log: (message, ...args) => { // Always log in development, log with context in production - if (process.env.NODE_ENV !== "production") { + if (process.env.NODE_ENV !== NodeEnv.Prod) { /* eslint-disable no-console */ console.log(`[Preload] ${message}`, ...args); /* eslint-enable no-console */ @@ -23,7 +24,7 @@ const logger = { }, info: (message, ...args) => { // Always log info in development, log with context in production - if (process.env.NODE_ENV !== "production") { + if (process.env.NODE_ENV !== NodeEnv.Prod) { /* eslint-disable no-console */ console.info(`[Preload] ${message}`, ...args); /* eslint-enable no-console */ @@ -53,7 +54,7 @@ const getPath = (pathType) => { logger.info("Preload script starting..."); // Force electron platform in the renderer process -window.process = { env: { VITE_PLATFORM: "electron" } }; +window.process = { env: { VITE_PLATFORM: BuildPlatform.Electron } }; try { contextBridge.exposeInMainWorld("electronAPI", { @@ -76,12 +77,12 @@ try { // Environment info env: { isElectron: true, - isDev: process.env.NODE_ENV === "development", - platform: "electron", // Explicitly set platform + isDev: process.env.NODE_ENV === NodeEnv.Dev, + platform: BuildPlatform.Electron, // Explicitly set platform }, // Path utilities getBasePath: () => { - return process.env.NODE_ENV === "development" ? "/" : "./"; + return process.env.NODE_ENV === NodeEnv.Dev ? "/" : "./"; }, }); diff --git a/src/interfaces/build.ts b/src/interfaces/build.ts new file mode 100644 index 00000000..133356f1 --- /dev/null +++ b/src/interfaces/build.ts @@ -0,0 +1,21 @@ +export const NodeEnv = { + Dev: "dev", + Test: "test", + Prod: "prod", +} as const; +export type NodeEnv = typeof NodeEnv[keyof typeof NodeEnv]; + +export const BuildEnv = { + Development: "development", + Testing: "testing", + Production: "production", +} as const; +export type BuildEnv = typeof BuildEnv[keyof typeof BuildEnv]; + +export const BuildPlatform = { + Web: "web", + Electron: "electron", + Capacitor: "capacitor", + PyWebView: "pywebview", +} as const; +export type BuildPlatform = typeof BuildPlatform[keyof typeof BuildPlatform]; diff --git a/src/main.web.ts b/src/main.web.ts index ff149056..60435763 100644 --- a/src/main.web.ts +++ b/src/main.web.ts @@ -1,12 +1,14 @@ import { initBackend } from "absurd-sql/dist/indexeddb-main-thread"; + import { initializeApp } from "./main.common"; import { logger } from "./utils/logger"; +import { BuildPlatform } from "@/interfaces/build"; const platform = process.env.VITE_PLATFORM; const pwa_enabled = process.env.VITE_PWA_ENABLED === "true"; // Only import service worker for web builds -if (platform !== "electron" && pwa_enabled) { +if (platform !== BuildPlatform.Electron && pwa_enabled) { import("./registerServiceWorker"); // Web PWA support } @@ -25,7 +27,7 @@ function sqlInit() { // workers through the main thread initBackend(worker); } -if (platform === "web" || platform === "development") { +if (platform === BuildPlatform.Web) { sqlInit(); } else { logger.warn("[Web] SQL not initialized for platform", { platform }); diff --git a/src/registerServiceWorker.ts b/src/registerServiceWorker.ts index e1f328b8..57153122 100644 --- a/src/registerServiceWorker.ts +++ b/src/registerServiceWorker.ts @@ -1,10 +1,11 @@ /* eslint-disable no-console */ import { register } from "register-service-worker"; +import { NodeEnv, BuildPlatform } from "@/interfaces/build"; // Check if we're in an Electron environment const isElectron = - process.env.VITE_PLATFORM === "electron" || + process.env.VITE_PLATFORM === BuildPlatform.Electron || process.env.VITE_DISABLE_PWA === "true" || window.navigator.userAgent.toLowerCase().includes("electron"); @@ -15,7 +16,7 @@ const isElectron = if ( !isElectron && process.env.VITE_PWA_ENABLED === "true" && - process.env.NODE_ENV === "production" + process.env.NODE_ENV === NodeEnv.Prod ) { register(`${process.env.BASE_URL}sw.js`, { ready() { diff --git a/src/services/PlatformServiceFactory.ts b/src/services/PlatformServiceFactory.ts index f5e34fa2..cef4324a 100644 --- a/src/services/PlatformServiceFactory.ts +++ b/src/services/PlatformServiceFactory.ts @@ -3,6 +3,7 @@ import { WebPlatformService } from "./platforms/WebPlatformService"; import { CapacitorPlatformService } from "./platforms/CapacitorPlatformService"; import { ElectronPlatformService } from "./platforms/ElectronPlatformService"; import { PyWebViewPlatformService } from "./platforms/PyWebViewPlatformService"; +import { BuildPlatform } from "@/interfaces/build"; /** * Factory class for creating platform-specific service implementations. @@ -35,19 +36,19 @@ export class PlatformServiceFactory { return PlatformServiceFactory.instance; } - const platform = process.env.VITE_PLATFORM || "web"; + const platform = process.env.VITE_PLATFORM || BuildPlatform.Web; switch (platform) { - case "capacitor": + case BuildPlatform.Capacitor: PlatformServiceFactory.instance = new CapacitorPlatformService(); break; - case "electron": + case BuildPlatform.Electron: PlatformServiceFactory.instance = new ElectronPlatformService(); break; - case "pywebview": + case BuildPlatform.PyWebView: PlatformServiceFactory.instance = new PyWebViewPlatformService(); break; - case "web": + case BuildPlatform.Web: default: PlatformServiceFactory.instance = new WebPlatformService(); break; diff --git a/src/services/api.ts b/src/services/api.ts index d7b67beb..93a2b691 100644 --- a/src/services/api.ts +++ b/src/services/api.ts @@ -7,6 +7,7 @@ import { AxiosError } from "axios"; import { logger, safeStringify } from "../utils/logger"; +import { BuildPlatform } from "@/interfaces/build"; /** * Handles API errors with platform-specific logging and error processing. @@ -36,7 +37,7 @@ import { logger, safeStringify } from "../utils/logger"; * ``` */ export const handleApiError = (error: AxiosError, endpoint: string) => { - if (process.env.VITE_PLATFORM === "capacitor") { + if (process.env.VITE_PLATFORM === BuildPlatform.Capacitor) { const endpointStr = safeStringify(endpoint); // we've seen this as an object in deep links logger.error(`[Capacitor API Error] ${endpointStr}:`, { message: error.message, diff --git a/src/utils/logger.ts b/src/utils/logger.ts index 8184c28b..ecca19f7 100644 --- a/src/utils/logger.ts +++ b/src/utils/logger.ts @@ -1,4 +1,5 @@ import { logToDb } from "../db/databaseUtil"; +import { BuildPlatform, NodeEnv } from "@/interfaces/build"; export function safeStringify(obj: unknown) { const seen = new WeakSet(); @@ -21,7 +22,7 @@ export function safeStringify(obj: unknown) { export const logger = { debug: (message: string, ...args: unknown[]) => { - if (process.env.NODE_ENV !== "production") { + if (process.env.NODE_ENV !== NodeEnv.Prod) { // eslint-disable-next-line no-console console.debug(message, ...args); // const argsString = args.length > 0 ? " - " + safeStringify(args) : ""; @@ -30,8 +31,8 @@ export const logger = { }, log: (message: string, ...args: unknown[]) => { if ( - process.env.NODE_ENV !== "production" || - process.env.VITE_PLATFORM === "capacitor" + process.env.NODE_ENV !== NodeEnv.Prod || + process.env.VITE_PLATFORM === BuildPlatform.Capacitor ) { // eslint-disable-next-line no-console console.log(message, ...args); @@ -41,9 +42,9 @@ export const logger = { }, info: (message: string, ...args: unknown[]) => { if ( - process.env.NODE_ENV !== "production" || - process.env.VITE_PLATFORM === "capacitor" || - process.env.VITE_PLATFORM === "electron" + process.env.NODE_ENV !== NodeEnv.Prod || + process.env.VITE_PLATFORM === BuildPlatform.Capacitor || + process.env.VITE_PLATFORM === BuildPlatform.Electron ) { // eslint-disable-next-line no-console console.info(message, ...args); diff --git a/src/views/DeepLinkRedirectView.vue b/src/views/DeepLinkRedirectView.vue index 8d2cb08c..71dd1a2f 100644 --- a/src/views/DeepLinkRedirectView.vue +++ b/src/views/DeepLinkRedirectView.vue @@ -100,6 +100,7 @@ import { Component, Vue } from "vue-facing-decorator"; import { RouteLocationNormalizedLoaded, Router } from "vue-router"; import { APP_SERVER } from "@/constants/app"; +import { NodeEnv } from "@/interfaces/build"; import { logger } from "@/utils/logger"; import { errorStringForLog } from "@/libs/endorserServer"; import { PlatformServiceFactory } from "@/services/PlatformServiceFactory"; @@ -148,7 +149,7 @@ export default class DeepLinkRedirectView extends Vue { this.deepLinkUrl = `timesafari://${fullPathWithQuery}`; this.webUrl = `${APP_SERVER}/${fullPathWithQuery}`; - this.isDevelopment = process.env.NODE_ENV !== "production"; + this.isDevelopment = process.env.NODE_ENV !== NodeEnv.Prod; this.userAgent = navigator.userAgent; this.openDeepLink(); diff --git a/tsconfig.node.json b/tsconfig.node.json index f2bdbb1d..ca790e95 100644 --- a/tsconfig.node.json +++ b/tsconfig.node.json @@ -8,5 +8,5 @@ "allowImportingTsExtensions": true, "noEmit": true }, - "include": ["vite.config.*"] + "include": ["vite.config.*", "./src/interfaces/build.ts"] } \ No newline at end of file diff --git a/vite.config.capacitor.mts b/vite.config.capacitor.mts index b47e5abe..a72f9b29 100644 --- a/vite.config.capacitor.mts +++ b/vite.config.capacitor.mts @@ -1,4 +1,5 @@ import { defineConfig } from "vite"; import { createBuildConfig } from "./vite.config.common.mts"; +import { BuildPlatform } from "./src/interfaces/build.ts"; -export default defineConfig(async () => createBuildConfig('capacitor')); \ No newline at end of file +export default defineConfig(async () => createBuildConfig(BuildPlatform.Capacitor)); \ No newline at end of file diff --git a/vite.config.common.mts b/vite.config.common.mts index e87b3ba7..eb8bac56 100644 --- a/vite.config.common.mts +++ b/vite.config.common.mts @@ -1,39 +1,40 @@ -import { defineConfig, UserConfig, Plugin } from "vite"; +import { defineConfig, UserConfig } from "vite"; import vue from "@vitejs/plugin-vue"; import dotenv from "dotenv"; import { loadAppConfig } from "./vite.config.common-utils.mts"; import path from "path"; import { fileURLToPath } from 'url'; - -export type BuildMode = 'web' | 'electron' | 'capacitor' | 'pywebview'; -export type BuildEnv = 'dev' | 'test' | 'prod'; +import { NodeEnv, BuildEnv, BuildPlatform } from "./src/interfaces/build.ts"; // Load environment variables -if ( - process.env.NODE_ENV === 'dev' - || process.env.NODE_ENV === 'test' - || process.env.NODE_ENV === 'prod' - ) { - console.log(`NODE_ENV=${process.env.NODE_ENV}`); +let buildEnv: BuildEnv; +if (process.env.NODE_ENV === NodeEnv.Dev) { + buildEnv = BuildEnv.Development; +} else if (process.env.NODE_ENV === NodeEnv.Test) { + buildEnv = BuildEnv.Testing; +} else if (process.env.NODE_ENV === NodeEnv.Prod) { + buildEnv = BuildEnv.Production; } else { - console.error("NODE_ENV is not set. Invoke with NODE_ENV=dev|test|prod"); - throw new Error("NODE_ENV is not set. Invoke with NODE_ENV=dev|test|prod"); - // process.exit(1); + console.error("NODE_ENV is not set. Invoke with NODE_ENV=" + Object.values(NodeEnv).join("|")); + throw new Error("NODE_ENV is not set. Invoke with NODE_ENV=" + Object.values(NodeEnv).join("|")); } +console.log(`Environment: ${buildEnv}`); -dotenv.config({ path: `.env.${process.env.NODE_ENV}` }); +dotenv.config({ path: `.env.${buildEnv}` }); const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); -export async function createBuildConfig(mode: BuildMode): Promise { +export async function createBuildConfig(platform: BuildPlatform): Promise { const appConfig = await loadAppConfig(); - const isElectron = mode === "electron"; - const isCapacitor = mode === "capacitor"; - const isPyWebView = mode === "pywebview"; + + console.log(`Platform: ${platform}`); + const isElectron = platform === BuildPlatform.Electron; + const isCapacitor = platform === BuildPlatform.Capacitor; + const isPyWebView = platform === BuildPlatform.PyWebView; // Explicitly set platform and disable PWA for Electron - process.env.VITE_PLATFORM = mode; + process.env.VITE_PLATFORM = platform; process.env.VITE_PWA_ENABLED = (isElectron || isPyWebView || isCapacitor) ? 'false' : 'true'; @@ -69,7 +70,7 @@ export async function createBuildConfig(mode: BuildMode): Promise { }, define: { 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV), - 'process.env.VITE_PLATFORM': JSON.stringify(mode), + 'process.env.VITE_PLATFORM': JSON.stringify(platform), 'process.env.VITE_PWA_ENABLED': JSON.stringify(!isElectron), 'process.env.VITE_DISABLE_PWA': JSON.stringify(isElectron), __dirname: isElectron ? JSON.stringify(process.cwd()) : '""', @@ -91,10 +92,10 @@ export async function createBuildConfig(mode: BuildMode): Promise { 'path': path.resolve(__dirname, './src/utils/node-modules/path.js'), 'fs': path.resolve(__dirname, './src/utils/node-modules/fs.js'), 'crypto': path.resolve(__dirname, './src/utils/node-modules/crypto.js'), - 'nostr-tools/nip06': mode === 'development' + 'nostr-tools/nip06': buildEnv === BuildEnv.Development ? 'nostr-tools/nip06' : path.resolve(__dirname, 'node_modules/nostr-tools/nip06'), - 'nostr-tools/core': mode === 'development' + 'nostr-tools/core': buildEnv === BuildEnv.Development ? 'nostr-tools' : path.resolve(__dirname, 'node_modules/nostr-tools'), 'nostr-tools': path.resolve(__dirname, 'node_modules/nostr-tools'), @@ -121,4 +122,4 @@ export async function createBuildConfig(mode: BuildMode): Promise { }; } -export default defineConfig(async () => createBuildConfig('web')); +export default defineConfig(async () => createBuildConfig(BuildPlatform.Web)); diff --git a/vite.config.electron.mts b/vite.config.electron.mts index 07188939..f966370f 100644 --- a/vite.config.electron.mts +++ b/vite.config.electron.mts @@ -1,9 +1,10 @@ import { defineConfig, mergeConfig } from "vite"; import { createBuildConfig } from "./vite.config.common.mts"; import path from 'path'; +import { BuildPlatform } from "./src/interfaces/build.ts"; export default defineConfig(async () => { - const baseConfig = await createBuildConfig('electron'); + const baseConfig = await createBuildConfig(BuildPlatform.Electron); return mergeConfig(baseConfig, { build: { diff --git a/vite.config.pywebview.mts b/vite.config.pywebview.mts index 81892137..f6371e9f 100644 --- a/vite.config.pywebview.mts +++ b/vite.config.pywebview.mts @@ -1,4 +1,5 @@ import { defineConfig } from "vite"; import { createBuildConfig } from "./vite.config.common.mts"; +import { BuildPlatform } from "./src/interfaces/build.ts"; -export default defineConfig(async () => createBuildConfig('pywebview')); \ No newline at end of file +export default defineConfig(async () => createBuildConfig(BuildPlatform.PyWebView)); \ No newline at end of file diff --git a/vite.config.web.mts b/vite.config.web.mts index a2f987f2..33a78784 100644 --- a/vite.config.web.mts +++ b/vite.config.web.mts @@ -2,9 +2,10 @@ import { defineConfig, mergeConfig } from "vite"; import { VitePWA } from "vite-plugin-pwa"; import { createBuildConfig } from "./vite.config.common.mts"; import { loadPwaConfig } from "./vite.config.common-utils.mts"; +import { BuildPlatform } from "./src/interfaces/build.ts"; export default defineConfig(async () => { - const baseConfig = await createBuildConfig('web'); + const baseConfig = await createBuildConfig(BuildPlatform.Web); const pwaConfig = await loadPwaConfig(); return mergeConfig(baseConfig, { -- 2.30.2 From f71bd9fb42048762c95d6417f2c840b3e8065443 Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Sun, 6 Jul 2025 19:02:09 -0600 Subject: [PATCH 10/12] Fix webapp-run command for test:web. --- playwright.config-local.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright.config-local.ts b/playwright.config-local.ts index 16f466a9..b09036f5 100644 --- a/playwright.config-local.ts +++ b/playwright.config-local.ts @@ -112,7 +112,7 @@ export default defineConfig({ */ webServer: { command: - "VITE_APP_SERVER=http://localhost:8081 VITE_DEFAULT_ENDORSER_API_SERVER=http://localhost:3000 VITE_DEFAULT_PARTNER_API_SERVER=http://localhost:3000 VITE_DEFAULT_IMAGE_API_SERVER=https://test-image-api.timesafari.app VITE_PASSKEYS_ENABLED=true npm run start:web -- --port=8081", + "NODE_ENV=dev VITE_APP_SERVER=http://localhost:8081 VITE_DEFAULT_ENDORSER_API_SERVER=http://localhost:3000 VITE_DEFAULT_PARTNER_API_SERVER=http://localhost:3000 VITE_DEFAULT_IMAGE_API_SERVER=https://test-image-api.timesafari.app VITE_PASSKEYS_ENABLED=true npm run start:web -- --port=8081", url: "http://localhost:8081", reuseExistingServer: !process.env.CI, }, -- 2.30.2 From bfa75484f32e6a9c0c80b1b65d1648e3ceebab8c Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Mon, 7 Jul 2025 11:16:18 -0600 Subject: [PATCH 11/12] Fix issue showing the actions on contact screen. (Test still fails later.) --- test-playwright/60-new-activity.spec.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test-playwright/60-new-activity.spec.ts b/test-playwright/60-new-activity.spec.ts index 0856e575..24c21885 100644 --- a/test-playwright/60-new-activity.spec.ts +++ b/test-playwright/60-new-activity.spec.ts @@ -2,14 +2,14 @@ import { test, expect } from '@playwright/test'; import { importUser, generateNewEthrUser, switchToUser } from './testUtils'; test('New offers for another user', async ({ page }) => { - const user01Did = await generateNewEthrUser(page); + const newUserDid = await generateNewEthrUser(page); await page.goto('./'); await page.getByTestId('closeOnboardingAndFinish').click(); await expect(page.getByTestId('newDirectOffersActivityNumber')).toBeHidden(); await importUser(page, '00'); await page.goto('./contacts'); - await page.getByPlaceholder('URL or DID, Name, Public Key').fill(user01Did + ', A Friend'); + await page.getByPlaceholder('URL or DID, Name, Public Key').fill(newUserDid + ', A Friend'); await expect(page.locator('button > svg.fa-plus')).toBeVisible(); await page.locator('button > svg.fa-plus').click(); await expect(page.locator('div[role="alert"] span:has-text("Contact Added")')).toBeVisible(); @@ -18,7 +18,7 @@ test('New offers for another user', async ({ page }) => { await expect(page.locator('div[role="alert"] button > svg.fa-xmark')).toBeHidden(); // ensure alert is gone // show buttons to make offers directly to people - await page.getByRole('button').filter({ hasText: /See Hours/i }).click(); + await page.getByRole('button').filter({ hasText: /See Actions/i }).click(); // make an offer directly to user 1 // Generate a random string of 3 characters, skipping the "0." at the beginning @@ -42,7 +42,7 @@ test('New offers for another user', async ({ page }) => { await expect(page.locator('div[role="alert"] button > svg.fa-xmark')).toBeHidden(); // ensure alert is gone // as user 1, go to the home page and check that two offers are shown as new - await switchToUser(page, user01Did); + await switchToUser(page, newUserDid); await page.goto('./'); let offerNumElem = page.getByTestId('newDirectOffersActivityNumber'); await expect(offerNumElem).toHaveText('2'); -- 2.30.2 From 8a2966a13e407adbabf2345d5b521413a75823b1 Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Mon, 7 Jul 2025 11:17:10 -0600 Subject: [PATCH 12/12] Enhance commentary and logging. --- .env.testing | 2 +- src/constants/app.ts | 1 + src/db-sql/migration.ts | 1 + src/libs/endorserServer.ts | 18 +++++++++++------- src/libs/util.ts | 2 +- src/views/AccountViewView.vue | 31 ++++++++++++++++--------------- src/views/HomeView.vue | 5 ++--- 7 files changed, 33 insertions(+), 27 deletions(-) diff --git a/.env.testing b/.env.testing index e69bc581..d4c84e0b 100644 --- a/.env.testing +++ b/.env.testing @@ -1,6 +1,6 @@ # Only the variables that start with VITE_ are seen in the application import.meta.env in Vue. - +# iOS doesn't like spaces in the app title. TIME_SAFARI_APP_TITLE="TimeSafari_Test" VITE_APP_SERVER=https://test.timesafari.app # This is the claim ID for actions in the BVC project. diff --git a/src/constants/app.ts b/src/constants/app.ts index a08cb15a..e0044ff4 100644 --- a/src/constants/app.ts +++ b/src/constants/app.ts @@ -7,6 +7,7 @@ export enum AppString { // This is used in titles and verbiage inside the app. // There is also an app name without spaces, for packaging in the package.json file used in the manifest. APP_NAME = "Time Safari", + // iOS doesn't like spaces in the app title. APP_NAME_NO_SPACES = "TimeSafari", PROD_ENDORSER_API_SERVER = "https://api.endorser.ch", diff --git a/src/db-sql/migration.ts b/src/db-sql/migration.ts index e06636bd..0feb3ad2 100644 --- a/src/db-sql/migration.ts +++ b/src/db-sql/migration.ts @@ -29,6 +29,7 @@ import { arrayBufferToBase64 } from "@/libs/crypto"; const randomBytes = crypto.getRandomValues(new Uint8Array(32)); const secretBase64 = arrayBufferToBase64(randomBytes); +console.log('secretBase64', secretBase64); // useful while we have multiple DBs activating (at least on web) // Each migration can include multiple SQL statements (with semicolons) const MIGRATIONS = [ diff --git a/src/libs/endorserServer.ts b/src/libs/endorserServer.ts index f2dc79a4..1776c29c 100644 --- a/src/libs/endorserServer.ts +++ b/src/libs/endorserServer.ts @@ -60,7 +60,7 @@ import { KeyMetaMaybeWithPrivate, } from "../interfaces/common"; import { PlanSummaryRecord } from "../interfaces/records"; -import { logger } from "../utils/logger"; +import { logger, safeStringify } from "../utils/logger"; import { PlatformServiceFactory } from "@/services/PlatformServiceFactory"; /** @@ -437,19 +437,23 @@ export async function getHeaders( } headers["Authorization"] = "Bearer " + token; } catch (error) { - // This rarely happens: we've seen it when they have account info but the - // encryption secret got lost. But in most cases we want users to at - // least see their feed -- and anything else that returns results for - // anonymous users. - // We'll continue with an anonymous request... still want to show feed and other things, but ideally let them know. + // This rarely happens: we've seen it when they have account info but the + // encryption secret got lost. + // Replicate this in Chrome: go to Storage and hit 'Clear site data'. + // Check the util.ts retrieveFullyDecryptedAccount method where it calls simpleDecrypt. + + // In most cases we want users to at least see their feed -- and anything + // else that returns results for anonymous users. + // We'll continue with an anonymous request... still want to show feed + // and other things, but we need to let them know. logConsoleAndDb( "Something failed in getHeaders call (will proceed anonymously" + ($notify ? " and notify user" : "") + "): " + // IntelliJ type system complains about getCircularReplacer() with: Argument of type '(obj: any, key: string, value: any) => any' is not assignable to parameter of type '(this: any, key: string, value: any) => any'. //JSON.stringify(error, getCircularReplacer()), // JSON.stringify(error) on a Dexie error throws another error about: Converting circular structure to JSON - error, + error + " - " + safeStringify(error), true, ); if ($notify) { diff --git a/src/libs/util.ts b/src/libs/util.ts index 17ba3c8e..5878a315 100644 --- a/src/libs/util.ts +++ b/src/libs/util.ts @@ -605,7 +605,7 @@ export const retrieveFullyDecryptedAccount = async ( dbAccount.values.length === 0 || dbAccount.values[0].length === 0 ) { - throw new Error("Account not found."); + throw new Error("Account not found for did: " + activeDid); } const fullAccountData = databaseUtil.mapQueryResultToValues( dbAccount, diff --git a/src/views/AccountViewView.vue b/src/views/AccountViewView.vue index b91dc224..6a589e14 100644 --- a/src/views/AccountViewView.vue +++ b/src/views/AccountViewView.vue @@ -126,7 +126,7 @@
People {{ profileImageUrl ? "without your image" : "" }} see this
- (if you've let them see your activity): + (if you've let them see which posts are yours):
URL.revokeObjectURL(this.downloadUrl), 1000); - } catch (error) { - this.handleExportError(error); - } + // // Revoke the temporary URL -- after a pause to avoid DuckDuckGo download failure + // setTimeout(() => URL.revokeObjectURL(this.downloadUrl), 1000); + // } catch (error) { + // this.handleExportError(error); + // } } /** diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index 49919da9..a626b099 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -102,8 +102,7 @@ Raymer * @version 1.0.0 */ class="text-md font-bold bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white mt-2 px-2 py-3 rounded-md" @click="showNameThenIdDialog()" > - Show them {{ PASSKEYS_ENABLED ? "default" : "your" }} identifier - info + Show them your identification info
@@ -683,7 +682,7 @@ export default class HomeView extends Vue { group: "alert", type: "warning", title: "Feed Loading Issue", - text: "Some feed data may be unavailable. Pull to refresh.", + text: "Some feed data may be unavailable. Try refreshing the page.", }, 5000, ); -- 2.30.2