Browse Source

convert all remaining DB writes & reads to SQL (with successful registration & claim)

pull/137/head
Trent Larson 1 month ago
parent
commit
8d1511e38f
  1. 153
      doc/secure-storage-implementation.md
  2. 13
      src/App.vue
  3. 6
      src/components/FeedFilters.vue
  4. 5
      src/components/GiftedDialog.vue
  5. 12
      src/components/ImageMethodDialog.vue
  6. 5
      src/components/MembersList.vue
  7. 8
      src/components/OfferDialog.vue
  8. 15
      src/components/OnboardingDialog.vue
  9. 14
      src/components/PhotoDialog.vue
  10. 12
      src/components/PushNotificationPermission.vue
  11. 8
      src/components/TopMessage.vue
  12. 7
      src/components/World/components/objects/landmarks.js
  13. 26
      src/db/databaseUtil.ts
  14. 6
      src/db/index.ts
  15. 1
      src/db/tables/accounts.ts
  16. 4
      src/libs/endorserServer.ts
  17. 123
      src/libs/util.ts
  18. 2
      src/main.capacitor.ts
  19. 5
      src/main.web.ts
  20. 15
      src/registerServiceWorker.ts
  21. 2
      src/services/deepLinks.ts
  22. 8
      src/test/index.ts
  23. 2
      src/utils/logger.ts
  24. 5
      src/views/AccountViewView.vue
  25. 11
      src/views/ClaimAddRawView.vue
  26. 5
      src/views/ClaimCertificateView.vue
  27. 5
      src/views/ClaimReportCertificateView.vue
  28. 18
      src/views/ClaimView.vue
  29. 5
      src/views/ConfirmGiftView.vue
  30. 5
      src/views/ContactAmountsView.vue
  31. 5
      src/views/ContactGiftingView.vue
  32. 5
      src/views/ContactImportView.vue
  33. 5
      src/views/ContactQRScanFullView.vue
  34. 5
      src/views/ContactQRScanShowView.vue
  35. 22
      src/views/ContactsView.vue
  36. 39
      src/views/DIDView.vue
  37. 2
      src/views/DeepLinkErrorView.vue
  38. 14
      src/views/DiscoverView.vue
  39. 25
      src/views/GiftedDetailsView.vue
  40. 10
      src/views/HelpNotificationsView.vue
  41. 14
      src/views/HelpView.vue
  42. 64
      src/views/HomeView.vue
  43. 9
      src/views/IdentitySwitcherView.vue
  44. 32
      src/views/ImportAccountView.vue
  45. 59
      src/views/ImportDerivedAccountView.vue
  46. 10
      src/views/InviteOneAcceptView.vue
  47. 41
      src/views/InviteOneView.vue
  48. 17
      src/views/LogView.vue
  49. 64
      src/views/NewActivityView.vue
  50. 13
      src/views/NewEditAccountView.vue
  51. 12
      src/views/NewEditProjectView.vue
  52. 24
      src/views/OfferDetailsView.vue
  53. 10
      src/views/OnboardMeetingListView.vue
  54. 10
      src/views/OnboardMeetingMembersView.vue
  55. 10
      src/views/OnboardMeetingSetupView.vue
  56. 17
      src/views/ProjectViewView.vue
  57. 19
      src/views/ProjectsView.vue
  58. 8
      src/views/QuickActionBvcBeginView.vue
  59. 29
      src/views/QuickActionBvcEndView.vue
  60. 19
      src/views/RecentOffersToUserProjectsView.vue
  61. 18
      src/views/RecentOffersToUserView.vue
  62. 21
      src/views/SearchAreaView.vue
  63. 22
      src/views/ShareMyContactInfoView.vue
  64. 29
      src/views/SharedPhotoView.vue
  65. 8
      src/views/StartView.vue
  66. 56
      src/views/TestView.vue
  67. 23
      src/views/UserProfileView.vue

153
doc/secure-storage-implementation.md

@ -131,7 +131,7 @@ async function getAccount(did: string): Promise<Account | undefined> {
); );
// Fallback to Dexie if needed // Fallback to Dexie if needed
if (USE_DEXIE_DB && !account) { if (USE_DEXIE_DB) {
account = await db.accounts.get(did); account = await db.accounts.get(did);
} }
@ -139,6 +139,157 @@ async function getAccount(did: string): Promise<Account | undefined> {
} }
``` ```
#### A. Modifying Code
When converting from Dexie.js to SQL-based implementation, follow these patterns:
1. **Database Access Pattern**
```typescript
// Before (Dexie)
const result = await db.table.where("field").equals(value).first();
// After (SQL)
const platform = PlatformServiceFactory.getInstance();
let result = await platform.dbQuery(
"SELECT * FROM table WHERE field = ?",
[value]
);
result = databaseUtil.mapQueryResultToValues(result);
// Fallback to Dexie if needed
if (USE_DEXIE_DB) {
result = await db.table.where("field").equals(value).first();
}
```
2. **Update Operations**
```typescript
// Before (Dexie)
await db.table.where("id").equals(id).modify(changes);
// After (SQL)
// For settings updates, use the utility methods:
await databaseUtil.updateDefaultSettings(changes);
// OR
await databaseUtil.updateAccountSettings(did, changes);
// For other tables, use direct SQL:
const platform = PlatformServiceFactory.getInstance();
await platform.dbExec(
"UPDATE table SET field1 = ?, field2 = ? WHERE id = ?",
[changes.field1, changes.field2, id]
);
// Fallback to Dexie if needed
if (USE_DEXIE_DB) {
await db.table.where("id").equals(id).modify(changes);
}
```
3. **Insert Operations**
```typescript
// Before (Dexie)
await db.table.add(item);
// After (SQL)
const platform = PlatformServiceFactory.getInstance();
const columns = Object.keys(item);
const values = Object.values(item);
const placeholders = values.map(() => '?').join(', ');
const sql = `INSERT INTO table (${columns.join(', ')}) VALUES (${placeholders})`;
await platform.dbExec(sql, values);
// Fallback to Dexie if needed
if (USE_DEXIE_DB) {
await db.table.add(item);
}
```
4. **Delete Operations**
```typescript
// Before (Dexie)
await db.table.where("id").equals(id).delete();
// After (SQL)
const platform = PlatformServiceFactory.getInstance();
await platform.dbExec("DELETE FROM table WHERE id = ?", [id]);
// Fallback to Dexie if needed
if (USE_DEXIE_DB) {
await db.table.where("id").equals(id).delete();
}
```
5. **Result Processing**
```typescript
// Before (Dexie)
const items = await db.table.toArray();
// After (SQL)
const platform = PlatformServiceFactory.getInstance();
let items = await platform.dbQuery("SELECT * FROM table");
items = databaseUtil.mapQueryResultToValues(items);
// Fallback to Dexie if needed
if (USE_DEXIE_DB) {
items = await db.table.toArray();
}
```
6. **Using Utility Methods**
When working with settings or other common operations, use the utility methods in `db/index.ts`:
```typescript
// Settings operations
await databaseUtil.updateDefaultSettings(settings);
await databaseUtil.updateAccountSettings(did, settings);
const settings = await databaseUtil.retrieveSettingsForDefaultAccount();
const settings = await databaseUtil.retrieveSettingsForActiveAccount();
// Logging operations
await databaseUtil.logToDb(message);
await databaseUtil.logConsoleAndDb(message, showInConsole);
```
Key Considerations:
- Always use `databaseUtil.mapQueryResultToValues()` to process SQL query results
- Use utility methods from `db/index.ts` when available instead of direct SQL
- Keep Dexie fallbacks wrapped in `if (USE_DEXIE_DB)` checks
- For queries that return results, use `let` variables to allow Dexie fallback to override
- For updates/inserts/deletes, execute both SQL and Dexie operations when `USE_DEXIE_DB` is true
Example Migration:
```typescript
// Before (Dexie)
export async function updateSettings(settings: Settings): Promise<void> {
await db.settings.put(settings);
}
// After (SQL)
export async function updateSettings(settings: Settings): Promise<void> {
const platform = PlatformServiceFactory.getInstance();
const { sql, params } = generateUpdateStatement(
settings,
"settings",
"id = ?",
[settings.id]
);
await platform.dbExec(sql, params);
}
```
Remember to:
- Create database access code to use the platform service, putting it in front of the Dexie version
- Instead of removing Dexie-specific code, keep it.
- For creates & updates & deletes, the duplicate code is fine.
- For queries where we use the results, make the setting from SQL into a 'let' variable, then wrap the Dexie code in a check for USE_DEXIE_DB from app.ts and if
it's true then use that result instead of the SQL code's result.
- Consider data migration needs, and warn if there are any potential migration problems
## Success Criteria ## Success Criteria
1. **Functionality** 1. **Functionality**

13
src/App.vue

@ -330,8 +330,11 @@
<script lang="ts"> <script lang="ts">
import { Vue, Component } from "vue-facing-decorator"; import { Vue, Component } from "vue-facing-decorator";
import { logConsoleAndDb, retrieveSettingsForActiveAccount } from "./db/index";
import { NotificationIface } from "./constants/app"; import { NotificationIface, USE_DEXIE_DB } from "./constants/app";
import * as databaseUtil from "./db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "./db/index";
import { logConsoleAndDb } from "./db/databaseUtil";
import { logger } from "./utils/logger"; import { logger } from "./utils/logger";
interface Settings { interface Settings {
@ -396,7 +399,11 @@ export default class App extends Vue {
try { try {
logger.log("Retrieving settings for the active account..."); logger.log("Retrieving settings for the active account...");
const settings: Settings = await retrieveSettingsForActiveAccount(); let settings: Settings =
await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
logger.log("Retrieved settings:", settings); logger.log("Retrieved settings:", settings);
const notifyingNewActivity = !!settings?.notifyingNewActivityTime; const notifyingNewActivity = !!settings?.notifyingNewActivityTime;

6
src/components/FeedFilters.vue

@ -101,6 +101,7 @@ import {
import { Router } from "vue-router"; import { Router } from "vue-router";
import { USE_DEXIE_DB } from "@/constants/app"; import { USE_DEXIE_DB } from "@/constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { MASTER_SETTINGS_KEY } from "../db/tables/settings"; import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
import { db, retrieveSettingsForActiveAccount } from "../db/index"; import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory"; import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
@ -125,7 +126,10 @@ export default class FeedFilters extends Vue {
async open(onCloseIfChanged: () => void) { async open(onCloseIfChanged: () => void) {
this.onCloseIfChanged = onCloseIfChanged; this.onCloseIfChanged = onCloseIfChanged;
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.hasVisibleDid = !!settings.filterFeedByVisible; this.hasVisibleDid = !!settings.filterFeedByVisible;
this.isNearby = !!settings.filterFeedByNearby; this.isNearby = !!settings.filterFeedByNearby;
if (settings.searchBoxes && settings.searchBoxes.length > 0) { if (settings.searchBoxes && settings.searchBoxes.length > 0) {

5
src/components/GiftedDialog.vue

@ -146,7 +146,10 @@ export default class GiftedDialog extends Vue {
this.offerId = offerId || ""; this.offerId = offerId || "";
try { try {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";

12
src/components/ImageMethodDialog.vue

@ -247,11 +247,16 @@ import axios from "axios";
import { ref } from "vue"; import { ref } from "vue";
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import VuePictureCropper, { cropper } from "vue-picture-cropper"; import VuePictureCropper, { cropper } from "vue-picture-cropper";
import { DEFAULT_IMAGE_API_SERVER, NotificationIface } from "../constants/app"; import {
DEFAULT_IMAGE_API_SERVER,
NotificationIface,
USE_DEXIE_DB,
} from "../constants/app";
import { retrieveSettingsForActiveAccount } from "../db/index"; import { retrieveSettingsForActiveAccount } from "../db/index";
import { accessToken } from "../libs/crypto"; import { accessToken } from "../libs/crypto";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "../services/PlatformServiceFactory"; import { PlatformServiceFactory } from "../services/PlatformServiceFactory";
import * as databaseUtil from "../db/databaseUtil";
const inputImageFileNameRef = ref<Blob>(); const inputImageFileNameRef = ref<Blob>();
@ -334,7 +339,10 @@ export default class ImageMethodDialog extends Vue {
*/ */
async mounted() { async mounted() {
try { try {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
} catch (error: unknown) { } catch (error: unknown) {
logger.error("Error retrieving settings from database:", error); logger.error("Error retrieving settings from database:", error);

5
src/components/MembersList.vue

@ -211,7 +211,10 @@ export default class MembersList extends Vue {
contacts: Array<Contact> = []; contacts: Array<Contact> = [];
async created() { async created() {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
this.firstName = settings.firstName || ""; this.firstName = settings.firstName || "";

8
src/components/OfferDialog.vue

@ -82,12 +82,13 @@
<script lang="ts"> <script lang="ts">
import { Vue, Component, Prop } from "vue-facing-decorator"; import { Vue, Component, Prop } from "vue-facing-decorator";
import { NotificationIface } from "../constants/app"; import { NotificationIface, USE_DEXIE_DB } from "../constants/app";
import { import {
createAndSubmitOffer, createAndSubmitOffer,
serverMessageForUser, serverMessageForUser,
} from "../libs/endorserServer"; } from "../libs/endorserServer";
import * as libsUtil from "../libs/util"; import * as libsUtil from "../libs/util";
import * as databaseUtil from "../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../db/index"; import { retrieveSettingsForActiveAccount } from "../db/index";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
@ -116,7 +117,10 @@ export default class OfferDialog extends Vue {
this.recipientDid = recipientDid; this.recipientDid = recipientDid;
this.recipientName = recipientName; this.recipientName = recipientName;
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";

15
src/components/OnboardingDialog.vue

@ -234,7 +234,10 @@ export default class OnboardingDialog extends Vue {
async open(page: OnboardPage) { async open(page: OnboardPage) {
this.page = page; this.page = page;
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.isRegistered = !!settings.isRegistered; this.isRegistered = !!settings.isRegistered;
const platformService = PlatformServiceFactory.getInstance(); const platformService = PlatformServiceFactory.getInstance();
@ -257,18 +260,28 @@ export default class OnboardingDialog extends Vue {
this.visible = true; this.visible = true;
if (this.page === OnboardPage.Create) { if (this.page === OnboardPage.Create) {
// we'll assume that they've been through all the other pages // we'll assume that they've been through all the other pages
await databaseUtil.updateAccountSettings(this.activeDid, {
finishedOnboarding: true,
});
if (USE_DEXIE_DB) {
await updateAccountSettings(this.activeDid, { await updateAccountSettings(this.activeDid, {
finishedOnboarding: true, finishedOnboarding: true,
}); });
} }
} }
}
async onClickClose(done?: boolean, goHome?: boolean) { async onClickClose(done?: boolean, goHome?: boolean) {
this.visible = false; this.visible = false;
if (done) { if (done) {
await databaseUtil.updateAccountSettings(this.activeDid, {
finishedOnboarding: true,
});
if (USE_DEXIE_DB) {
await updateAccountSettings(this.activeDid, { await updateAccountSettings(this.activeDid, {
finishedOnboarding: true, finishedOnboarding: true,
}); });
}
if (goHome) { if (goHome) {
this.$router.push({ name: "home" }); this.$router.push({ name: "home" });
} }

14
src/components/PhotoDialog.vue

@ -119,7 +119,12 @@ PhotoDialog.vue */
import axios from "axios"; import axios from "axios";
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import VuePictureCropper, { cropper } from "vue-picture-cropper"; import VuePictureCropper, { cropper } from "vue-picture-cropper";
import { DEFAULT_IMAGE_API_SERVER, NotificationIface } from "../constants/app"; import {
DEFAULT_IMAGE_API_SERVER,
NotificationIface,
USE_DEXIE_DB,
} from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../db/index"; import { retrieveSettingsForActiveAccount } from "../db/index";
import { accessToken } from "../libs/crypto"; import { accessToken } from "../libs/crypto";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
@ -173,9 +178,12 @@ export default class PhotoDialog extends Vue {
* @throws {Error} When settings retrieval fails * @throws {Error} When settings retrieval fails
*/ */
async mounted() { async mounted() {
logger.log("PhotoDialog mounted"); // logger.log("PhotoDialog mounted");
try { try {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.isRegistered = !!settings.isRegistered; this.isRegistered = !!settings.isRegistered;
logger.log("isRegistered:", this.isRegistered); logger.log("isRegistered:", this.isRegistered);

12
src/components/PushNotificationPermission.vue

@ -102,7 +102,12 @@
<script lang="ts"> <script lang="ts">
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import { DEFAULT_PUSH_SERVER, NotificationIface } from "../constants/app"; import {
DEFAULT_PUSH_SERVER,
NotificationIface,
USE_DEXIE_DB,
} from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { import {
logConsoleAndDb, logConsoleAndDb,
retrieveSettingsForActiveAccount, retrieveSettingsForActiveAccount,
@ -169,7 +174,10 @@ export default class PushNotificationPermission extends Vue {
this.isVisible = true; this.isVisible = true;
this.pushType = pushType; this.pushType = pushType;
try { try {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
let pushUrl = DEFAULT_PUSH_SERVER; let pushUrl = DEFAULT_PUSH_SERVER;
if (settings?.webPushServer) { if (settings?.webPushServer) {
pushUrl = settings.webPushServer; pushUrl = settings.webPushServer;

8
src/components/TopMessage.vue

@ -15,7 +15,8 @@
<script lang="ts"> <script lang="ts">
import { Component, Vue, Prop } from "vue-facing-decorator"; import { Component, Vue, Prop } from "vue-facing-decorator";
import { AppString, NotificationIface } from "../constants/app"; import { AppString, NotificationIface, USE_DEXIE_DB } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../db/index"; import { retrieveSettingsForActiveAccount } from "../db/index";
@Component @Component
@ -28,7 +29,10 @@ export default class TopMessage extends Vue {
async mounted() { async mounted() {
try { try {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
if ( if (
settings.warnIfTestServer && settings.warnIfTestServer &&
settings.apiServer !== AppString.PROD_ENDORSER_API_SERVER settings.apiServer !== AppString.PROD_ENDORSER_API_SERVER

7
src/components/World/components/objects/landmarks.js

@ -3,6 +3,8 @@ import * as THREE from "three";
import { GLTFLoader } from "three/addons/loaders/GLTFLoader"; import { GLTFLoader } from "three/addons/loaders/GLTFLoader";
import * as SkeletonUtils from "three/addons/utils/SkeletonUtils"; import * as SkeletonUtils from "three/addons/utils/SkeletonUtils";
import * as TWEEN from "@tweenjs/tween.js"; import * as TWEEN from "@tweenjs/tween.js";
import { USE_DEXIE_DB } from "../../../../constants/app";
import * as databaseUtil from "../../../../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../../../../db"; import { retrieveSettingsForActiveAccount } from "../../../../db";
import { getHeaders } from "../../../../libs/endorserServer"; import { getHeaders } from "../../../../libs/endorserServer";
import { logger } from "../../../../utils/logger"; import { logger } from "../../../../utils/logger";
@ -14,7 +16,10 @@ export async function loadLandmarks(vue, world, scene, loop) {
vue.setWorldProperty("animationDurationSeconds", ANIMATION_DURATION_SECS); vue.setWorldProperty("animationDurationSeconds", ANIMATION_DURATION_SECS);
try { try {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
const activeDid = settings.activeDid || ""; const activeDid = settings.activeDid || "";
const apiServer = settings.apiServer; const apiServer = settings.apiServer;
const headers = await getHeaders(activeDid); const headers = await getHeaders(activeDid);

26
src/db/databaseUtil.ts

@ -1,3 +1,8 @@
/**
* This file is the SQL replacement of the index.ts file in the db directory.
* That file will eventually be deleted.
*/
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory"; import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { MASTER_SETTINGS_KEY, Settings } from "./tables/settings"; import { MASTER_SETTINGS_KEY, Settings } from "./tables/settings";
import { logger } from "@/utils/logger"; import { logger } from "@/utils/logger";
@ -81,7 +86,15 @@ export async function retrieveSettingsForDefaultAccount(): Promise<Settings> {
if (!result) { if (!result) {
return DEFAULT_SETTINGS; return DEFAULT_SETTINGS;
} else { } else {
return mapColumnsToValues(result.columns, result.values)[0] as Settings; const settings = mapColumnsToValues(
result.columns,
result.values,
)[0] as Settings;
if (settings.searchBoxes) {
// @ts-expect-error - the searchBoxes field is a string in the DB
settings.searchBoxes = JSON.parse(settings.searchBoxes);
}
return settings;
} }
} }
@ -101,7 +114,12 @@ export async function retrieveSettingsForActiveAccount(): Promise<Settings> {
const overrideSettingsFiltered = Object.fromEntries( const overrideSettingsFiltered = Object.fromEntries(
Object.entries(overrideSettings).filter(([_, v]) => v !== null), Object.entries(overrideSettings).filter(([_, v]) => v !== null),
); );
return { ...defaultSettings, ...overrideSettingsFiltered }; const settings = { ...defaultSettings, ...overrideSettingsFiltered };
if (settings.searchBoxes) {
// @ts-expect-error - the searchBoxes field is a string in the DB
settings.searchBoxes = JSON.parse(settings.searchBoxes);
}
return settings;
} }
} }
@ -160,8 +178,8 @@ export function generateInsertStatement(
model: Record<string, unknown>, model: Record<string, unknown>,
tableName: string, tableName: string,
): { sql: string; params: unknown[] } { ): { sql: string; params: unknown[] } {
const columns = Object.keys(model); const columns = Object.keys(model).filter((key) => model[key] !== undefined);
const values = Object.values(model); const values = Object.values(model).filter((value) => value !== undefined);
const placeholders = values.map(() => "?").join(", "); const placeholders = values.map(() => "?").join(", ");
const insertSql = `INSERT INTO ${tableName} (${columns.join(", ")}) VALUES (${placeholders})`; const insertSql = `INSERT INTO ${tableName} (${columns.join(", ")}) VALUES (${placeholders})`;
return { return {

6
src/db/index.ts

@ -1,3 +1,9 @@
/**
* This is the original IndexedDB version of the database.
* It will eventually be replaced fully by the SQL version in databaseUtil.ts.
* Turn this on or off with the USE_DEXIE_DB constant in constants/app.ts.
*/
import BaseDexie, { Table } from "dexie"; import BaseDexie, { Table } from "dexie";
import { encrypted, Encryption } from "@pvermeer/dexie-encrypted-addon"; import { encrypted, Encryption } from "@pvermeer/dexie-encrypted-addon";
import * as R from "ramda"; import * as R from "ramda";

1
src/db/tables/accounts.ts

@ -45,6 +45,7 @@ export type Account = {
publicKeyHex: string; publicKeyHex: string;
}; };
// When finished with USE_DEXIE_DB, move these fields to Account and move identity and mnemonic here.
export type AccountEncrypted = Account & { export type AccountEncrypted = Account & {
identityEncrBase64: string; identityEncrBase64: string;
mnemonicEncrBase64: string; mnemonicEncrBase64: string;

4
src/libs/endorserServer.ts

@ -30,8 +30,8 @@ import {
} from "../constants/app"; } from "../constants/app";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import { accessToken, deriveAddress, nextDerivationPath } from "../libs/crypto"; import { accessToken, deriveAddress, nextDerivationPath } from "../libs/crypto";
import { logConsoleAndDb, NonsensitiveDexie } from "../db/index"; import { NonsensitiveDexie } from "../db/index";
import { logConsoleAndDb } from "../db/databaseUtil";
import { import {
retrieveAccountMetadata, retrieveAccountMetadata,
retrieveFullyDecryptedAccount, retrieveFullyDecryptedAccount,

123
src/libs/util.ts

@ -490,10 +490,19 @@ export const retrieveAccountCount = async (): Promise<number> => {
}; };
export const retrieveAccountDids = async (): Promise<string[]> => { export const retrieveAccountDids = async (): Promise<string[]> => {
const platformService = PlatformServiceFactory.getInstance();
const dbAccounts = await platformService.dbQuery(`SELECT did FROM accounts`);
let allDids =
databaseUtil
.mapQueryResultToValues(dbAccounts)
?.map((row) => row[0] as string) || [];
if (USE_DEXIE_DB) {
// this is the old way
// one of the few times we use accountsDBPromise directly; try to avoid more usage // one of the few times we use accountsDBPromise directly; try to avoid more usage
const accountsDB = await accountsDBPromise; const accountsDB = await accountsDBPromise;
const allAccounts = await accountsDB.accounts.toArray(); const allAccounts = await accountsDB.accounts.toArray();
const allDids = allAccounts.map((acc) => acc.did); allDids = allAccounts.map((acc) => acc.did);
}
return allDids; return allDids;
}; };
@ -502,6 +511,21 @@ export const retrieveAccountDids = async (): Promise<string[]> => {
export const retrieveAccountMetadata = async ( export const retrieveAccountMetadata = async (
activeDid: string, activeDid: string,
): Promise<AccountKeyInfo | undefined> => { ): Promise<AccountKeyInfo | undefined> => {
let result: AccountKeyInfo | undefined = undefined;
const platformService = PlatformServiceFactory.getInstance();
const dbAccount = await platformService.dbQuery(
`SELECT * FROM accounts WHERE did = ?`,
[activeDid],
);
const account = databaseUtil.mapQueryResultToValues(dbAccount)[0] as Account;
if (account) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { identity, mnemonic, ...metadata } = account;
result = metadata;
} else {
result = undefined;
}
if (USE_DEXIE_DB) {
// one of the few times we use accountsDBPromise directly; try to avoid more usage // one of the few times we use accountsDBPromise directly; try to avoid more usage
const accountsDB = await accountsDBPromise; const accountsDB = await accountsDBPromise;
const account = (await accountsDB.accounts const account = (await accountsDB.accounts
@ -511,21 +535,36 @@ export const retrieveAccountMetadata = async (
if (account) { if (account) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
const { identity, mnemonic, ...metadata } = account; const { identity, mnemonic, ...metadata } = account;
return metadata; result = metadata;
} else { } else {
return undefined; result = undefined;
}
} }
return result;
}; };
export const retrieveAllAccountsMetadata = async (): Promise<Account[]> => { export const retrieveAllAccountsMetadata = async (): Promise<
AccountEncrypted[]
> => {
const platformService = PlatformServiceFactory.getInstance();
const dbAccounts = await platformService.dbQuery(`SELECT * FROM accounts`);
const accounts = databaseUtil.mapQueryResultToValues(dbAccounts) as Account[];
let result = accounts.map((account) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { identity, mnemonic, ...metadata } = account;
return metadata;
});
if (USE_DEXIE_DB) {
// one of the few times we use accountsDBPromise directly; try to avoid more usage // one of the few times we use accountsDBPromise directly; try to avoid more usage
const accountsDB = await accountsDBPromise; const accountsDB = await accountsDBPromise;
const array = await accountsDB.accounts.toArray(); const array = await accountsDB.accounts.toArray();
return array.map((account) => { result = array.map((account) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
const { identity, mnemonic, ...metadata } = account; const { identity, mnemonic, ...metadata } = account;
return metadata; return metadata;
}); });
}
return result;
}; };
export const retrieveFullyDecryptedAccount = async ( export const retrieveFullyDecryptedAccount = async (
@ -583,32 +622,34 @@ export const retrieveFullyDecryptedAccount = async (
export const retrieveAllFullyDecryptedAccounts = async (): Promise< export const retrieveAllFullyDecryptedAccounts = async (): Promise<
Array<AccountKeyInfo> Array<AccountKeyInfo>
> => { > => {
const platformService = PlatformServiceFactory.getInstance();
const queryResult = await platformService.dbQuery("SELECT * FROM accounts");
let allAccounts = databaseUtil.mapQueryResultToValues(
queryResult,
) as unknown as Account[];
if (USE_DEXIE_DB) {
const accountsDB = await accountsDBPromise; const accountsDB = await accountsDBPromise;
const allAccounts = await accountsDB.accounts.toArray(); allAccounts = await accountsDB.accounts.toArray();
}
return allAccounts; return allAccounts;
}; };
/** /**
* Generates a new identity, saves it to the database, and sets it as the active identity. * Saves a new identity to both SQL and Dexie databases
* @return {Promise<string>} with the DID of the new identity
*/ */
export const generateSaveAndActivateIdentity = async (): Promise<string> => { export async function saveNewIdentity(
const mnemonic = generateSeed(); identity: string,
// address is 0x... ETH address, without "did:eth:" mnemonic: string,
const [address, privateHex, publicHex, derivationPath] = newId: { did: string; keys: Array<{ publicKeyHex: string }> },
deriveAddress(mnemonic); derivationPath: string,
): Promise<void> {
const newId = newIdentifier(address, publicHex, privateHex, derivationPath);
const identity = JSON.stringify(newId);
// one of the few times we use accountsDBPromise directly; try to avoid more usage
try { try {
// add to the new sql db // add to the new sql db
const platformService = PlatformServiceFactory.getInstance(); const platformService = PlatformServiceFactory.getInstance();
const secrets = await platformService.dbQuery( const secrets = await platformService.dbQuery(
`SELECT secretBase64 FROM secret`, `SELECT secretBase64 FROM secret`,
); );
if (secrets.values.length === 0 || secrets.values[0].length === 0) { if (!secrets?.values?.length || !secrets.values[0]?.length) {
throw new Error( throw new Error(
"No initial encryption supported. We recommend you clear your data and start over.", "No initial encryption supported. We recommend you clear your data and start over.",
); );
@ -634,6 +675,7 @@ export const generateSaveAndActivateIdentity = async (): Promise<string> => {
await databaseUtil.updateDefaultSettings({ activeDid: newId.did }); await databaseUtil.updateDefaultSettings({ activeDid: newId.did });
if (USE_DEXIE_DB) { if (USE_DEXIE_DB) {
// one of the few times we use accountsDBPromise directly; try to avoid more usage
const accountsDB = await accountsDBPromise; const accountsDB = await accountsDBPromise;
await accountsDB.accounts.add({ await accountsDB.accounts.add({
dateCreated: new Date().toISOString(), dateCreated: new Date().toISOString(),
@ -643,7 +685,6 @@ export const generateSaveAndActivateIdentity = async (): Promise<string> => {
mnemonic: mnemonic, mnemonic: mnemonic,
publicKeyHex: newId.keys[0].publicKeyHex, publicKeyHex: newId.keys[0].publicKeyHex,
}); });
await updateDefaultSettings({ activeDid: newId.did }); await updateDefaultSettings({ activeDid: newId.did });
} }
} catch (error) { } catch (error) {
@ -652,6 +693,22 @@ export const generateSaveAndActivateIdentity = async (): Promise<string> => {
"Failed to set default settings. Please try again or restart the app.", "Failed to set default settings. Please try again or restart the app.",
); );
} }
}
/**
* Generates a new identity, saves it to the database, and sets it as the active identity.
* @return {Promise<string>} with the DID of the new identity
*/
export const generateSaveAndActivateIdentity = async (): Promise<string> => {
const mnemonic = generateSeed();
// address is 0x... ETH address, without "did:eth:"
const [address, privateHex, publicHex, derivationPath] =
deriveAddress(mnemonic);
const newId = newIdentifier(address, publicHex, privateHex, derivationPath);
const identity = JSON.stringify(newId);
await saveNewIdentity(identity, mnemonic, newId, derivationPath);
await databaseUtil.updateAccountSettings(newId.did, { isRegistered: false }); await databaseUtil.updateAccountSettings(newId.did, { isRegistered: false });
if (USE_DEXIE_DB) { if (USE_DEXIE_DB) {
await updateAccountSettings(newId.did, { isRegistered: false }); await updateAccountSettings(newId.did, { isRegistered: false });
@ -673,9 +730,19 @@ export const registerAndSavePasskey = async (
passkeyCredIdHex, passkeyCredIdHex,
publicKeyHex: Buffer.from(publicKeyBytes).toString("hex"), publicKeyHex: Buffer.from(publicKeyBytes).toString("hex"),
}; };
const insertStatement = databaseUtil.generateInsertStatement(
account,
"accounts",
);
await PlatformServiceFactory.getInstance().dbExec(
insertStatement.sql,
insertStatement.params,
);
if (USE_DEXIE_DB) {
// one of the few times we use accountsDBPromise directly; try to avoid more usage // one of the few times we use accountsDBPromise directly; try to avoid more usage
const accountsDB = await accountsDBPromise; const accountsDB = await accountsDBPromise;
await accountsDB.accounts.add(account); await accountsDB.accounts.add(account);
}
return account; return account;
}; };
@ -683,13 +750,22 @@ export const registerSaveAndActivatePasskey = async (
keyName: string, keyName: string,
): Promise<Account> => { ): Promise<Account> => {
const account = await registerAndSavePasskey(keyName); const account = await registerAndSavePasskey(keyName);
await databaseUtil.updateDefaultSettings({ activeDid: account.did });
await databaseUtil.updateAccountSettings(account.did, {
isRegistered: false,
});
if (USE_DEXIE_DB) {
await updateDefaultSettings({ activeDid: account.did }); await updateDefaultSettings({ activeDid: account.did });
await updateAccountSettings(account.did, { isRegistered: false }); await updateAccountSettings(account.did, { isRegistered: false });
}
return account; return account;
}; };
export const getPasskeyExpirationSeconds = async (): Promise<number> => { export const getPasskeyExpirationSeconds = async (): Promise<number> => {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
return ( return (
(settings?.passkeyExpirationMinutes ?? DEFAULT_PASSKEY_EXPIRATION_MINUTES) * (settings?.passkeyExpirationMinutes ?? DEFAULT_PASSKEY_EXPIRATION_MINUTES) *
60 60
@ -705,7 +781,10 @@ export const sendTestThroughPushServer = async (
subscriptionJSON: PushSubscriptionJSON, subscriptionJSON: PushSubscriptionJSON,
skipFilter: boolean, skipFilter: boolean,
): Promise<AxiosResponse> => { ): Promise<AxiosResponse> => {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
let pushUrl: string = DEFAULT_PUSH_SERVER as string; let pushUrl: string = DEFAULT_PUSH_SERVER as string;
if (settings?.webPushServer) { if (settings?.webPushServer) {
pushUrl = settings.webPushServer; pushUrl = settings.webPushServer;

2
src/main.capacitor.ts

@ -34,7 +34,7 @@ import router from "./router";
import { handleApiError } from "./services/api"; import { handleApiError } from "./services/api";
import { AxiosError } from "axios"; import { AxiosError } from "axios";
import { DeepLinkHandler } from "./services/deepLinks"; import { DeepLinkHandler } from "./services/deepLinks";
import { logConsoleAndDb } from "./db"; import { logConsoleAndDb } from "./db/databaseUtil";
import { logger } from "./utils/logger"; import { logger } from "./utils/logger";
logger.log("[Capacitor] Starting initialization"); logger.log("[Capacitor] Starting initialization");

5
src/main.web.ts

@ -3,7 +3,10 @@ import { initBackend } from "absurd-sql/dist/indexeddb-main-thread";
import { initializeApp } from "./main.common"; import { initializeApp } from "./main.common";
// Only import service worker for web builds // Only import service worker for web builds
if (process.env.VITE_PLATFORM !== 'electron' && process.env.VITE_PWA_ENABLED === 'true') { if (
process.env.VITE_PLATFORM !== "electron" &&
process.env.VITE_PWA_ENABLED === "true"
) {
import("./registerServiceWorker"); // Web PWA support import("./registerServiceWorker"); // Web PWA support
} }

15
src/registerServiceWorker.ts

@ -3,17 +3,20 @@
import { register } from "register-service-worker"; import { register } from "register-service-worker";
// Check if we're in an Electron environment // Check if we're in an Electron environment
const isElectron = process.env.VITE_PLATFORM === 'electron' || const isElectron =
process.env.VITE_DISABLE_PWA === 'true' || process.env.VITE_PLATFORM === "electron" ||
window.navigator.userAgent.toLowerCase().includes('electron'); process.env.VITE_DISABLE_PWA === "true" ||
window.navigator.userAgent.toLowerCase().includes("electron");
// Only register service worker if: // Only register service worker if:
// 1. Not in Electron // 1. Not in Electron
// 2. PWA is explicitly enabled // 2. PWA is explicitly enabled
// 3. In production mode // 3. In production mode
if (!isElectron && if (
!isElectron &&
process.env.VITE_PWA_ENABLED === "true" && process.env.VITE_PWA_ENABLED === "true" &&
process.env.NODE_ENV === "production") { process.env.NODE_ENV === "production"
) {
register(`${process.env.BASE_URL}sw.js`, { register(`${process.env.BASE_URL}sw.js`, {
ready() { ready() {
console.log("Service worker is active."); console.log("Service worker is active.");
@ -47,6 +50,6 @@ if (!isElectron &&
: process.env.VITE_PWA_ENABLED !== "true" : process.env.VITE_PWA_ENABLED !== "true"
? "PWA not enabled" ? "PWA not enabled"
: "not in production mode" : "not in production mode"
}` }`,
); );
} }

2
src/services/deepLinks.ts

@ -52,7 +52,7 @@ import {
routeSchema, routeSchema,
DeepLinkRoute, DeepLinkRoute,
} from "../interfaces/deepLinks"; } from "../interfaces/deepLinks";
import { logConsoleAndDb } from "../db"; import { logConsoleAndDb } from "../db/databaseUtil";
import type { DeepLinkError } from "../interfaces/deepLinks"; import type { DeepLinkError } from "../interfaces/deepLinks";
/** /**

8
src/test/index.ts

@ -1,6 +1,7 @@
import axios from "axios"; import axios from "axios";
import * as didJwt from "did-jwt"; import * as didJwt from "did-jwt";
import { AppString } from "../constants/app"; import { AppString, USE_DEXIE_DB } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../db"; import { retrieveSettingsForActiveAccount } from "../db";
import { SERVICE_ID } from "../libs/endorserServer"; import { SERVICE_ID } from "../libs/endorserServer";
import { deriveAddress, newIdentifier } from "../libs/crypto"; import { deriveAddress, newIdentifier } from "../libs/crypto";
@ -16,7 +17,10 @@ export async function testServerRegisterUser() {
const identity0 = newIdentifier(addr, publicHex, privateHex, deriPath); const identity0 = newIdentifier(addr, publicHex, privateHex, deriPath);
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
// Make a claim // Make a claim
const vcClaim = { const vcClaim = {

2
src/utils/logger.ts

@ -1,4 +1,4 @@
import { logToDb } from "../db"; import { logToDb } from "../db/databaseUtil";
function safeStringify(obj: unknown) { function safeStringify(obj: unknown) {
const seen = new WeakSet(); const seen = new WeakSet();

5
src/views/AccountViewView.vue

@ -2022,9 +2022,14 @@ export default class AccountViewView extends Vue {
if ((error as any).response.status === 404) { if ((error as any).response.status === 404) {
logger.error("The image was already deleted:", error); logger.error("The image was already deleted:", error);
await databaseUtil.updateAccountSettings(this.activeDid, {
profileImageUrl: undefined,
});
if (USE_DEXIE_DB) {
await updateAccountSettings(this.activeDid, { await updateAccountSettings(this.activeDid, {
profileImageUrl: undefined, profileImageUrl: undefined,
}); });
}
this.profileImageUrl = undefined; this.profileImageUrl = undefined;

11
src/views/ClaimAddRawView.vue

@ -33,8 +33,10 @@ import { Component, Vue } from "vue-facing-decorator";
import { AxiosInstance } from "axios"; import { AxiosInstance } from "axios";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import { NotificationIface } from "../constants/app"; import { NotificationIface, USE_DEXIE_DB } from "../constants/app";
import { logConsoleAndDb, retrieveSettingsForActiveAccount } from "../db/index"; import * as databaseUtil from "../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../db/index";
import { logConsoleAndDb } from "../db/databaseUtil";
import * as serverUtil from "../libs/endorserServer"; import * as serverUtil from "../libs/endorserServer";
import * as libsUtil from "../libs/util"; import * as libsUtil from "../libs/util";
import { errorStringForLog } from "../libs/endorserServer"; import { errorStringForLog } from "../libs/endorserServer";
@ -77,7 +79,10 @@ export default class ClaimAddRawView extends Vue {
* Initialize settings from active account * Initialize settings from active account
*/ */
private async initializeSettings() { private async initializeSettings() {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
} }

5
src/views/ClaimCertificateView.vue

@ -35,7 +35,10 @@ export default class ClaimCertificateView extends Vue {
serverUtil = serverUtil; serverUtil = serverUtil;
async created() { async created() {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
const pathParams = window.location.pathname.substring( const pathParams = window.location.pathname.substring(

5
src/views/ClaimReportCertificateView.vue

@ -31,7 +31,10 @@ export default class ClaimReportCertificateView extends Vue {
endorserServer = endorserServer; endorserServer = endorserServer;
async created() { async created() {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
const pathParams = window.location.pathname.substring( const pathParams = window.location.pathname.substring(

18
src/views/ClaimView.vue

@ -543,13 +543,10 @@ import { GenericVerifiableCredential } from "../interfaces";
import GiftedDialog from "../components/GiftedDialog.vue"; import GiftedDialog from "../components/GiftedDialog.vue";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import { NotificationIface, USE_DEXIE_DB } from "../constants/app"; import { NotificationIface, USE_DEXIE_DB } from "../constants/app";
import {
db,
logConsoleAndDb,
retrieveSettingsForActiveAccount,
} from "../db/index";
import { Contact } from "../db/tables/contacts";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { db } from "../db/index";
import { logConsoleAndDb } from "../db/databaseUtil";
import { Contact } from "../db/tables/contacts";
import * as serverUtil from "../libs/endorserServer"; import * as serverUtil from "../libs/endorserServer";
import { import {
GenericCredWrapper, GenericCredWrapper,
@ -622,8 +619,11 @@ export default class ClaimView extends Vue {
} }
async created() { async created() {
logger.log("ClaimView created"); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
const settings = await retrieveSettingsForActiveAccount(); if (USE_DEXIE_DB) {
settings = await databaseUtil.retrieveSettingsForActiveAccount();
}
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
const platformService = PlatformServiceFactory.getInstance(); const platformService = PlatformServiceFactory.getInstance();
@ -702,7 +702,6 @@ export default class ClaimView extends Vue {
} }
async loadClaim(claimId: string, userDid: string) { async loadClaim(claimId: string, userDid: string) {
logger.log("[ClaimView] loadClaim called with claimId:", claimId);
const urlPath = libsUtil.isGlobalUri(claimId) const urlPath = libsUtil.isGlobalUri(claimId)
? "/api/claim/byHandle/" ? "/api/claim/byHandle/"
: "/api/claim/"; : "/api/claim/";
@ -710,7 +709,6 @@ export default class ClaimView extends Vue {
const headers = await serverUtil.getHeaders(userDid); const headers = await serverUtil.getHeaders(userDid);
try { try {
logger.log("[ClaimView] Making API request to:", url);
const resp = await this.axios.get(url, { headers }); const resp = await this.axios.get(url, { headers });
if (resp.status === 200) { if (resp.status === 200) {
this.veriClaim = resp.data; this.veriClaim = resp.data;

5
src/views/ConfirmGiftView.vue

@ -530,7 +530,10 @@ export default class ConfirmGiftView extends Vue {
* Initializes component settings and user data * Initializes component settings and user data
*/ */
private async initializeSettings() { private async initializeSettings() {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
const platformService = PlatformServiceFactory.getInstance(); const platformService = PlatformServiceFactory.getInstance();

5
src/views/ContactAmountsView.vue

@ -169,7 +169,10 @@ export default class ContactAmountssView extends Vue {
this.contact = (await db.contacts.get(contactDid)) || null; this.contact = (await db.contacts.get(contactDid)) || null;
} }
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.activeDid = settings?.activeDid || ""; this.activeDid = settings?.activeDid || "";
this.apiServer = settings?.apiServer || ""; this.apiServer = settings?.apiServer || "";

5
src/views/ContactGiftingView.vue

@ -100,7 +100,10 @@ export default class ContactGiftingView extends Vue {
async created() { async created() {
try { try {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";

5
src/views/ContactImportView.vue

@ -344,7 +344,10 @@ export default class ContactImportView extends Vue {
* Initializes component settings from active account * Initializes component settings from active account
*/ */
private async initializeSettings() { private async initializeSettings() {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
} }

5
src/views/ContactQRScanFullView.vue

@ -164,7 +164,10 @@ export default class ContactQRScan extends Vue {
async created() { async created() {
try { try {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
this.givenName = settings.firstName || ""; this.givenName = settings.firstName || "";

5
src/views/ContactQRScanShowView.vue

@ -263,7 +263,10 @@ export default class ContactQRScanShow extends Vue {
async created() { async created() {
try { try {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
this.givenName = settings.firstName || ""; this.givenName = settings.firstName || "";

22
src/views/ContactsView.vue

@ -539,7 +539,12 @@ export default class ContactsView extends Vue {
if (response.status != 201) { if (response.status != 201) {
throw { error: { response: response } }; throw { error: { response: response } };
} }
await databaseUtil.updateAccountSettings(this.activeDid, {
isRegistered: true,
});
if (USE_DEXIE_DB) {
await updateAccountSettings(this.activeDid, { isRegistered: true }); await updateAccountSettings(this.activeDid, { isRegistered: true });
}
this.isRegistered = true; this.isRegistered = true;
this.$notify( this.$notify(
{ {
@ -990,6 +995,8 @@ export default class ContactsView extends Vue {
newContact as unknown as Record<string, unknown>, newContact as unknown as Record<string, unknown>,
"contacts", "contacts",
); );
console.log("sql", sql);
console.log("params", params);
let contactPromise = platformService.dbExec(sql, params); let contactPromise = platformService.dbExec(sql, params);
if (USE_DEXIE_DB) { if (USE_DEXIE_DB) {
// @ts-expect-error since the result of this promise won't be used, and this will go away soon // @ts-expect-error since the result of this promise won't be used, and this will go away soon
@ -1023,17 +1030,27 @@ export default class ContactsView extends Vue {
text: "Do you want to register them?", text: "Do you want to register them?",
onCancel: async (stopAsking?: boolean) => { onCancel: async (stopAsking?: boolean) => {
if (stopAsking) { if (stopAsking) {
await databaseUtil.updateDefaultSettings({
hideRegisterPromptOnNewContact: stopAsking,
});
if (USE_DEXIE_DB) {
await updateDefaultSettings({ await updateDefaultSettings({
hideRegisterPromptOnNewContact: stopAsking, hideRegisterPromptOnNewContact: stopAsking,
}); });
}
this.hideRegisterPromptOnNewContact = stopAsking; this.hideRegisterPromptOnNewContact = stopAsking;
} }
}, },
onNo: async (stopAsking?: boolean) => { onNo: async (stopAsking?: boolean) => {
if (stopAsking) { if (stopAsking) {
await databaseUtil.updateDefaultSettings({
hideRegisterPromptOnNewContact: stopAsking,
});
if (USE_DEXIE_DB) {
await updateDefaultSettings({ await updateDefaultSettings({
hideRegisterPromptOnNewContact: stopAsking, hideRegisterPromptOnNewContact: stopAsking,
}); });
}
this.hideRegisterPromptOnNewContact = stopAsking; this.hideRegisterPromptOnNewContact = stopAsking;
} }
}, },
@ -1327,9 +1344,14 @@ export default class ContactsView extends Vue {
private async toggleShowContactAmounts() { private async toggleShowContactAmounts() {
const newShowValue = !this.showGiveNumbers; const newShowValue = !this.showGiveNumbers;
try { try {
await databaseUtil.updateDefaultSettings({
showContactGivesInline: newShowValue,
});
if (USE_DEXIE_DB) {
await updateDefaultSettings({ await updateDefaultSettings({
showContactGivesInline: newShowValue, showContactGivesInline: newShowValue,
}); });
}
} catch (err) { } catch (err) {
const fullError = const fullError =
"Error updating contact-amounts setting: " + errorStringForLog(err); "Error updating contact-amounts setting: " + errorStringForLog(err);

39
src/views/DIDView.vue

@ -232,10 +232,11 @@ import { RouteLocationNormalizedLoaded, Router } from "vue-router";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import InfiniteScroll from "../components/InfiniteScroll.vue"; import InfiniteScroll from "../components/InfiniteScroll.vue";
import TopMessage from "../components/TopMessage.vue"; import TopMessage from "../components/TopMessage.vue";
import { NotificationIface } from "../constants/app"; import { NotificationIface, USE_DEXIE_DB } from "../constants/app";
import { db, retrieveSettingsForActiveAccount } from "../db/index"; import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import { BoundingBox } from "../db/tables/settings"; import { BoundingBox } from "../db/tables/settings";
import * as databaseUtil from "../db/databaseUtil";
import { import {
GenericCredWrapper, GenericCredWrapper,
GenericVerifiableCredential, GenericVerifiableCredential,
@ -253,6 +254,7 @@ import {
import * as libsUtil from "../libs/util"; import * as libsUtil from "../libs/util";
import EntityIcon from "../components/EntityIcon.vue"; import EntityIcon from "../components/EntityIcon.vue";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
/** /**
* DIDView Component * DIDView Component
@ -323,7 +325,10 @@ export default class DIDView extends Vue {
* Initializes component settings from active account * Initializes component settings from active account
*/ */
private async initializeSettings() { private async initializeSettings() {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
} }
@ -370,7 +375,17 @@ export default class DIDView extends Vue {
private async loadContactInformation() { private async loadContactInformation() {
if (!this.viewingDid) return; if (!this.viewingDid) return;
const platformService = PlatformServiceFactory.getInstance();
const dbContacts = await platformService.dbQuery(
"SELECT * FROM contacts WHERE did = ?",
[this.viewingDid],
);
this.contactFromDid = databaseUtil.mapQueryResultToValues(
dbContacts,
)[0] as unknown as Contact;
if (USE_DEXIE_DB) {
this.contactFromDid = await db.contacts.get(this.viewingDid); this.contactFromDid = await db.contacts.get(this.viewingDid);
}
if (this.contactFromDid) { if (this.contactFromDid) {
this.contactYaml = yaml.dump(this.contactFromDid); this.contactYaml = yaml.dump(this.contactFromDid);
} }
@ -433,8 +448,14 @@ export default class DIDView extends Vue {
* @param contact - Contact object to be deleted * @param contact - Contact object to be deleted
*/ */
async deleteContact(contact: Contact) { async deleteContact(contact: Contact) {
const platformService = PlatformServiceFactory.getInstance();
await platformService.dbExec("DELETE FROM contacts WHERE did = ?", [
contact.did,
]);
if (USE_DEXIE_DB) {
await db.open(); await db.open();
await db.contacts.delete(contact.did); await db.contacts.delete(contact.did);
}
this.$notify( this.$notify(
{ {
group: "alert", group: "alert",
@ -492,7 +513,14 @@ export default class DIDView extends Vue {
); );
if (regResult.success) { if (regResult.success) {
contact.registered = true; contact.registered = true;
const platformService = PlatformServiceFactory.getInstance();
await platformService.dbExec(
"UPDATE contacts SET registered = ? WHERE did = ?",
[true, contact.did],
);
if (USE_DEXIE_DB) {
await db.contacts.update(contact.did, { registered: true }); await db.contacts.update(contact.did, { registered: true });
}
this.$notify( this.$notify(
{ {
@ -781,7 +809,14 @@ export default class DIDView extends Vue {
const visibility = resp.data; const visibility = resp.data;
contact.seesMe = visibility; contact.seesMe = visibility;
//console.log("Visi check:", visibility, contact.seesMe, contact.did); //console.log("Visi check:", visibility, contact.seesMe, contact.did);
const platformService = PlatformServiceFactory.getInstance();
await platformService.dbExec(
"UPDATE contacts SET seesMe = ? WHERE did = ?",
[visibility, contact.did],
);
if (USE_DEXIE_DB) {
await db.contacts.update(contact.did, { seesMe: visibility }); await db.contacts.update(contact.did, { seesMe: visibility });
}
this.$notify( this.$notify(
{ {

2
src/views/DeepLinkErrorView.vue

@ -42,7 +42,7 @@
import { computed, onMounted } from "vue"; import { computed, onMounted } from "vue";
import { useRoute, useRouter } from "vue-router"; import { useRoute, useRouter } from "vue-router";
import { VALID_DEEP_LINK_ROUTES } from "../interfaces/deepLinks"; import { VALID_DEEP_LINK_ROUTES } from "../interfaces/deepLinks";
import { logConsoleAndDb } from "../db"; import { logConsoleAndDb } from "../db/databaseUtil";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
const route = useRoute(); const route = useRoute();

14
src/views/DiscoverView.vue

@ -317,6 +317,7 @@ import TopMessage from "../components/TopMessage.vue";
import { import {
NotificationIface, NotificationIface,
DEFAULT_PARTNER_API_SERVER, DEFAULT_PARTNER_API_SERVER,
USE_DEXIE_DB,
} from "../constants/app"; } from "../constants/app";
import { import {
db, db,
@ -325,6 +326,7 @@ import {
} from "../db/index"; } from "../db/index";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import { BoundingBox } from "../db/tables/settings"; import { BoundingBox } from "../db/tables/settings";
import * as databaseUtil from "../db/databaseUtil";
import { PlanData } from "../interfaces"; import { PlanData } from "../interfaces";
import { import {
didInfo, didInfo,
@ -333,6 +335,8 @@ import {
} from "../libs/endorserServer"; } from "../libs/endorserServer";
import { OnboardPage, retrieveAccountDids } from "../libs/util"; import { OnboardPage, retrieveAccountDids } from "../libs/util";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { UserProfile } from "@/libs/partnerServer";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
interface Tile { interface Tile {
indexLat: number; indexLat: number;
indexLon: number; indexLon: number;
@ -392,14 +396,22 @@ export default class DiscoverView extends Vue {
const searchPeople = !!this.$route.query["searchPeople"]; const searchPeople = !!this.$route.query["searchPeople"];
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.activeDid = (settings.activeDid as string) || ""; this.activeDid = (settings.activeDid as string) || "";
this.apiServer = (settings.apiServer as string) || ""; this.apiServer = (settings.apiServer as string) || "";
this.partnerApiServer = this.partnerApiServer =
(settings.partnerApiServer as string) || this.partnerApiServer; (settings.partnerApiServer as string) || this.partnerApiServer;
this.searchBox = settings.searchBoxes?.[0] || null; this.searchBox = settings.searchBoxes?.[0] || null;
const platformService = PlatformServiceFactory.getInstance();
const dbContacts = await platformService.dbQuery("SELECT * FROM contacts");
this.allContacts = databaseUtil.mapQueryResultToValues(dbContacts) as unknown as Contact[];
if (USE_DEXIE_DB) {
this.allContacts = await db.contacts.toArray(); this.allContacts = await db.contacts.toArray();
}
this.allMyDids = await retrieveAccountDids(); this.allMyDids = await retrieveAccountDids();

25
src/views/GiftedDetailsView.vue

@ -261,8 +261,13 @@ import { RouteLocationNormalizedLoaded, Router } from "vue-router";
import ImageMethodDialog from "../components/ImageMethodDialog.vue"; import ImageMethodDialog from "../components/ImageMethodDialog.vue";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import TopMessage from "../components/TopMessage.vue"; import TopMessage from "../components/TopMessage.vue";
import { DEFAULT_IMAGE_API_SERVER, NotificationIface } from "../constants/app"; import {
DEFAULT_IMAGE_API_SERVER,
NotificationIface,
USE_DEXIE_DB,
} from "../constants/app";
import { db, retrieveSettingsForActiveAccount } from "../db/index"; import { db, retrieveSettingsForActiveAccount } from "../db/index";
import * as databaseUtil from "../db/databaseUtil";
import { GenericCredWrapper, GiveVerifiableCredential } from "../interfaces"; import { GenericCredWrapper, GiveVerifiableCredential } from "../interfaces";
import { import {
createAndSubmitGive, createAndSubmitGive,
@ -275,6 +280,8 @@ import {
import * as libsUtil from "../libs/util"; import * as libsUtil from "../libs/util";
import { retrieveAccountDids } from "../libs/util"; import { retrieveAccountDids } from "../libs/util";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { Contact } from "@/db/tables/contacts";
@Component({ @Component({
components: { components: {
@ -421,7 +428,10 @@ export default class GiftedDetails extends Vue {
this.imageUrl = this.$route.query["shareUrl"] as string; this.imageUrl = this.$route.query["shareUrl"] as string;
} }
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
@ -429,7 +439,16 @@ export default class GiftedDetails extends Vue {
(this.giverDid && !this.giverName) || (this.giverDid && !this.giverName) ||
(this.recipientDid && !this.recipientName) (this.recipientDid && !this.recipientName)
) { ) {
const allContacts = await db.contacts.toArray(); const platformService = PlatformServiceFactory.getInstance();
const dbContacts = await platformService.dbQuery(
"SELECT * FROM contacts",
);
let allContacts = databaseUtil.mapQueryResultToValues(
dbContacts,
) as unknown as Contact[];
if (USE_DEXIE_DB) {
allContacts = await db.contacts.toArray();
}
const allMyDids = await retrieveAccountDids(); const allMyDids = await retrieveAccountDids();
if (this.giverDid && !this.giverName) { if (this.giverDid && !this.giverName) {
this.giverName = didInfo( this.giverName = didInfo(

10
src/views/HelpNotificationsView.vue

@ -308,13 +308,15 @@
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import { NotificationIface } from "../constants/app"; import { NotificationIface, USE_DEXIE_DB } from "../constants/app";
import { DIRECT_PUSH_TITLE, sendTestThroughPushServer } from "../libs/util"; import { DIRECT_PUSH_TITLE, sendTestThroughPushServer } from "../libs/util";
import PushNotificationPermission from "../components/PushNotificationPermission.vue"; import PushNotificationPermission from "../components/PushNotificationPermission.vue";
import { db } from "../db/index"; import { db } from "../db/index";
import { MASTER_SETTINGS_KEY } from "../db/tables/settings"; import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
import * as databaseUtil from "../db/databaseUtil";
import { Router } from "vue-router"; import { Router } from "vue-router";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
@Component({ components: { PushNotificationPermission, QuickNav } }) @Component({ components: { PushNotificationPermission, QuickNav } })
export default class HelpNotificationsView extends Vue { export default class HelpNotificationsView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
@ -420,10 +422,16 @@ export default class HelpNotificationsView extends Vue {
DIRECT_PUSH_TITLE, DIRECT_PUSH_TITLE,
async (success: boolean, timeText: string, message?: string) => { async (success: boolean, timeText: string, message?: string) => {
if (success) { if (success) {
databaseUtil.updateDefaultSettings({
notifyingReminderMessage: message,
notifyingReminderTime: timeText,
});
if (USE_DEXIE_DB) {
await db.settings.update(MASTER_SETTINGS_KEY, { await db.settings.update(MASTER_SETTINGS_KEY, {
notifyingReminderMessage: message, notifyingReminderMessage: message,
notifyingReminderTime: timeText, notifyingReminderTime: timeText,
}); });
}
this.notifyingReminder = true; this.notifyingReminder = true;
this.notifyingReminderMessage = message || ""; this.notifyingReminderMessage = message || "";
this.notifyingReminderTime = timeText; this.notifyingReminderTime = timeText;

14
src/views/HelpView.vue

@ -579,7 +579,8 @@ import { useClipboard } from "@vueuse/core";
import * as Package from "../../package.json"; import * as Package from "../../package.json";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import { NotificationIface } from "../constants/app"; import { NotificationIface, USE_DEXIE_DB } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { import {
retrieveSettingsForActiveAccount, retrieveSettingsForActiveAccount,
updateAccountSettings, updateAccountSettings,
@ -609,12 +610,21 @@ export default class HelpView extends Vue {
} }
async unsetFinishedOnboarding() { async unsetFinishedOnboarding() {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
if (settings.activeDid) { if (settings.activeDid) {
await databaseUtil.updateAccountSettings(settings.activeDid, {
finishedOnboarding: false,
});
if (USE_DEXIE_DB) {
await updateAccountSettings(settings.activeDid, { await updateAccountSettings(settings.activeDid, {
finishedOnboarding: false, finishedOnboarding: false,
}); });
} }
}
this.$router.push({ name: "home" }); this.$router.push({ name: "home" });
} }
} }

64
src/views/HomeView.vue

@ -316,6 +316,7 @@ import {
AppString, AppString,
NotificationIface, NotificationIface,
PASSKEYS_ENABLED, PASSKEYS_ENABLED,
USE_DEXIE_DB,
} from "../constants/app"; } from "../constants/app";
import { import {
db, db,
@ -329,6 +330,7 @@ import {
checkIsAnyFeedFilterOn, checkIsAnyFeedFilterOn,
MASTER_SETTINGS_KEY, MASTER_SETTINGS_KEY,
} from "../db/tables/settings"; } from "../db/tables/settings";
import * as databaseUtil from "../db/databaseUtil";
import { import {
contactForDid, contactForDid,
containsNonHiddenDid, containsNonHiddenDid,
@ -349,6 +351,7 @@ import { GiveSummaryRecord } from "../interfaces";
import * as serverUtil from "../libs/endorserServer"; import * as serverUtil from "../libs/endorserServer";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { GiveRecordWithContactInfo } from "../types"; import { GiveRecordWithContactInfo } from "../types";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
interface Claim { interface Claim {
claim?: Claim; // For nested claims in Verifiable Credentials claim?: Claim; // For nested claims in Verifiable Credentials
@ -520,10 +523,22 @@ export default class HomeView extends Vue {
this.allMyDids = [newDid]; this.allMyDids = [newDid];
} }
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
const platformService = PlatformServiceFactory.getInstance();
const dbContacts = await platformService.dbQuery(
"SELECT * FROM contacts",
);
this.allContacts = databaseUtil.mapQueryResultToValues(
dbContacts,
) as unknown as Contact[];
if (USE_DEXIE_DB) {
this.allContacts = await db.contacts.toArray(); this.allContacts = await db.contacts.toArray();
}
this.feedLastViewedClaimId = settings.lastViewedClaimId; this.feedLastViewedClaimId = settings.lastViewedClaimId;
this.givenName = settings.firstName || ""; this.givenName = settings.firstName || "";
this.isFeedFilteredByVisible = !!settings.filterFeedByVisible; this.isFeedFilteredByVisible = !!settings.filterFeedByVisible;
@ -534,7 +549,6 @@ export default class HomeView extends Vue {
settings.lastAckedOfferToUserProjectsJwtId; settings.lastAckedOfferToUserProjectsJwtId;
this.searchBoxes = settings.searchBoxes || []; this.searchBoxes = settings.searchBoxes || [];
this.showShortcutBvc = !!settings.showShortcutBvc; this.showShortcutBvc = !!settings.showShortcutBvc;
this.isAnyFeedFilterOn = checkIsAnyFeedFilterOn(settings); this.isAnyFeedFilterOn = checkIsAnyFeedFilterOn(settings);
if (!settings.finishedOnboarding) { if (!settings.finishedOnboarding) {
@ -552,10 +566,16 @@ export default class HomeView extends Vue {
this.activeDid, this.activeDid,
); );
if (resp.status === 200) { if (resp.status === 200) {
await databaseUtil.updateAccountSettings(this.activeDid, {
isRegistered: true,
...(await databaseUtil.retrieveSettingsForActiveAccount()),
});
if (USE_DEXIE_DB) {
await updateAccountSettings(this.activeDid, { await updateAccountSettings(this.activeDid, {
isRegistered: true, isRegistered: true,
...(await retrieveSettingsForActiveAccount()), ...(await retrieveSettingsForActiveAccount()),
}); });
}
this.isRegistered = true; this.isRegistered = true;
} }
} catch (e) { } catch (e) {
@ -618,7 +638,10 @@ export default class HomeView extends Vue {
* Called by mounted() and reloadFeedOnChange() * Called by mounted() and reloadFeedOnChange()
*/ */
private async loadSettings() { private async loadSettings() {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.feedLastViewedClaimId = settings.lastViewedClaimId; this.feedLastViewedClaimId = settings.lastViewedClaimId;
@ -642,8 +665,15 @@ export default class HomeView extends Vue {
* Called by mounted() and initializeIdentity() * Called by mounted() and initializeIdentity()
*/ */
private async loadContacts() { private async loadContacts() {
const platformService = PlatformServiceFactory.getInstance();
const dbContacts = await platformService.dbQuery("SELECT * FROM contacts");
this.allContacts = databaseUtil.mapQueryResultToValues(
dbContacts,
) as unknown as Contact[];
if (USE_DEXIE_DB) {
this.allContacts = await db.contacts.toArray(); this.allContacts = await db.contacts.toArray();
} }
}
/** /**
* Verifies user registration status with endorser service * Verifies user registration status with endorser service
@ -663,11 +693,22 @@ export default class HomeView extends Vue {
this.activeDid, this.activeDid,
); );
if (resp.status === 200) { if (resp.status === 200) {
let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
await databaseUtil.updateAccountSettings(this.activeDid, {
apiServer: this.apiServer,
isRegistered: true,
...settings,
});
if (USE_DEXIE_DB) {
await updateAccountSettings(this.activeDid, { await updateAccountSettings(this.activeDid, {
apiServer: this.apiServer, apiServer: this.apiServer,
isRegistered: true, isRegistered: true,
...(await retrieveSettingsForActiveAccount()), ...settings,
}); });
}
this.isRegistered = true; this.isRegistered = true;
} }
} catch (e) { } catch (e) {
@ -728,7 +769,10 @@ export default class HomeView extends Vue {
* Called by mounted() * Called by mounted()
*/ */
private async checkOnboarding() { private async checkOnboarding() {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
if (!settings.finishedOnboarding) { if (!settings.finishedOnboarding) {
(this.$refs.onboardingDialog as OnboardingDialog).open(OnboardPage.Home); (this.$refs.onboardingDialog as OnboardingDialog).open(OnboardPage.Home);
} }
@ -790,7 +834,10 @@ export default class HomeView extends Vue {
* Called by FeedFilters component when filters change * Called by FeedFilters component when filters change
*/ */
async reloadFeedOnChange() { async reloadFeedOnChange() {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.isFeedFilteredByVisible = !!settings.filterFeedByVisible; this.isFeedFilteredByVisible = !!settings.filterFeedByVisible;
this.isFeedFilteredByNearby = !!settings.filterFeedByNearby; this.isFeedFilteredByNearby = !!settings.filterFeedByNearby;
this.isAnyFeedFilterOn = checkIsAnyFeedFilterOn(settings); this.isAnyFeedFilterOn = checkIsAnyFeedFilterOn(settings);
@ -1230,12 +1277,17 @@ export default class HomeView extends Vue {
this.feedLastViewedClaimId == null || this.feedLastViewedClaimId == null ||
this.feedLastViewedClaimId < records[0].jwtId this.feedLastViewedClaimId < records[0].jwtId
) { ) {
await databaseUtil.updateDefaultSettings({
lastViewedClaimId: records[0].jwtId,
});
if (USE_DEXIE_DB) {
await db.open(); await db.open();
await db.settings.update(MASTER_SETTINGS_KEY, { await db.settings.update(MASTER_SETTINGS_KEY, {
lastViewedClaimId: records[0].jwtId, lastViewedClaimId: records[0].jwtId,
}); });
} }
} }
}
/** /**
* Handles feed error and shows notification * Handles feed error and shows notification

9
src/views/IdentitySwitcherView.vue

@ -105,15 +105,17 @@ import { Component, Vue } from "vue-facing-decorator";
import { Router } from "vue-router"; import { Router } from "vue-router";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import { NotificationIface } from "../constants/app"; import { NotificationIface, USE_DEXIE_DB } from "../constants/app";
import { import {
accountsDBPromise, accountsDBPromise,
db, db,
retrieveSettingsForActiveAccount, retrieveSettingsForActiveAccount,
} from "../db/index"; } from "../db/index";
import { MASTER_SETTINGS_KEY } from "../db/tables/settings"; import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
import * as databaseUtil from "../db/databaseUtil";
import { retrieveAllAccountsMetadata } from "../libs/util"; import { retrieveAllAccountsMetadata } from "../libs/util";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
@Component({ components: { QuickNav } }) @Component({ components: { QuickNav } })
export default class IdentitySwitcherView extends Vue { export default class IdentitySwitcherView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
@ -127,7 +129,10 @@ export default class IdentitySwitcherView extends Vue {
async created() { async created() {
try { try {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
this.apiServerInput = settings.apiServer || ""; this.apiServerInput = settings.apiServer || "";

32
src/views/ImportAccountView.vue

@ -86,7 +86,8 @@
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import { Router } from "vue-router"; import { Router } from "vue-router";
import { AppString, NotificationIface } from "../constants/app"; import { AppString, NotificationIface, USE_DEXIE_DB } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { import {
accountsDBPromise, accountsDBPromise,
db, db,
@ -97,9 +98,12 @@ import {
DEFAULT_ROOT_DERIVATION_PATH, DEFAULT_ROOT_DERIVATION_PATH,
deriveAddress, deriveAddress,
newIdentifier, newIdentifier,
simpleEncrypt,
} from "../libs/crypto"; } from "../libs/crypto";
import { retrieveAccountCount } from "../libs/util"; import { retrieveAccountCount, saveNewIdentity } from "../libs/util";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
@Component({ @Component({
components: {}, components: {},
}) })
@ -126,7 +130,10 @@ export default class ImportAccountView extends Vue {
async created() { async created() {
this.numAccounts = await retrieveAccountCount(); this.numAccounts = await retrieveAccountCount();
// get the server, to help with import on the test server // get the server, to help with import on the test server
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
} }
@ -155,22 +162,13 @@ export default class ImportAccountView extends Vue {
const accountsDB = await accountsDBPromise; const accountsDB = await accountsDBPromise;
if (this.shouldErase) { if (this.shouldErase) {
const platformService = PlatformServiceFactory.getInstance();
await platformService.dbExec("DELETE FROM accounts");
if (USE_DEXIE_DB) {
await accountsDB.accounts.clear(); await accountsDB.accounts.clear();
} }
await accountsDB.accounts.add({ }
dateCreated: new Date().toISOString(), saveNewIdentity(JSON.stringify(newId), mne, newId, this.derivationPath);
derivationPath: this.derivationPath,
did: newId.did,
identity: JSON.stringify(newId),
mnemonic: mne,
publicKeyHex: newId.keys[0].publicKeyHex,
});
// record that as the active DID
await db.open();
await db.settings.update(MASTER_SETTINGS_KEY, {
activeDid: newId.did,
});
this.$router.push({ name: "account" }); this.$router.push({ name: "account" });
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (err: any) { } catch (err: any) {

59
src/views/ImportDerivedAccountView.vue

@ -80,8 +80,12 @@ import {
} from "../libs/crypto"; } from "../libs/crypto";
import { accountsDBPromise, db } from "../db/index"; import { accountsDBPromise, db } from "../db/index";
import { MASTER_SETTINGS_KEY } from "../db/tables/settings"; import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
import { retrieveAllFullyDecryptedAccounts } from "../libs/util"; import * as databaseUtil from "../db/databaseUtil";
import { retrieveAllAccountsMetadata } from "../libs/util";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { AccountEncrypted } from "@/db/tables/accounts";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { USE_DEXIE_DB } from "@/constants/app";
@Component({ @Component({
components: {}, components: {},
}) })
@ -94,11 +98,15 @@ export default class ImportAccountView extends Vue {
selectedArrayFirstDid = ""; selectedArrayFirstDid = "";
async mounted() { async mounted() {
const accounts = await retrieveAllFullyDecryptedAccounts(); // let's match derived accounts differently so we don't need the private info const accounts: AccountEncrypted[] = await retrieveAllAccountsMetadata();
const seedDids: Record<string, Array<string>> = {}; const seedDids: Record<string, Array<string>> = {};
accounts.forEach((account) => { accounts.forEach((account) => {
const prevDids: Array<string> = seedDids[account.mnemonic] || []; const mnemonicMaybeEncrypted =
seedDids[account.mnemonic] = prevDids.concat([account.did]); account.mnemonic || account.mnemonicEncrBase64;
if (mnemonicMaybeEncrypted) {
const prevDids: Array<string> = seedDids[mnemonicMaybeEncrypted] || [];
seedDids[mnemonicMaybeEncrypted] = prevDids.concat([account.did]);
}
}); });
this.didArrays = Object.values(seedDids); this.didArrays = Object.values(seedDids);
this.selectedArrayFirstDid = this.didArrays[0][0]; this.selectedArrayFirstDid = this.didArrays[0][0];
@ -117,14 +125,29 @@ export default class ImportAccountView extends Vue {
const selectedArray: Array<string> = const selectedArray: Array<string> =
this.didArrays.find((dids) => dids[0] === this.selectedArrayFirstDid) || this.didArrays.find((dids) => dids[0] === this.selectedArrayFirstDid) ||
[]; [];
const platformService = PlatformServiceFactory.getInstance();
const qmarks = selectedArray.map(() => "?").join(",");
const queryResult = await platformService.dbQuery(
`SELECT * FROM accounts WHERE did IN (${qmarks})`,
selectedArray,
);
let allMatchingAccounts = databaseUtil.mapQueryResultToValues(
queryResult,
) as unknown as AccountEncrypted[];
if (USE_DEXIE_DB) {
const accountsDB = await accountsDBPromise; // let's match derived accounts differently so we don't need the private info const accountsDB = await accountsDBPromise; // let's match derived accounts differently so we don't need the private info
const allMatchingAccounts = await accountsDB.accounts allMatchingAccounts = (await accountsDB.accounts
.where("did") .where("did")
.anyOf(...selectedArray) .anyOf(...selectedArray)
.toArray(); .toArray()) as AccountEncrypted[];
}
const accountWithMaxDeriv = allMatchingAccounts[0]; const accountWithMaxDeriv = allMatchingAccounts[0];
allMatchingAccounts.slice(1).forEach((account) => { allMatchingAccounts.slice(1).forEach((account) => {
if (account.derivationPath > accountWithMaxDeriv.derivationPath) { if (
account.derivationPath &&
accountWithMaxDeriv.derivationPath &&
account.derivationPath > accountWithMaxDeriv.derivationPath
) {
accountWithMaxDeriv.derivationPath = account.derivationPath; accountWithMaxDeriv.derivationPath = account.derivationPath;
} }
}); });
@ -140,6 +163,21 @@ export default class ImportAccountView extends Vue {
const newId = newIdentifier(address, publicHex, privateHex, newDerivPath); const newId = newIdentifier(address, publicHex, privateHex, newDerivPath);
try { try {
const { sql, params } = databaseUtil.generateInsertStatement(
{
dateCreated: new Date().toISOString(),
derivationPath: newDerivPath,
did: newId.did,
identity: JSON.stringify(newId),
mnemonic: mne,
publicKeyHex: newId.keys[0].publicKeyHex,
},
"accounts",
);
const platformService = PlatformServiceFactory.getInstance();
await platformService.dbExec(sql, params);
if (USE_DEXIE_DB) {
const accountsDB = await accountsDBPromise;
await accountsDB.accounts.add({ await accountsDB.accounts.add({
dateCreated: new Date().toISOString(), dateCreated: new Date().toISOString(),
derivationPath: newDerivPath, derivationPath: newDerivPath,
@ -148,12 +186,17 @@ export default class ImportAccountView extends Vue {
mnemonic: mne, mnemonic: mne,
publicKeyHex: newId.keys[0].publicKeyHex, publicKeyHex: newId.keys[0].publicKeyHex,
}); });
}
// record that as the active DID // record that as the active DID
await db.open(); await platformService.dbExec("UPDATE settings SET activeDid = ?", [
newId.did,
]);
if (USE_DEXIE_DB) {
await db.settings.update(MASTER_SETTINGS_KEY, { await db.settings.update(MASTER_SETTINGS_KEY, {
activeDid: newId.did, activeDid: newId.did,
}); });
}
this.$router.push({ name: "account" }); this.$router.push({ name: "account" });
} catch (err) { } catch (err) {
logger.error("Error saving mnemonic & updating settings:", err); logger.error("Error saving mnemonic & updating settings:", err);

10
src/views/InviteOneAcceptView.vue

@ -42,12 +42,13 @@ import { Component, Vue } from "vue-facing-decorator";
import { Router, RouteLocationNormalized } from "vue-router"; import { Router, RouteLocationNormalized } from "vue-router";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import { APP_SERVER, NotificationIface } from "../constants/app"; import { APP_SERVER, NotificationIface, USE_DEXIE_DB } from "../constants/app";
import { import {
db, db,
logConsoleAndDb, logConsoleAndDb,
retrieveSettingsForActiveAccount, retrieveSettingsForActiveAccount,
} from "../db/index"; } from "../db/index";
import * as databaseUtil from "../db/databaseUtil";
import { decodeEndorserJwt } from "../libs/crypto/vc"; import { decodeEndorserJwt } from "../libs/crypto/vc";
import { errorStringForLog } from "../libs/endorserServer"; import { errorStringForLog } from "../libs/endorserServer";
import { generateSaveAndActivateIdentity } from "../libs/util"; import { generateSaveAndActivateIdentity } from "../libs/util";
@ -112,10 +113,13 @@ export default class InviteOneAcceptView extends Vue {
*/ */
async mounted() { async mounted() {
this.checkingInvite = true; this.checkingInvite = true;
await db.open();
// Load or generate identity // Load or generate identity
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
await db.open();
settings = await retrieveSettingsForActiveAccount();
}
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";

41
src/views/InviteOneView.vue

@ -138,11 +138,19 @@ import ContactNameDialog from "../components/ContactNameDialog.vue";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import TopMessage from "../components/TopMessage.vue"; import TopMessage from "../components/TopMessage.vue";
import InviteDialog from "../components/InviteDialog.vue"; import InviteDialog from "../components/InviteDialog.vue";
import { APP_SERVER, AppString, NotificationIface } from "../constants/app"; import {
APP_SERVER,
AppString,
NotificationIface,
USE_DEXIE_DB,
} from "../constants/app";
import { db, retrieveSettingsForActiveAccount } from "../db/index"; import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import * as databaseUtil from "../db/databaseUtil";
import { createInviteJwt, getHeaders } from "../libs/endorserServer"; import { createInviteJwt, getHeaders } from "../libs/endorserServer";
import { PlatformServiceFactory } from "../services/PlatformServiceFactory";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
interface Invite { interface Invite {
inviteIdentifier: string; inviteIdentifier: string;
expiresAt: string; expiresAt: string;
@ -168,8 +176,11 @@ export default class InviteOneView extends Vue {
async mounted() { async mounted() {
try { try {
let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
await db.open(); await db.open();
const settings = await retrieveSettingsForActiveAccount(); settings = await retrieveSettingsForActiveAccount();
}
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
this.isRegistered = !!settings.isRegistered; this.isRegistered = !!settings.isRegistered;
@ -181,7 +192,16 @@ export default class InviteOneView extends Vue {
); );
this.invites = response.data.data; this.invites = response.data.data;
const baseContacts: Contact[] = await db.contacts.toArray(); const platformService = PlatformServiceFactory.getInstance();
const queryResult = await platformService.dbQuery(
"SELECT * FROM contacts",
);
let baseContacts = databaseUtil.mapQueryResultToValues(
queryResult,
) as unknown as Contact[];
if (USE_DEXIE_DB) {
baseContacts = await db.contacts.toArray();
}
for (const invite of this.invites) { for (const invite of this.invites) {
const contact = baseContacts.find( const contact = baseContacts.find(
(contact) => contact.did === invite.redeemedBy, (contact) => contact.did === invite.redeemedBy,
@ -328,18 +348,27 @@ export default class InviteOneView extends Vue {
); );
} }
addNewContact(did: string, notes: string) { async addNewContact(did: string, notes: string) {
(this.$refs.contactNameDialog as ContactNameDialog).open( (this.$refs.contactNameDialog as ContactNameDialog).open(
"To Whom Did You Send The Invite?", "To Whom Did You Send The Invite?",
"Their name will be added to your contact list.", "Their name will be added to your contact list.",
(name) => { async (name) => {
// the person obviously registered themselves and this user already granted visibility, so we just add them // the person obviously registered themselves and this user already granted visibility, so we just add them
const contact = { const contact = {
did: did, did: did,
name: name, name: name,
registered: true, registered: true,
}; };
db.contacts.add(contact); const platformService = PlatformServiceFactory.getInstance();
const columns = Object.keys(contact);
const values = Object.values(contact);
const placeholders = values.map(() => "?").join(", ");
const sql = `INSERT INTO contacts (${columns.join(", ")}) VALUES (${placeholders})`;
await platformService.dbExec(sql, values);
if (USE_DEXIE_DB) {
await db.contacts.add(contact);
}
this.contactsRedeemed[did] = contact; this.contactsRedeemed[did] = contact;
this.$notify( this.$notify(
{ {

17
src/views/LogView.vue

@ -55,6 +55,9 @@ import TopMessage from "../components/TopMessage.vue";
import { db } from "../db/index"; import { db } from "../db/index";
import { Log } from "../db/tables/logs"; import { Log } from "../db/tables/logs";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "../services/PlatformServiceFactory";
import { USE_DEXIE_DB } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
@Component({ @Component({
components: { components: {
@ -76,9 +79,19 @@ export default class LogView extends Vue {
async loadLogs() { async loadLogs() {
try { try {
this.error = null; // Clear any previous errors this.error = null; // Clear any previous errors
let allLogs: Log[] = [];
const platformService = PlatformServiceFactory.getInstance();
const queryResult = await platformService.dbQuery("SELECT * FROM logs");
allLogs = databaseUtil.mapQueryResultToValues(
queryResult,
) as unknown as Log[];
if (USE_DEXIE_DB) {
await db.open(); await db.open();
// Get all logs and sort by date in reverse chronological order allLogs = await db.logs.toArray();
const allLogs = await db.logs.toArray(); }
// Sort by date in reverse chronological order
this.logs = allLogs.sort((a, b) => { this.logs = allLogs.sort((a, b) => {
const dateA = new Date(a.date); const dateA = new Date(a.date);
const dateB = new Date(b.date); const dateB = new Date(b.date);

64
src/views/NewActivityView.vue

@ -153,7 +153,7 @@ import { Component, Vue } from "vue-facing-decorator";
import GiftedDialog from "../components/GiftedDialog.vue"; import GiftedDialog from "../components/GiftedDialog.vue";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import EntityIcon from "../components/EntityIcon.vue"; import EntityIcon from "../components/EntityIcon.vue";
import { NotificationIface } from "../constants/app"; import { NotificationIface, USE_DEXIE_DB } from "../constants/app";
import { import {
db, db,
retrieveSettingsForActiveAccount, retrieveSettingsForActiveAccount,
@ -169,6 +169,9 @@ import {
getNewOffersToUserProjects, getNewOffersToUserProjects,
} from "../libs/endorserServer"; } from "../libs/endorserServer";
import { retrieveAccountDids } from "../libs/util"; import { retrieveAccountDids } from "../libs/util";
import { PlatformServiceFactory } from "../services/PlatformServiceFactory";
import * as databaseUtil from "../db/databaseUtil";
import { logger } from "../utils/logger";
@Component({ @Component({
components: { GiftedDialog, QuickNav, EntityIcon }, components: { GiftedDialog, QuickNav, EntityIcon },
@ -194,14 +197,28 @@ export default class NewActivityView extends Vue {
async created() { async created() {
try { try {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.lastAckedOfferToUserJwtId = settings.lastAckedOfferToUserJwtId || ""; this.lastAckedOfferToUserJwtId = settings.lastAckedOfferToUserJwtId || "";
this.lastAckedOfferToUserProjectsJwtId = this.lastAckedOfferToUserProjectsJwtId =
settings.lastAckedOfferToUserProjectsJwtId || ""; settings.lastAckedOfferToUserProjectsJwtId || "";
const platformService = PlatformServiceFactory.getInstance();
const queryResult = await platformService.dbQuery(
"SELECT * FROM contacts",
);
this.allContacts = databaseUtil.mapQueryResultToValues(
queryResult,
) as unknown as Contact[];
if (USE_DEXIE_DB) {
await db.open();
this.allContacts = await db.contacts.toArray(); this.allContacts = await db.contacts.toArray();
}
this.allMyDids = await retrieveAccountDids(); this.allMyDids = await retrieveAccountDids();
const offersToUserData = await getNewOffersToUser( const offersToUserData = await getNewOffersToUser(
@ -240,9 +257,14 @@ export default class NewActivityView extends Vue {
async expandOffersToUserAndMarkRead() { async expandOffersToUserAndMarkRead() {
this.showOffersDetails = !this.showOffersDetails; this.showOffersDetails = !this.showOffersDetails;
if (this.showOffersDetails) { if (this.showOffersDetails) {
await databaseUtil.updateAccountSettings(this.activeDid, {
lastAckedOfferToUserJwtId: this.newOffersToUser[0].jwtId,
});
if (USE_DEXIE_DB) {
await updateAccountSettings(this.activeDid, { await updateAccountSettings(this.activeDid, {
lastAckedOfferToUserJwtId: this.newOffersToUser[0].jwtId, lastAckedOfferToUserJwtId: this.newOffersToUser[0].jwtId,
}); });
}
// note that we don't update this.lastAckedOfferToUserJwtId in case they // note that we don't update this.lastAckedOfferToUserJwtId in case they
// later choose the last one to keep the offers as new // later choose the last one to keep the offers as new
this.$notify( this.$notify(
@ -263,14 +285,24 @@ export default class NewActivityView extends Vue {
); );
if (index !== -1 && index < this.newOffersToUser.length - 1) { if (index !== -1 && index < this.newOffersToUser.length - 1) {
// Set to the next offer's jwtId // Set to the next offer's jwtId
await updateAccountSettings(this.activeDid, { await databaseUtil.updateAccountSettings(this.activeDid, {
lastAckedOfferToUserJwtId: this.newOffersToUser[index + 1].jwtId, lastAckedOfferToUserJwtId: this.newOffersToUser[index + 1].jwtId,
}); });
if (USE_DEXIE_DB) {
await db.settings.update(this.activeDid, {
lastAckedOfferToUserJwtId: this.newOffersToUser[index + 1].jwtId,
});
}
} else { } else {
// it's the last entry (or not found), so just keep it the same // it's the last entry (or not found), so just keep it the same
await updateAccountSettings(this.activeDid, { await databaseUtil.updateAccountSettings(this.activeDid, {
lastAckedOfferToUserJwtId: this.lastAckedOfferToUserJwtId, lastAckedOfferToUserJwtId: this.lastAckedOfferToUserJwtId,
}); });
if (USE_DEXIE_DB) {
await db.settings.update(this.activeDid, {
lastAckedOfferToUserJwtId: this.lastAckedOfferToUserJwtId,
});
}
} }
this.$notify( this.$notify(
{ {
@ -287,10 +319,16 @@ export default class NewActivityView extends Vue {
this.showOffersToUserProjectsDetails = this.showOffersToUserProjectsDetails =
!this.showOffersToUserProjectsDetails; !this.showOffersToUserProjectsDetails;
if (this.showOffersToUserProjectsDetails) { if (this.showOffersToUserProjectsDetails) {
await updateAccountSettings(this.activeDid, { await databaseUtil.updateAccountSettings(this.activeDid, {
lastAckedOfferToUserProjectsJwtId:
this.newOffersToUserProjects[0].jwtId,
});
if (USE_DEXIE_DB) {
await db.settings.update(this.activeDid, {
lastAckedOfferToUserProjectsJwtId: lastAckedOfferToUserProjectsJwtId:
this.newOffersToUserProjects[0].jwtId, this.newOffersToUserProjects[0].jwtId,
}); });
}
// note that we don't update this.lastAckedOfferToUserProjectsJwtId in case // note that we don't update this.lastAckedOfferToUserProjectsJwtId in case
// they later choose the last one to keep the offers as new // they later choose the last one to keep the offers as new
this.$notify( this.$notify(
@ -311,16 +349,28 @@ export default class NewActivityView extends Vue {
); );
if (index !== -1 && index < this.newOffersToUserProjects.length - 1) { if (index !== -1 && index < this.newOffersToUserProjects.length - 1) {
// Set to the next offer's jwtId // Set to the next offer's jwtId
await updateAccountSettings(this.activeDid, { await databaseUtil.updateAccountSettings(this.activeDid, {
lastAckedOfferToUserProjectsJwtId: lastAckedOfferToUserProjectsJwtId:
this.newOffersToUserProjects[index + 1].jwtId, this.newOffersToUserProjects[index + 1].jwtId,
}); });
if (USE_DEXIE_DB) {
await db.settings.update(this.activeDid, {
lastAckedOfferToUserProjectsJwtId:
this.newOffersToUserProjects[index + 1].jwtId,
});
}
} else { } else {
// it's the last entry (or not found), so just keep it the same // it's the last entry (or not found), so just keep it the same
await updateAccountSettings(this.activeDid, { await databaseUtil.updateAccountSettings(this.activeDid, {
lastAckedOfferToUserProjectsJwtId: lastAckedOfferToUserProjectsJwtId:
this.lastAckedOfferToUserProjectsJwtId, this.lastAckedOfferToUserProjectsJwtId,
}); });
if (USE_DEXIE_DB) {
await db.settings.update(this.activeDid, {
lastAckedOfferToUserProjectsJwtId:
this.lastAckedOfferToUserProjectsJwtId,
});
}
} }
this.$notify( this.$notify(
{ {

13
src/views/NewEditAccountView.vue

@ -47,8 +47,10 @@
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import { Router } from "vue-router"; import { Router } from "vue-router";
import { USE_DEXIE_DB } from "@/constants/app";
import { db, retrieveSettingsForActiveAccount } from "../db/index"; import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { MASTER_SETTINGS_KEY } from "../db/tables/settings"; import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
import * as databaseUtil from "../db/databaseUtil";
@Component({ @Component({
components: {}, components: {},
@ -60,17 +62,26 @@ export default class NewEditAccountView extends Vue {
// 'created' hook runs when the Vue instance is first created // 'created' hook runs when the Vue instance is first created
async created() { async created() {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.givenName = this.givenName =
(settings.firstName || "") + (settings.firstName || "") +
(settings.lastName ? ` ${settings.lastName}` : ""); // deprecated, pre v 0.1.3 (settings.lastName ? ` ${settings.lastName}` : ""); // deprecated, pre v 0.1.3
} }
async onClickSaveChanges() { async onClickSaveChanges() {
await databaseUtil.updateDefaultSettings({
firstName: this.givenName,
lastName: "", // deprecated, pre v 0.1.3
});
if (USE_DEXIE_DB) {
await db.settings.update(MASTER_SETTINGS_KEY, { await db.settings.update(MASTER_SETTINGS_KEY, {
firstName: this.givenName, firstName: this.givenName,
lastName: "", // deprecated, pre v 0.1.3 lastName: "", // deprecated, pre v 0.1.3
}); });
}
this.$router.back(); this.$router.back();
} }

12
src/views/NewEditProjectView.vue

@ -237,7 +237,9 @@ import {
DEFAULT_IMAGE_API_SERVER, DEFAULT_IMAGE_API_SERVER,
DEFAULT_PARTNER_API_SERVER, DEFAULT_PARTNER_API_SERVER,
NotificationIface, NotificationIface,
USE_DEXIE_DB,
} from "../constants/app"; } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../db/index"; import { retrieveSettingsForActiveAccount } from "../db/index";
import { PlanVerifiableCredential } from "../interfaces"; import { PlanVerifiableCredential } from "../interfaces";
import { import {
@ -303,7 +305,10 @@ export default class NewEditProjectView extends Vue {
async mounted() { async mounted() {
this.numAccounts = await retrieveAccountCount(); this.numAccounts = await retrieveAccountCount();
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
this.showGeneralAdvanced = !!settings.showGeneralAdvanced; this.showGeneralAdvanced = !!settings.showGeneralAdvanced;
@ -702,7 +707,10 @@ export default class NewEditProjectView extends Vue {
) { ) {
try { try {
let partnerServer = DEFAULT_PARTNER_API_SERVER; let partnerServer = DEFAULT_PARTNER_API_SERVER;
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
if (settings.partnerApiServer) { if (settings.partnerApiServer) {
partnerServer = settings.partnerApiServer; partnerServer = settings.partnerApiServer;
} }

24
src/views/OfferDetailsView.vue

@ -180,7 +180,7 @@ import { RouteLocationNormalizedLoaded, Router } from "vue-router";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import TopMessage from "../components/TopMessage.vue"; import TopMessage from "../components/TopMessage.vue";
import { NotificationIface } from "../constants/app"; import { NotificationIface, USE_DEXIE_DB } from "../constants/app";
import { db, retrieveSettingsForActiveAccount } from "../db/index"; import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { GenericCredWrapper, OfferVerifiableCredential } from "../interfaces"; import { GenericCredWrapper, OfferVerifiableCredential } from "../interfaces";
import { import {
@ -193,6 +193,10 @@ import {
import * as libsUtil from "../libs/util"; import * as libsUtil from "../libs/util";
import { retrieveAccountDids } from "../libs/util"; import { retrieveAccountDids } from "../libs/util";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { Contact } from "@/db/tables/contacts";
import * as databaseUtil from "../db/databaseUtil";
/** /**
* Offer Details View Component * Offer Details View Component
* @author Matthew Raymer * @author Matthew Raymer
@ -398,7 +402,10 @@ export default class OfferDetailsView extends Vue {
* @throws Will not throw but logs errors * @throws Will not throw but logs errors
*/ */
private async loadAccountSettings() { private async loadAccountSettings() {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.apiServer = settings.apiServer ?? ""; this.apiServer = settings.apiServer ?? "";
this.activeDid = settings.activeDid ?? ""; this.activeDid = settings.activeDid ?? "";
this.showGeneralAdvanced = settings.showGeneralAdvanced ?? false; this.showGeneralAdvanced = settings.showGeneralAdvanced ?? false;
@ -409,7 +416,18 @@ export default class OfferDetailsView extends Vue {
*/ */
private async loadRecipientInfo() { private async loadRecipientInfo() {
if (this.recipientDid && !this.recipientName) { if (this.recipientDid && !this.recipientName) {
const allContacts = await db.contacts.toArray(); let allContacts: Contact[] = [];
const platformService = PlatformServiceFactory.getInstance();
const queryResult = await platformService.dbQuery(
"SELECT * FROM contacts",
);
allContacts = databaseUtil.mapQueryResultToValues(
queryResult,
) as unknown as Contact[];
if (USE_DEXIE_DB) {
await db.open();
allContacts = await db.contacts.toArray();
}
const allMyDids = await retrieveAccountDids(); const allMyDids = await retrieveAccountDids();
this.recipientName = didInfo( this.recipientName = didInfo(
this.recipientDid, this.recipientDid,

10
src/views/OnboardMeetingListView.vue

@ -89,13 +89,16 @@ import { Router } from "vue-router";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import TopMessage from "../components/TopMessage.vue"; import TopMessage from "../components/TopMessage.vue";
import { logConsoleAndDb, retrieveSettingsForActiveAccount } from "../db/index"; import * as databaseUtil from "../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../db/index";
import { logConsoleAndDb } from "../db/databaseUtil";
import { import {
errorStringForLog, errorStringForLog,
getHeaders, getHeaders,
serverMessageForUser, serverMessageForUser,
} from "../libs/endorserServer"; } from "../libs/endorserServer";
import { encryptMessage } from "../libs/crypto"; import { encryptMessage } from "../libs/crypto";
import { USE_DEXIE_DB } from "@/constants/app";
interface Meeting { interface Meeting {
name: string; name: string;
@ -134,7 +137,10 @@ export default class OnboardMeetingListView extends Vue {
showPasswordDialog = false; showPasswordDialog = false;
async created() { async created() {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
this.firstName = settings.firstName || ""; this.firstName = settings.firstName || "";

10
src/views/OnboardMeetingMembersView.vue

@ -45,7 +45,9 @@ import QuickNav from "../components/QuickNav.vue";
import TopMessage from "../components/TopMessage.vue"; import TopMessage from "../components/TopMessage.vue";
import MembersList from "../components/MembersList.vue"; import MembersList from "../components/MembersList.vue";
import UserNameDialog from "../components/UserNameDialog.vue"; import UserNameDialog from "../components/UserNameDialog.vue";
import { logConsoleAndDb, retrieveSettingsForActiveAccount } from "../db/index"; import * as databaseUtil from "../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../db/index";
import { logConsoleAndDb } from "../db/databaseUtil";
import { encryptMessage } from "../libs/crypto"; import { encryptMessage } from "../libs/crypto";
import { import {
errorStringForLog, errorStringForLog,
@ -53,6 +55,7 @@ import {
serverMessageForUser, serverMessageForUser,
} from "../libs/endorserServer"; } from "../libs/endorserServer";
import { generateSaveAndActivateIdentity } from "../libs/util"; import { generateSaveAndActivateIdentity } from "../libs/util";
import { USE_DEXIE_DB } from "@/constants/app";
@Component({ @Component({
components: { components: {
@ -91,7 +94,10 @@ export default class OnboardMeetingMembersView extends Vue {
this.errorMessage = "The password is missing. Go back and try again."; this.errorMessage = "The password is missing. Go back and try again.";
return; return;
} }
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
this.firstName = settings.firstName || ""; this.firstName = settings.firstName || "";

10
src/views/OnboardMeetingSetupView.vue

@ -232,7 +232,9 @@ import { Component, Vue } from "vue-facing-decorator";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import TopMessage from "../components/TopMessage.vue"; import TopMessage from "../components/TopMessage.vue";
import MembersList from "../components/MembersList.vue"; import MembersList from "../components/MembersList.vue";
import { logConsoleAndDb, retrieveSettingsForActiveAccount } from "../db/index"; import * as databaseUtil from "../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../db/index";
import { logConsoleAndDb } from "../db/databaseUtil";
import { import {
errorStringForLog, errorStringForLog,
getHeaders, getHeaders,
@ -240,6 +242,7 @@ import {
} from "../libs/endorserServer"; } from "../libs/endorserServer";
import { encryptMessage } from "../libs/crypto"; import { encryptMessage } from "../libs/crypto";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { USE_DEXIE_DB } from "@/constants/app";
interface ServerMeeting { interface ServerMeeting {
groupId: number; // from the server groupId: number; // from the server
name: string; // from the server name: string; // from the server
@ -284,7 +287,10 @@ export default class OnboardMeetingView extends Vue {
} }
async created() { async created() {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
this.fullName = settings.firstName || ""; this.fullName = settings.firstName || "";

17
src/views/ProjectViewView.vue

@ -624,7 +624,8 @@ import TopMessage from "../components/TopMessage.vue";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import EntityIcon from "../components/EntityIcon.vue"; import EntityIcon from "../components/EntityIcon.vue";
import ProjectIcon from "../components/ProjectIcon.vue"; import ProjectIcon from "../components/ProjectIcon.vue";
import { NotificationIface } from "../constants/app"; import { NotificationIface, USE_DEXIE_DB } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { import {
db, db,
logConsoleAndDb, logConsoleAndDb,
@ -636,6 +637,7 @@ import * as serverUtil from "../libs/endorserServer";
import { retrieveAccountDids } from "../libs/util"; import { retrieveAccountDids } from "../libs/util";
import HiddenDidDialog from "../components/HiddenDidDialog.vue"; import HiddenDidDialog from "../components/HiddenDidDialog.vue";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
/** /**
* Project View Component * Project View Component
* @author Matthew Raymer * @author Matthew Raymer
@ -778,10 +780,21 @@ export default class ProjectViewView extends Vue {
* @emits Notification on profile loading errors * @emits Notification on profile loading errors
*/ */
async created() { async created() {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
const platformService = PlatformServiceFactory.getInstance();
const queryResult = await platformService.dbQuery("SELECT * FROM contacts");
this.allContacts = databaseUtil.mapQueryResultToValues(
queryResult,
) as unknown as Contact[];
if (USE_DEXIE_DB) {
await db.open();
this.allContacts = await db.contacts.toArray(); this.allContacts = await db.contacts.toArray();
}
this.isRegistered = !!settings.isRegistered; this.isRegistered = !!settings.isRegistered;
try { try {

19
src/views/ProjectsView.vue

@ -269,7 +269,7 @@ import { AxiosRequestConfig } from "axios";
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import { Router } from "vue-router"; import { Router } from "vue-router";
import { NotificationIface } from "../constants/app"; import { NotificationIface, USE_DEXIE_DB } from "../constants/app";
import { db, retrieveSettingsForActiveAccount } from "../db/index"; import { db, retrieveSettingsForActiveAccount } from "../db/index";
import EntityIcon from "../components/EntityIcon.vue"; import EntityIcon from "../components/EntityIcon.vue";
import InfiniteScroll from "../components/InfiniteScroll.vue"; import InfiniteScroll from "../components/InfiniteScroll.vue";
@ -278,12 +278,14 @@ import OnboardingDialog from "../components/OnboardingDialog.vue";
import ProjectIcon from "../components/ProjectIcon.vue"; import ProjectIcon from "../components/ProjectIcon.vue";
import TopMessage from "../components/TopMessage.vue"; import TopMessage from "../components/TopMessage.vue";
import UserNameDialog from "../components/UserNameDialog.vue"; import UserNameDialog from "../components/UserNameDialog.vue";
import * as databaseUtil from "../db/databaseUtil";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import { didInfo, getHeaders, getPlanFromCache } from "../libs/endorserServer"; import { didInfo, getHeaders, getPlanFromCache } from "../libs/endorserServer";
import { OfferSummaryRecord, PlanData } from "../interfaces/records"; import { OfferSummaryRecord, PlanData } from "../interfaces/records";
import * as libsUtil from "../libs/util"; import * as libsUtil from "../libs/util";
import { OnboardPage } from "../libs/util"; import { OnboardPage } from "../libs/util";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
@Component({ @Component({
components: { components: {
EntityIcon, EntityIcon,
@ -324,13 +326,26 @@ export default class ProjectsView extends Vue {
async mounted() { async mounted() {
try { try {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
this.isRegistered = !!settings.isRegistered; this.isRegistered = !!settings.isRegistered;
this.givenName = settings.firstName || ""; this.givenName = settings.firstName || "";
const platformService = PlatformServiceFactory.getInstance();
const queryResult = await platformService.dbQuery(
"SELECT * FROM contacts",
);
this.allContacts = databaseUtil.mapQueryResultToValues(
queryResult,
) as unknown as Contact[];
if (USE_DEXIE_DB) {
await db.open();
this.allContacts = await db.contacts.toArray(); this.allContacts = await db.contacts.toArray();
}
this.allMyDids = await libsUtil.retrieveAccountDids(); this.allMyDids = await libsUtil.retrieveAccountDids();

8
src/views/QuickActionBvcBeginView.vue

@ -72,7 +72,8 @@ import { Component, Vue } from "vue-facing-decorator";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import TopMessage from "../components/TopMessage.vue"; import TopMessage from "../components/TopMessage.vue";
import { NotificationIface } from "../constants/app"; import { NotificationIface, USE_DEXIE_DB } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../db/index"; import { retrieveSettingsForActiveAccount } from "../db/index";
import { import {
BVC_MEETUPS_PROJECT_CLAIM_ID, BVC_MEETUPS_PROJECT_CLAIM_ID,
@ -117,7 +118,10 @@ export default class QuickActionBvcBeginView extends Vue {
} }
async record() { async record() {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
const activeDid = settings.activeDid || ""; const activeDid = settings.activeDid || "";
const apiServer = settings.apiServer || ""; const apiServer = settings.apiServer || "";

29
src/views/QuickActionBvcEndView.vue

@ -144,7 +144,8 @@ import { Router } from "vue-router";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import TopMessage from "../components/TopMessage.vue"; import TopMessage from "../components/TopMessage.vue";
import { NotificationIface } from "../constants/app"; import { NotificationIface, USE_DEXIE_DB } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { import {
accountsDBPromise, accountsDBPromise,
db, db,
@ -165,6 +166,7 @@ import {
getHeaders, getHeaders,
} from "../libs/endorserServer"; } from "../libs/endorserServer";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
@Component({ @Component({
methods: { claimSpecialDescription }, methods: { claimSpecialDescription },
components: { components: {
@ -191,10 +193,24 @@ export default class QuickActionBvcBeginView extends Vue {
async created() { async created() {
this.loadingConfirms = true; this.loadingConfirms = true;
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
const platformService = PlatformServiceFactory.getInstance();
const contactQueryResult = await platformService.dbQuery(
"SELECT * FROM contacts",
);
this.allContacts = databaseUtil.mapQueryResultToValues(
contactQueryResult,
) as unknown as Contact[];
if (USE_DEXIE_DB) {
await db.open();
this.allContacts = await db.contacts.toArray(); this.allContacts = await db.contacts.toArray();
}
let currentOrPreviousSat = DateTime.now().setZone("America/Denver"); let currentOrPreviousSat = DateTime.now().setZone("America/Denver");
if (currentOrPreviousSat.weekday < 6) { if (currentOrPreviousSat.weekday < 6) {
@ -213,10 +229,19 @@ export default class QuickActionBvcBeginView extends Vue {
suppressMilliseconds: true, suppressMilliseconds: true,
}) || ""; }) || "";
const queryResult = await platformService.dbQuery(
"SELECT did FROM accounts",
);
this.allMyDids =
databaseUtil
.mapQueryResultToValues(queryResult)
?.map((row) => row[0] as string) || [];
if (USE_DEXIE_DB) {
const accountsDB = await accountsDBPromise; const accountsDB = await accountsDBPromise;
await accountsDB.open(); await accountsDB.open();
const allAccounts = await accountsDB.accounts.toArray(); const allAccounts = await accountsDB.accounts.toArray();
this.allMyDids = allAccounts.map((acc) => acc.did); this.allMyDids = allAccounts.map((acc) => acc.did);
}
const headers = await getHeaders(this.activeDid); const headers = await getHeaders(this.activeDid);
try { try {
const response = await fetch( const response = await fetch(

19
src/views/RecentOffersToUserProjectsView.vue

@ -83,7 +83,8 @@ import EntityIcon from "../components/EntityIcon.vue";
import GiftedDialog from "../components/GiftedDialog.vue"; import GiftedDialog from "../components/GiftedDialog.vue";
import InfiniteScroll from "../components/InfiniteScroll.vue"; import InfiniteScroll from "../components/InfiniteScroll.vue";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import { NotificationIface } from "../constants/app"; import { NotificationIface, USE_DEXIE_DB } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { db, retrieveSettingsForActiveAccount } from "../db/index"; import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import { Router } from "vue-router"; import { Router } from "vue-router";
@ -95,6 +96,7 @@ import {
} from "../libs/endorserServer"; } from "../libs/endorserServer";
import { retrieveAccountDids } from "../libs/util"; import { retrieveAccountDids } from "../libs/util";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
@Component({ @Component({
components: { EntityIcon, GiftedDialog, InfiniteScroll, QuickNav }, components: { EntityIcon, GiftedDialog, InfiniteScroll, QuickNav },
}) })
@ -116,13 +118,26 @@ export default class RecentOffersToUserView extends Vue {
async created() { async created() {
try { try {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.lastAckedOfferToUserProjectsJwtId = this.lastAckedOfferToUserProjectsJwtId =
settings.lastAckedOfferToUserProjectsJwtId || ""; settings.lastAckedOfferToUserProjectsJwtId || "";
const contactQueryResult =
await PlatformServiceFactory.getInstance().dbQuery(
"SELECT * FROM contacts",
);
this.allContacts = databaseUtil.mapQueryResultToValues(
contactQueryResult,
) as unknown as Contact[];
if (USE_DEXIE_DB) {
await db.open();
this.allContacts = await db.contacts.toArray(); this.allContacts = await db.contacts.toArray();
}
this.allMyDids = await retrieveAccountDids(); this.allMyDids = await retrieveAccountDids();

18
src/views/RecentOffersToUserView.vue

@ -76,7 +76,8 @@ import GiftedDialog from "../components/GiftedDialog.vue";
import EntityIcon from "../components/EntityIcon.vue"; import EntityIcon from "../components/EntityIcon.vue";
import InfiniteScroll from "../components/InfiniteScroll.vue"; import InfiniteScroll from "../components/InfiniteScroll.vue";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import { NotificationIface } from "../constants/app"; import { NotificationIface, USE_DEXIE_DB } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { db, retrieveSettingsForActiveAccount } from "../db/index"; import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import { OfferSummaryRecord } from "../interfaces"; import { OfferSummaryRecord } from "../interfaces";
@ -87,6 +88,7 @@ import {
} from "../libs/endorserServer"; } from "../libs/endorserServer";
import { retrieveAccountDids } from "../libs/util"; import { retrieveAccountDids } from "../libs/util";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
@Component({ @Component({
components: { EntityIcon, GiftedDialog, InfiniteScroll, QuickNav }, components: { EntityIcon, GiftedDialog, InfiniteScroll, QuickNav },
}) })
@ -108,12 +110,24 @@ export default class RecentOffersToUserView extends Vue {
async created() { async created() {
try { try {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.lastAckedOfferToUserJwtId = settings.lastAckedOfferToUserJwtId || ""; this.lastAckedOfferToUserJwtId = settings.lastAckedOfferToUserJwtId || "";
const contactQueryResult =
await PlatformServiceFactory.getInstance().dbQuery(
"SELECT * FROM contacts",
);
this.allContacts = databaseUtil.mapQueryResultToValues(
contactQueryResult,
) as unknown as Contact[];
if (USE_DEXIE_DB) {
this.allContacts = await db.contacts.toArray(); this.allContacts = await db.contacts.toArray();
}
this.allMyDids = await retrieveAccountDids(); this.allMyDids = await retrieveAccountDids();

21
src/views/SearchAreaView.vue

@ -112,10 +112,12 @@ import {
import { Router } from "vue-router"; import { Router } from "vue-router";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import { NotificationIface } from "../constants/app"; import { NotificationIface, USE_DEXIE_DB } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { db, retrieveSettingsForActiveAccount } from "../db/index"; import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { BoundingBox, MASTER_SETTINGS_KEY } from "../db/tables/settings"; import { BoundingBox, MASTER_SETTINGS_KEY } from "../db/tables/settings";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
const DEFAULT_LAT_LONG_DIFF = 0.01; const DEFAULT_LAT_LONG_DIFF = 0.01;
const WORLD_ZOOM = 2; const WORLD_ZOOM = 2;
const DEFAULT_ZOOM = 2; const DEFAULT_ZOOM = 2;
@ -147,7 +149,10 @@ export default class SearchAreaView extends Vue {
searchBox: { name: string; bbox: BoundingBox } | null = null; searchBox: { name: string; bbox: BoundingBox } | null = null;
async mounted() { async mounted() {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.searchBox = settings.searchBoxes?.[0] || null; this.searchBox = settings.searchBoxes?.[0] || null;
this.resetLatLong(); this.resetLatLong();
} }
@ -204,10 +209,15 @@ export default class SearchAreaView extends Vue {
westLong: this.localCenterLong - this.localLongDiff, westLong: this.localCenterLong - this.localLongDiff,
}, },
}; };
const searchBoxes = JSON.stringify([newSearchBox]);
// @ts-expect-error - the DB requires searchBoxes to be a string
databaseUtil.updateDefaultSettings({ searchBoxes });
if (USE_DEXIE_DB) {
await db.open(); await db.open();
await db.settings.update(MASTER_SETTINGS_KEY, { await db.settings.update(MASTER_SETTINGS_KEY, {
searchBoxes: [newSearchBox], searchBoxes: [newSearchBox],
}); });
}
this.searchBox = newSearchBox; this.searchBox = newSearchBox;
this.isChoosingSearchBox = false; this.isChoosingSearchBox = false;
@ -251,11 +261,18 @@ export default class SearchAreaView extends Vue {
public async forgetSearchBox() { public async forgetSearchBox() {
try { try {
// @ts-expect-error - the DB requires searchBoxes to be a string
await databaseUtil.updateDefaultSettings({
searchBoxes: "[]",
filterFeedByNearby: false,
});
if (USE_DEXIE_DB) {
await db.open(); await db.open();
await db.settings.update(MASTER_SETTINGS_KEY, { await db.settings.update(MASTER_SETTINGS_KEY, {
searchBoxes: [], searchBoxes: [],
filterFeedByNearby: false, filterFeedByNearby: false,
}); });
}
this.searchBox = null; this.searchBox = null;
this.localCenterLat = 0; this.localCenterLat = 0;
this.localCenterLong = 0; this.localCenterLong = 0;

22
src/views/ShareMyContactInfoView.vue

@ -46,11 +46,14 @@ import { Router } from "vue-router";
import { useClipboard } from "@vueuse/core"; import { useClipboard } from "@vueuse/core";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import TopMessage from "../components/TopMessage.vue"; import TopMessage from "../components/TopMessage.vue";
import { NotificationIface, APP_SERVER } from "../constants/app"; import { NotificationIface, APP_SERVER, USE_DEXIE_DB } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { db, retrieveSettingsForActiveAccount } from "../db/index"; import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { retrieveAccountMetadata } from "../libs/util"; import { retrieveAccountMetadata } from "../libs/util";
import { generateEndorserJwtUrlForAccount } from "../libs/endorserServer"; import { generateEndorserJwtUrlForAccount } from "../libs/endorserServer";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
@Component({ @Component({
components: { QuickNav, TopMessage }, components: { QuickNav, TopMessage },
}) })
@ -63,7 +66,10 @@ export default class ShareMyContactInfoView extends Vue {
} }
async onClickShare() { async onClickShare() {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
const activeDid = settings.activeDid || ""; const activeDid = settings.activeDid || "";
const givenName = settings.firstName || ""; const givenName = settings.firstName || "";
const isRegistered = !!settings.isRegistered; const isRegistered = !!settings.isRegistered;
@ -71,7 +77,17 @@ export default class ShareMyContactInfoView extends Vue {
const account = await retrieveAccountMetadata(activeDid); const account = await retrieveAccountMetadata(activeDid);
const numContacts = await db.contacts.count(); const platformService = PlatformServiceFactory.getInstance();
const contactQueryResult = await platformService.dbQuery(
"SELECT COUNT(*) FROM contacts",
);
let numContacts =
(databaseUtil.mapQueryResultToValues(
contactQueryResult,
)?.[0]?.[0] as number) || 0;
if (USE_DEXIE_DB) {
numContacts = await db.contacts.count();
}
if (account) { if (account) {
const message = await generateEndorserJwtUrlForAccount( const message = await generateEndorserJwtUrlForAccount(

29
src/views/SharedPhotoView.vue

@ -78,12 +78,16 @@ import {
DEFAULT_IMAGE_API_SERVER, DEFAULT_IMAGE_API_SERVER,
IMAGE_TYPE_PROFILE, IMAGE_TYPE_PROFILE,
NotificationIface, NotificationIface,
USE_DEXIE_DB,
} from "../constants/app"; } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { db, retrieveSettingsForActiveAccount } from "../db/index"; import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { MASTER_SETTINGS_KEY } from "../db/tables/settings"; import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
import { accessToken } from "../libs/crypto"; import { accessToken } from "../libs/crypto";
import { base64ToBlob, SHARED_PHOTO_BASE64_KEY } from "../libs/util"; import { base64ToBlob, SHARED_PHOTO_BASE64_KEY } from "../libs/util";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { Temp } from "@/db/tables/temp";
@Component({ components: { PhotoDialog, QuickNav } }) @Component({ components: { PhotoDialog, QuickNav } })
export default class SharedPhotoView extends Vue { export default class SharedPhotoView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
@ -100,16 +104,32 @@ export default class SharedPhotoView extends Vue {
// 'created' hook runs when the Vue instance is first created // 'created' hook runs when the Vue instance is first created
async mounted() { async mounted() {
try { try {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.activeDid = settings.activeDid; this.activeDid = settings.activeDid;
const temp = await db.temp.get(SHARED_PHOTO_BASE64_KEY); const platformService = PlatformServiceFactory.getInstance();
const tempQuery = await platformService.dbQuery(
"SELECT * FROM temp WHERE id = ?",
[SHARED_PHOTO_BASE64_KEY],
);
let temp = databaseUtil.mapQueryResultToValues(tempQuery)?.[0] as Temp;
if (USE_DEXIE_DB) {
temp = (await db.temp.get(SHARED_PHOTO_BASE64_KEY)) as unknown as Temp;
}
const imageB64 = temp?.blobB64 as string; const imageB64 = temp?.blobB64 as string;
if (temp) { if (temp) {
this.imageBlob = base64ToBlob(imageB64); this.imageBlob = base64ToBlob(imageB64);
// clear the temp image // clear the temp image
db.temp.delete(SHARED_PHOTO_BASE64_KEY); await platformService.dbExec("DELETE FROM temp WHERE id = ?", [
SHARED_PHOTO_BASE64_KEY,
]);
if (USE_DEXIE_DB) {
await db.temp.delete(SHARED_PHOTO_BASE64_KEY);
}
this.imageFileName = this.$route.query["fileName"] as string; this.imageFileName = this.$route.query["fileName"] as string;
} else { } else {
@ -150,9 +170,12 @@ export default class SharedPhotoView extends Vue {
recordProfile() { recordProfile() {
(this.$refs.photoDialog as PhotoDialog).open( (this.$refs.photoDialog as PhotoDialog).open(
async (imgUrl) => { async (imgUrl) => {
databaseUtil.updateDefaultSettings({ profileImageUrl: imgUrl });
if (USE_DEXIE_DB) {
await db.settings.update(MASTER_SETTINGS_KEY, { await db.settings.update(MASTER_SETTINGS_KEY, {
profileImageUrl: imgUrl, profileImageUrl: imgUrl,
}); });
}
this.$router.push({ name: "account" }); this.$router.push({ name: "account" });
}, },
IMAGE_TYPE_PROFILE, IMAGE_TYPE_PROFILE,

8
src/views/StartView.vue

@ -91,7 +91,8 @@
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import { Router } from "vue-router"; import { Router } from "vue-router";
import { AppString, PASSKEYS_ENABLED } from "../constants/app"; import { AppString, PASSKEYS_ENABLED, USE_DEXIE_DB } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../db/index"; import { retrieveSettingsForActiveAccount } from "../db/index";
import { import {
registerSaveAndActivatePasskey, registerSaveAndActivatePasskey,
@ -109,7 +110,10 @@ export default class StartView extends Vue {
numAccounts = 0; numAccounts = 0;
async mounted() { async mounted() {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.givenName = settings.firstName || ""; this.givenName = settings.firstName || "";
this.numAccounts = await retrieveAccountCount(); this.numAccounts = await retrieveAccountCount();

56
src/views/TestView.vue

@ -167,11 +167,30 @@
<button <button
class="text-sm text-blue-600 hover:text-blue-800 underline" class="text-sm text-blue-600 hover:text-blue-800 underline"
@click=" @click="
sqlQuery = 'SELECT * FROM sqlite_master WHERE type=\'table\';' sqlQuery = 'SELECT * FROM sqlite_master WHERE type=\'table\';';
executeSql();
" "
> >
All Tables All Tables
</button> </button>
<button
class="text-sm text-blue-600 hover:text-blue-800 underline"
@click="
sqlQuery = 'SELECT * FROM accounts;';
executeSql();
"
>
Accounts
</button>
<button
class="text-sm text-blue-600 hover:text-blue-800 underline"
@click="
sqlQuery = 'SELECT * FROM settings;';
executeSql();
"
>
Settings
</button>
</div> </div>
<div> <div>
<textarea <textarea
@ -311,7 +330,8 @@ import { Component, Vue } from "vue-facing-decorator";
import { Router } from "vue-router"; import { Router } from "vue-router";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import { AppString, NotificationIface } from "../constants/app"; import { AppString, NotificationIface, USE_DEXIE_DB } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { db, retrieveSettingsForActiveAccount } from "../db/index"; import { db, retrieveSettingsForActiveAccount } from "../db/index";
import * as vcLib from "../libs/crypto/vc"; import * as vcLib from "../libs/crypto/vc";
import * as cryptoLib from "../libs/crypto"; import * as cryptoLib from "../libs/crypto";
@ -331,6 +351,7 @@ import {
} from "../libs/util"; } from "../libs/util";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory"; import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { Temp } from "@/db/tables/temp";
const inputFileNameRef = ref<Blob>(); const inputFileNameRef = ref<Blob>();
const TEST_PAYLOAD = { const TEST_PAYLOAD = {
@ -369,7 +390,10 @@ export default class Help extends Vue {
cryptoLib = cryptoLib; cryptoLib = cryptoLib;
async mounted() { async mounted() {
const settings = await retrieveSettingsForActiveAccount(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
if (USE_DEXIE_DB) {
settings = await retrieveSettingsForActiveAccount();
}
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.userName = settings.firstName; this.userName = settings.firstName;
@ -399,13 +423,37 @@ export default class Help extends Vue {
}); });
const blobB64 = await blobToBase64(blob); const blobB64 = await blobToBase64(blob);
this.fileName = (file as File).name; this.fileName = (file as File).name;
const temp = await db.temp.get(SHARED_PHOTO_BASE64_KEY);
const platformService = PlatformServiceFactory.getInstance();
const tempQuery = await platformService.dbQuery(
"SELECT * FROM temp WHERE id = ?",
[SHARED_PHOTO_BASE64_KEY],
);
let temp = databaseUtil.mapQueryResultToValues(
tempQuery,
)?.[0] as Temp;
if (temp) {
await platformService.dbExec(
"UPDATE temp SET blobB64 = ? WHERE id = ?",
[blobB64, SHARED_PHOTO_BASE64_KEY],
);
} else {
await platformService.dbExec(
"INSERT INTO temp (id, blobB64) VALUES (?, ?)",
[SHARED_PHOTO_BASE64_KEY, blobB64],
);
}
if (USE_DEXIE_DB) {
temp = (await db.temp.get(
SHARED_PHOTO_BASE64_KEY,
)) as unknown as Temp;
if (temp) { if (temp) {
await db.temp.update(SHARED_PHOTO_BASE64_KEY, { blobB64 }); await db.temp.update(SHARED_PHOTO_BASE64_KEY, { blobB64 });
} else { } else {
await db.temp.add({ id: SHARED_PHOTO_BASE64_KEY, blobB64 }); await db.temp.add({ id: SHARED_PHOTO_BASE64_KEY, blobB64 });
} }
} }
}
}; };
reader.readAsArrayBuffer(file as Blob); reader.readAsArrayBuffer(file as Blob);
} }

23
src/views/UserProfileView.vue

@ -102,13 +102,17 @@ import TopMessage from "../components/TopMessage.vue";
import { import {
DEFAULT_PARTNER_API_SERVER, DEFAULT_PARTNER_API_SERVER,
NotificationIface, NotificationIface,
USE_DEXIE_DB,
} from "../constants/app"; } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { db } from "../db/index"; import { db } from "../db/index";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import { didInfo, getHeaders } from "../libs/endorserServer"; import { didInfo, getHeaders } from "../libs/endorserServer";
import { UserProfile } from "../libs/partnerServer"; import { UserProfile } from "../libs/partnerServer";
import { retrieveAccountDids } from "../libs/util"; import { retrieveAccountDids } from "../libs/util";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { Settings } from "@/db/tables/settings";
@Component({ @Component({
components: { components: {
LMap, LMap,
@ -135,12 +139,29 @@ export default class UserProfileView extends Vue {
didInfo = didInfo; didInfo = didInfo;
async mounted() { async mounted() {
const settings = await db.settings.toArray(); const platformService = PlatformServiceFactory.getInstance();
const settingsQuery = await platformService.dbQuery(
"SELECT * FROM settings",
);
let settings = databaseUtil.mapQueryResultToValues(
settingsQuery,
) as Settings[];
if (USE_DEXIE_DB) {
settings = await db.settings.toArray();
}
this.activeDid = settings[0]?.activeDid || ""; this.activeDid = settings[0]?.activeDid || "";
this.partnerApiServer = this.partnerApiServer =
settings[0]?.partnerApiServer || this.partnerApiServer; settings[0]?.partnerApiServer || this.partnerApiServer;
const contactQuery = await platformService.dbQuery(
"SELECT * FROM contacts",
);
this.allContacts = databaseUtil.mapQueryResultToValues(
contactQuery,
) as unknown as Contact[];
if (USE_DEXIE_DB) {
this.allContacts = await db.contacts.toArray(); this.allContacts = await db.contacts.toArray();
}
this.allMyDids = await retrieveAccountDids(); this.allMyDids = await retrieveAccountDids();
await this.loadProfile(); await this.loadProfile();

Loading…
Cancel
Save