Browse Source

add SQL DB access to everywhere we are using the DB, up to the "C" files

pull/137/head
Trent Larson 2 weeks ago
parent
commit
7de4125eb7
  1. 49
      src/components/FeedFilters.vue
  2. 15
      src/components/GiftedDialog.vue
  3. 36
      src/components/GiftedPrompts.vue
  4. 33
      src/components/MembersList.vue
  5. 27
      src/components/OnboardingDialog.vue
  6. 22
      src/components/UserNameDialog.vue
  7. 2
      src/constants/app.ts
  8. 36
      src/db/databaseUtil.ts
  9. 5
      src/libs/util.ts
  10. 2
      src/main.web.ts
  11. 5
      src/services/PlatformService.ts
  12. 5
      src/services/platforms/WebPlatformService.ts
  13. 7
      src/views/AccountViewView.vue
  14. 18
      src/views/ClaimCertificateView.vue
  15. 18
      src/views/ClaimReportCertificateView.vue
  16. 16
      src/views/ClaimView.vue
  17. 16
      src/views/ConfirmGiftView.vue
  18. 17
      src/views/ContactAmountsView.vue
  19. 48
      src/views/ContactEditView.vue
  20. 24
      src/views/ContactGiftingView.vue
  21. 36
      src/views/ContactImportView.vue
  22. 37
      src/views/ContactQRScanFullView.vue
  23. 67
      src/views/ContactQRScanShowView.vue
  24. 89
      src/views/ContactsView.vue

49
src/components/FeedFilters.vue

@ -99,8 +99,11 @@ import {
LTileLayer, LTileLayer,
} from "@vue-leaflet/vue-leaflet"; } from "@vue-leaflet/vue-leaflet";
import { Router } from "vue-router"; import { Router } from "vue-router";
import { USE_DEXIE_DB } from "@/constants/app";
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";
@Component({ @Component({
components: { components: {
@ -144,9 +147,17 @@ export default class FeedFilters extends Vue {
async toggleNearby() { async toggleNearby() {
this.settingChanged = true; this.settingChanged = true;
this.isNearby = !this.isNearby; this.isNearby = !this.isNearby;
await db.settings.update(MASTER_SETTINGS_KEY, { const platformService = PlatformServiceFactory.getInstance();
filterFeedByNearby: this.isNearby, await platformService.dbExec(
}); `UPDATE settings SET filterFeedByNearby = ? WHERE id = ?`,
[this.isNearby, MASTER_SETTINGS_KEY],
);
if (USE_DEXIE_DB) {
await db.settings.update(MASTER_SETTINGS_KEY, {
filterFeedByNearby: this.isNearby,
});
}
} }
async clearAll() { async clearAll() {
@ -154,10 +165,18 @@ export default class FeedFilters extends Vue {
this.settingChanged = true; this.settingChanged = true;
} }
await db.settings.update(MASTER_SETTINGS_KEY, { const platformService = PlatformServiceFactory.getInstance();
filterFeedByNearby: false, await platformService.dbExec(
filterFeedByVisible: false, `UPDATE settings SET filterFeedByNearby = ? AND filterFeedByVisible = ? WHERE id = ?`,
}); [false, false, MASTER_SETTINGS_KEY],
);
if (USE_DEXIE_DB) {
await db.settings.update(MASTER_SETTINGS_KEY, {
filterFeedByNearby: false,
filterFeedByVisible: false,
});
}
this.hasVisibleDid = false; this.hasVisibleDid = false;
this.isNearby = false; this.isNearby = false;
@ -168,10 +187,18 @@ export default class FeedFilters extends Vue {
this.settingChanged = true; this.settingChanged = true;
} }
await db.settings.update(MASTER_SETTINGS_KEY, { const platformService = PlatformServiceFactory.getInstance();
filterFeedByNearby: true, await platformService.dbExec(
filterFeedByVisible: true, `UPDATE settings SET filterFeedByNearby = ? AND filterFeedByVisible = ? WHERE id = ?`,
}); [true, true, MASTER_SETTINGS_KEY],
);
if (USE_DEXIE_DB) {
await db.settings.update(MASTER_SETTINGS_KEY, {
filterFeedByNearby: true,
filterFeedByVisible: true,
});
}
this.hasVisibleDid = true; this.hasVisibleDid = true;
this.isNearby = true; this.isNearby = true;

15
src/components/GiftedDialog.vue

@ -89,7 +89,7 @@
<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 {
createAndSubmitGive, createAndSubmitGive,
didInfo, didInfo,
@ -98,8 +98,10 @@ import {
import * as libsUtil from "../libs/util"; import * as libsUtil from "../libs/util";
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 { 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
export default class GiftedDialog extends Vue { export default class GiftedDialog extends Vue {
@ -148,7 +150,16 @@ export default class GiftedDialog extends Vue {
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.allContacts = await db.contacts.toArray(); const platformService = PlatformServiceFactory.getInstance();
const result = await platformService.dbQuery(`SELECT * FROM contacts`);
if (result) {
this.allContacts = databaseUtil.mapQueryResultToValues(
result,
) as unknown as Contact[];
}
if (USE_DEXIE_DB) {
this.allContacts = await db.contacts.toArray();
}
this.allMyDids = await retrieveAccountDids(); this.allMyDids = await retrieveAccountDids();

36
src/components/GiftedPrompts.vue

@ -74,10 +74,12 @@
import { Vue, Component } from "vue-facing-decorator"; import { Vue, Component } 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 { db } from "../db/index"; import { db } from "../db/index";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import * as databaseUtil from "../db/databaseUtil";
import { GiverReceiverInputInfo } from "../libs/util"; import { GiverReceiverInputInfo } from "../libs/util";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
@Component @Component
export default class GivenPrompts extends Vue { export default class GivenPrompts extends Vue {
@ -127,8 +129,16 @@ export default class GivenPrompts extends Vue {
this.visible = true; this.visible = true;
this.callbackOnFullGiftInfo = callbackOnFullGiftInfo; this.callbackOnFullGiftInfo = callbackOnFullGiftInfo;
await db.open(); const platformService = PlatformServiceFactory.getInstance();
this.numContacts = await db.contacts.count(); const result = await platformService.dbQuery(
"SELECT COUNT(*) FROM contacts",
);
if (result) {
this.numContacts = result.values[0][0] as number;
}
if (USE_DEXIE_DB) {
this.numContacts = await db.contacts.count();
}
this.shownContactDbIndices = new Array<boolean>(this.numContacts); // all undefined to start this.shownContactDbIndices = new Array<boolean>(this.numContacts); // all undefined to start
} }
@ -229,10 +239,22 @@ export default class GivenPrompts extends Vue {
this.nextIdeaPastContacts(); this.nextIdeaPastContacts();
} else { } else {
// get the contact at that offset // get the contact at that offset
await db.open(); const platformService = PlatformServiceFactory.getInstance();
this.currentContact = await db.contacts const result = await platformService.dbQuery(
.offset(someContactDbIndex) "SELECT * FROM contacts LIMIT 1 OFFSET ?",
.first(); [someContactDbIndex],
);
if (result) {
this.currentContact = databaseUtil.mapQueryResultToValues(result)[
someContactDbIndex
] as unknown as Contact;
}
if (USE_DEXIE_DB) {
await db.open();
this.currentContact = await db.contacts
.offset(someContactDbIndex)
.first();
}
this.shownContactDbIndices[someContactDbIndex] = true; this.shownContactDbIndices[someContactDbIndex] = true;
} }
} }

33
src/components/MembersList.vue

@ -172,8 +172,10 @@ import {
} from "../libs/endorserServer"; } from "../libs/endorserServer";
import { decryptMessage } from "../libs/crypto"; import { decryptMessage } from "../libs/crypto";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import * as databaseUtil from "../db/databaseUtil";
import * as libsUtil from "../libs/util"; import * as libsUtil from "../libs/util";
import { NotificationIface } from "../constants/app"; import { NotificationIface, USE_DEXIE_DB } from "../constants/app";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
interface Member { interface Member {
admitted: boolean; admitted: boolean;
@ -355,7 +357,16 @@ export default class MembersList extends Vue {
} }
async loadContacts() { async loadContacts() {
this.contacts = await db.contacts.toArray(); const platformService = PlatformServiceFactory.getInstance();
const result = await platformService.dbQuery("SELECT * FROM contacts");
if (result) {
this.contacts = databaseUtil.mapQueryResultToValues(
result,
) as unknown as Contact[];
}
if (USE_DEXIE_DB) {
this.contacts = await db.contacts.toArray();
}
} }
getContactFor(did: string): Contact | undefined { getContactFor(did: string): Contact | undefined {
@ -439,7 +450,14 @@ export default class MembersList extends Vue {
if (result.success) { if (result.success) {
decrMember.isRegistered = true; decrMember.isRegistered = true;
if (oldContact) { if (oldContact) {
await db.contacts.update(decrMember.did, { registered: true }); const platformService = PlatformServiceFactory.getInstance();
await platformService.dbExec(
"UPDATE contacts SET registered = ? WHERE did = ?",
[true, decrMember.did],
);
if (USE_DEXIE_DB) {
await db.contacts.update(decrMember.did, { registered: true });
}
oldContact.registered = true; oldContact.registered = true;
} }
this.$notify( this.$notify(
@ -492,7 +510,14 @@ export default class MembersList extends Vue {
name: member.name, name: member.name,
}; };
await db.contacts.add(newContact); const platformService = PlatformServiceFactory.getInstance();
await platformService.dbExec(
"INSERT INTO contacts (did, name) VALUES (?, ?)",
[member.did, member.name],
);
if (USE_DEXIE_DB) {
await db.contacts.add(newContact);
}
this.contacts.push(newContact); this.contacts.push(newContact);
this.$notify( this.$notify(

27
src/components/OnboardingDialog.vue

@ -201,13 +201,16 @@
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 { import {
db, db,
retrieveSettingsForActiveAccount, retrieveSettingsForActiveAccount,
updateAccountSettings, updateAccountSettings,
} from "../db/index"; } from "../db/index";
import * as databaseUtil from "../db/databaseUtil";
import { OnboardPage } from "../libs/util"; import { OnboardPage } from "../libs/util";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { Contact } from "@/db/tables/contacts";
@Component({ @Component({
computed: { computed: {
@ -222,7 +225,7 @@ export default class OnboardingDialog extends Vue {
$router!: Router; $router!: Router;
activeDid = ""; activeDid = "";
firstContactName = null; firstContactName = "";
givenName = ""; givenName = "";
isRegistered = false; isRegistered = false;
numContacts = 0; numContacts = 0;
@ -234,10 +237,22 @@ export default class OnboardingDialog extends Vue {
const settings = await retrieveSettingsForActiveAccount(); const settings = await retrieveSettingsForActiveAccount();
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.isRegistered = !!settings.isRegistered; this.isRegistered = !!settings.isRegistered;
const contacts = await db.contacts.toArray(); const platformService = PlatformServiceFactory.getInstance();
this.numContacts = contacts.length; const dbContacts = await platformService.dbQuery("SELECT * FROM contacts");
if (this.numContacts > 0) { if (dbContacts) {
this.firstContactName = contacts[0].name; this.numContacts = dbContacts.values.length;
const firstContact = dbContacts.values[0];
const fullContact = databaseUtil.mapColumnsToValues(dbContacts.columns, [
firstContact,
]) as unknown as Contact;
this.firstContactName = fullContact.name || "";
}
if (USE_DEXIE_DB) {
const contacts = await db.contacts.toArray();
this.numContacts = contacts.length;
if (this.numContacts > 0) {
this.firstContactName = contacts[0].name || "";
}
} }
this.visible = true; this.visible = true;
if (this.page === OnboardPage.Create) { if (this.page === OnboardPage.Create) {

22
src/components/UserNameDialog.vue

@ -37,9 +37,11 @@
<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 { db, retrieveSettingsForActiveAccount } from "../db/index"; import { db, retrieveSettingsForActiveAccount } from "../db/index";
import * as databaseUtil from "../db/databaseUtil";
import { MASTER_SETTINGS_KEY } from "../db/tables/settings"; import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
@Component @Component
export default class UserNameDialog extends Vue { export default class UserNameDialog extends Vue {
@ -61,15 +63,25 @@ export default class UserNameDialog extends Vue {
*/ */
async open(aCallback?: (name?: string) => void) { async open(aCallback?: (name?: string) => void) {
this.callback = aCallback || this.callback; this.callback = aCallback || this.callback;
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.visible = true; this.visible = true;
} }
async onClickSaveChanges() { async onClickSaveChanges() {
await db.settings.update(MASTER_SETTINGS_KEY, { const platformService = PlatformServiceFactory.getInstance();
firstName: this.givenName, await platformService.dbExec(
}); "UPDATE settings SET firstName = ? WHERE key = ?",
[this.givenName, MASTER_SETTINGS_KEY],
);
if (USE_DEXIE_DB) {
await db.settings.update(MASTER_SETTINGS_KEY, {
firstName: this.givenName,
});
}
this.visible = false; this.visible = false;
this.callback(this.givenName); this.callback(this.givenName);
} }

2
src/constants/app.ts

@ -51,7 +51,7 @@ export const IMAGE_TYPE_PROFILE = "profile";
export const PASSKEYS_ENABLED = export const PASSKEYS_ENABLED =
!!import.meta.env.VITE_PASSKEYS_ENABLED || false; !!import.meta.env.VITE_PASSKEYS_ENABLED || false;
export const USE_DEXIE_DB = true; export const USE_DEXIE_DB = false;
/** /**
* The possible values for "group" and "type" are in App.vue. * The possible values for "group" and "type" are in App.vue.

36
src/db/databaseUtil.ts

@ -2,6 +2,7 @@ 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";
import { DEFAULT_ENDORSER_API_SERVER } from "@/constants/app"; import { DEFAULT_ENDORSER_API_SERVER } from "@/constants/app";
import { QueryExecResult } from "@/interfaces/database";
export async function updateDefaultSettings( export async function updateDefaultSettings(
settingsChanges: Settings, settingsChanges: Settings,
@ -149,6 +150,26 @@ export async function logConsoleAndDb(
await logToDb(message); await logToDb(message);
} }
/**
* Generates an SQL INSERT statement and parameters from a model object.
* @param model The model object containing fields to update
* @param tableName The name of the table to update
* @returns Object containing the SQL statement and parameters array
*/
export function generateInsertStatement(
model: Record<string, unknown>,
tableName: string,
): { sql: string; params: unknown[] } {
const columns = Object.keys(model);
const values = Object.values(model);
const placeholders = values.map(() => "?").join(", ");
const insertSql = `INSERT INTO ${tableName} (${columns.join(", ")}) VALUES (${placeholders})`;
return {
sql: insertSql,
params: values,
};
}
/** /**
* Generates an SQL UPDATE statement and parameters from a model object. * Generates an SQL UPDATE statement and parameters from a model object.
* @param model The model object containing fields to update * @param model The model object containing fields to update
@ -157,7 +178,7 @@ export async function logConsoleAndDb(
* @param whereParams Parameters for the WHERE clause * @param whereParams Parameters for the WHERE clause
* @returns Object containing the SQL statement and parameters array * @returns Object containing the SQL statement and parameters array
*/ */
function generateUpdateStatement( export function generateUpdateStatement(
model: Record<string, unknown>, model: Record<string, unknown>,
tableName: string, tableName: string,
whereClause: string, whereClause: string,
@ -186,6 +207,17 @@ function generateUpdateStatement(
}; };
} }
export function mapQueryResultToValues(
record: QueryExecResult | undefined,
): Array<Record<string, unknown>> {
if (!record) {
return [];
}
return mapColumnsToValues(record.columns, record.values) as Array<
Record<string, unknown>
>;
}
/** /**
* Maps an array of column names to an array of value arrays, creating objects where each column name * Maps an array of column names to an array of value arrays, creating objects where each column name
* is mapped to its corresponding value. * is mapped to its corresponding value.
@ -196,7 +228,7 @@ function generateUpdateStatement(
export function mapColumnsToValues( export function mapColumnsToValues(
columns: string[], columns: string[],
values: unknown[][], values: unknown[][],
): Record<string, unknown>[] { ): Array<Record<string, unknown>> {
return values.map((row) => { return values.map((row) => {
const obj: Record<string, unknown> = {}; const obj: Record<string, unknown> = {};
columns.forEach((column, index) => { columns.forEach((column, index) => {

5
src/libs/util.ts

@ -558,9 +558,8 @@ export const retrieveFullyDecryptedAccount = async (
) { ) {
throw new Error("Account not found."); throw new Error("Account not found.");
} }
const fullAccountData = databaseUtil.mapColumnsToValues( const fullAccountData = databaseUtil.mapQueryResultToValues(
dbAccount.columns, dbAccount,
dbAccount.values,
)[0] as AccountEncrypted; )[0] as AccountEncrypted;
const identityEncr = base64ToArrayBuffer(fullAccountData.identityEncrBase64); const identityEncr = base64ToArrayBuffer(fullAccountData.identityEncrBase64);
const mnemonicEncr = base64ToArrayBuffer(fullAccountData.mnemonicEncrBase64); const mnemonicEncr = base64ToArrayBuffer(fullAccountData.mnemonicEncrBase64);

2
src/main.web.ts

@ -1,4 +1,4 @@
// @ts-ignore // @ts-expect-error but not sure why it's not in there
import { initBackend } from "absurd-sql/dist/indexeddb-main-thread"; import { initBackend } from "absurd-sql/dist/indexeddb-main-thread";
import { initializeApp } from "./main.common"; import { initializeApp } from "./main.common";
import "./registerServiceWorker"; // Web PWA support import "./registerServiceWorker"; // Web PWA support

5
src/services/PlatformService.ts

@ -107,7 +107,10 @@ export interface PlatformService {
* @param params - The parameters to pass to the query * @param params - The parameters to pass to the query
* @returns Promise resolving to the query result * @returns Promise resolving to the query result
*/ */
dbQuery(sql: string, params?: unknown[]): Promise<QueryExecResult>; dbQuery(
sql: string,
params?: unknown[],
): Promise<QueryExecResult | undefined>;
/** /**
* Executes a create/update/delete on the database. * Executes a create/update/delete on the database.

5
src/services/platforms/WebPlatformService.ts

@ -365,7 +365,10 @@ export class WebPlatformService implements PlatformService {
/** /**
* @see PlatformService.dbQuery * @see PlatformService.dbQuery
*/ */
dbQuery(sql: string, params?: unknown[]): Promise<QueryExecResult> { dbQuery(
sql: string,
params?: unknown[],
): Promise<QueryExecResult | undefined> {
return databaseService.query(sql, params).then((result) => result[0]); return databaseService.query(sql, params).then((result) => result[0]);
} }

7
src/views/AccountViewView.vue

@ -1350,17 +1350,14 @@ export default class AccountViewView extends Vue {
* Processes the identity and updates the component's state. * Processes the identity and updates the component's state.
*/ */
async processIdentity() { async processIdentity() {
let account: Account | undefined = undefined;
const platformService = PlatformServiceFactory.getInstance(); const platformService = PlatformServiceFactory.getInstance();
const dbAccount = await platformService.dbQuery( const dbAccount = await platformService.dbQuery(
"SELECT * FROM accounts WHERE did = ?", "SELECT * FROM accounts WHERE did = ?",
[this.activeDid], [this.activeDid],
); );
let account: Account | undefined = undefined;
if (dbAccount) { if (dbAccount) {
account = databaseUtil.mapColumnsToValues( account = databaseUtil.mapQueryResultToValues(dbAccount)[0] as Account;
dbAccount.columns,
dbAccount.values,
)[0] as Account;
} }
if (USE_DEXIE_DB) { if (USE_DEXIE_DB) {
account = await retrieveAccountMetadata(this.activeDid); account = await retrieveAccountMetadata(this.activeDid);

18
src/views/ClaimCertificateView.vue

@ -14,11 +14,14 @@
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import { nextTick } from "vue"; import { nextTick } from "vue";
import QRCode from "qrcode"; import QRCode from "qrcode";
import { APP_SERVER, NotificationIface } from "../constants/app"; import { APP_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 * as serverUtil from "../libs/endorserServer"; import * as serverUtil from "../libs/endorserServer";
import { GenericCredWrapper, GenericVerifiableCredential } from "../interfaces"; import { GenericCredWrapper, GenericVerifiableCredential } from "../interfaces";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { Contact } from "@/db/tables/contacts";
@Component @Component
export default class ClaimCertificateView extends Vue { export default class ClaimCertificateView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
@ -84,8 +87,17 @@ export default class ClaimCertificateView extends Vue {
claimData: GenericCredWrapper<GenericVerifiableCredential>, claimData: GenericCredWrapper<GenericVerifiableCredential>,
confirmerIds: Array<string>, confirmerIds: Array<string>,
) { ) {
await db.open(); const platformService = PlatformServiceFactory.getInstance();
const allContacts = await db.contacts.toArray(); const dbAllContacts = await platformService.dbQuery(
"SELECT * FROM contacts",
);
let allContacts = databaseUtil.mapQueryResultToValues(
dbAllContacts,
) as unknown as Contact[];
if (USE_DEXIE_DB) {
await db.open();
allContacts = await db.contacts.toArray();
}
const canvas = this.$refs.claimCanvas as HTMLCanvasElement; const canvas = this.$refs.claimCanvas as HTMLCanvasElement;
if (canvas) { if (canvas) {

18
src/views/ClaimReportCertificateView.vue

@ -11,10 +11,13 @@ import { Component, Vue } from "vue-facing-decorator";
import { nextTick } from "vue"; import { nextTick } from "vue";
import QRCode from "qrcode"; import QRCode from "qrcode";
import { APP_SERVER, NotificationIface } from "../constants/app"; import { APP_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 * as endorserServer from "../libs/endorserServer"; import * as endorserServer from "../libs/endorserServer";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { Contact } from "@/db/tables/contacts";
@Component @Component
export default class ClaimReportCertificateView extends Vue { export default class ClaimReportCertificateView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
@ -66,8 +69,17 @@ export default class ClaimReportCertificateView extends Vue {
async drawCanvas( async drawCanvas(
claimData: endorserServer.GenericCredWrapper<endorserServer.GenericVerifiableCredential>, claimData: endorserServer.GenericCredWrapper<endorserServer.GenericVerifiableCredential>,
) { ) {
await db.open(); const platformService = PlatformServiceFactory.getInstance();
const allContacts = await db.contacts.toArray(); const dbAllContacts = await platformService.dbQuery(
"SELECT * FROM contacts",
);
let allContacts = databaseUtil.mapQueryResultToValues(
dbAllContacts,
) as unknown as Contact[];
if (USE_DEXIE_DB) {
await db.open();
allContacts = await db.contacts.toArray();
}
const canvas = this.$refs.claimCanvas as HTMLCanvasElement; const canvas = this.$refs.claimCanvas as HTMLCanvasElement;
if (canvas) { if (canvas) {

16
src/views/ClaimView.vue

@ -542,13 +542,14 @@ import { useClipboard } from "@vueuse/core";
import { GenericVerifiableCredential } from "../interfaces"; 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 } from "../constants/app"; import { NotificationIface, USE_DEXIE_DB } from "../constants/app";
import { import {
db, db,
logConsoleAndDb, logConsoleAndDb,
retrieveSettingsForActiveAccount, retrieveSettingsForActiveAccount,
} from "../db/index"; } from "../db/index";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import * as databaseUtil from "../db/databaseUtil";
import * as serverUtil from "../libs/endorserServer"; import * as serverUtil from "../libs/endorserServer";
import { import {
GenericCredWrapper, GenericCredWrapper,
@ -557,6 +558,7 @@ import {
} from "../interfaces"; } from "../interfaces";
import * as libsUtil from "../libs/util"; import * as libsUtil from "../libs/util";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
@Component({ @Component({
components: { GiftedDialog, QuickNav }, components: { GiftedDialog, QuickNav },
@ -624,7 +626,17 @@ export default class ClaimView extends Vue {
const settings = await retrieveSettingsForActiveAccount(); const settings = await retrieveSettingsForActiveAccount();
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
this.allContacts = await db.contacts.toArray(); const platformService = PlatformServiceFactory.getInstance();
const dbAllContacts = await platformService.dbQuery(
"SELECT * FROM contacts",
);
this.allContacts = databaseUtil.mapQueryResultToValues(
dbAllContacts,
) as unknown as Contact[];
if (USE_DEXIE_DB) {
await db.open();
this.allContacts = await db.contacts.toArray();
}
this.isRegistered = settings.isRegistered || false; this.isRegistered = settings.isRegistered || false;
try { try {

16
src/views/ConfirmGiftView.vue

@ -438,9 +438,10 @@ import { Component, Vue } from "vue-facing-decorator";
import { useClipboard } from "@vueuse/core"; import { useClipboard } from "@vueuse/core";
import { RouteLocationNormalizedLoaded, Router } from "vue-router"; import { RouteLocationNormalizedLoaded, 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 { 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 * as serverUtil from "../libs/endorserServer"; import * as serverUtil from "../libs/endorserServer";
import { GenericVerifiableCredential, GiveSummaryRecord } from "../interfaces"; import { GenericVerifiableCredential, GiveSummaryRecord } from "../interfaces";
import { displayAmount } from "../libs/endorserServer"; import { displayAmount } from "../libs/endorserServer";
@ -448,6 +449,7 @@ import * as libsUtil from "../libs/util";
import { retrieveAccountDids } from "../libs/util"; import { retrieveAccountDids } from "../libs/util";
import TopMessage from "../components/TopMessage.vue"; import TopMessage from "../components/TopMessage.vue";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
/** /**
* ConfirmGiftView Component * ConfirmGiftView Component
* *
@ -531,7 +533,17 @@ export default class ConfirmGiftView extends Vue {
const settings = await retrieveSettingsForActiveAccount(); const settings = await retrieveSettingsForActiveAccount();
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
this.allContacts = await db.contacts.toArray(); const platformService = PlatformServiceFactory.getInstance();
const dbAllContacts = await platformService.dbQuery(
"SELECT * FROM contacts",
);
this.allContacts = databaseUtil.mapQueryResultToValues(
dbAllContacts,
) as unknown as Contact[];
if (USE_DEXIE_DB) {
await db.open();
this.allContacts = await db.contacts.toArray();
}
this.isRegistered = settings.isRegistered || false; this.isRegistered = settings.isRegistered || false;
this.allMyDids = await retrieveAccountDids(); this.allMyDids = await retrieveAccountDids();

17
src/views/ContactAmountsView.vue

@ -117,9 +117,10 @@ import { Component, Vue } from "vue-facing-decorator";
import { RouteLocationNormalizedLoaded, Router } from "vue-router"; import { RouteLocationNormalizedLoaded, 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 { 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 { import {
AgreeVerifiableCredential, AgreeVerifiableCredential,
GiveSummaryRecord, GiveSummaryRecord,
@ -133,6 +134,7 @@ import {
} from "../libs/endorserServer"; } from "../libs/endorserServer";
import { retrieveAccountCount } from "../libs/util"; import { retrieveAccountCount } from "../libs/util";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
@Component({ components: { QuickNav } }) @Component({ components: { QuickNav } })
export default class ContactAmountssView extends Vue { export default class ContactAmountssView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
@ -154,7 +156,18 @@ export default class ContactAmountssView extends Vue {
async created() { async created() {
try { try {
const contactDid = this.$route.query["contactDid"] as string; const contactDid = this.$route.query["contactDid"] as string;
this.contact = (await db.contacts.get(contactDid)) || null; const platformService = PlatformServiceFactory.getInstance();
const dbContact = await platformService.dbQuery(
"SELECT * FROM contacts WHERE did = ?",
[contactDid],
);
this.contact = databaseUtil.mapQueryResultToValues(
dbContact,
)[0] as unknown as Contact;
if (USE_DEXIE_DB) {
await db.open();
this.contact = (await db.contacts.get(contactDid)) || null;
}
const settings = await retrieveSettingsForActiveAccount(); const settings = await retrieveSettingsForActiveAccount();
this.activeDid = settings?.activeDid || ""; this.activeDid = settings?.activeDid || "";

48
src/views/ContactEditView.vue

@ -138,9 +138,11 @@ 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 { AppString, NotificationIface } from "../constants/app"; import { AppString, NotificationIface, USE_DEXIE_DB } from "../constants/app";
import { db } from "../db/index"; import { db } from "../db/index";
import { Contact, ContactMethod } from "../db/tables/contacts"; import { Contact, ContactMethod } from "../db/tables/contacts";
import * as databaseUtil from "../db/databaseUtil";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
/** /**
* Contact Edit View Component * Contact Edit View Component
@ -188,7 +190,7 @@ export default class ContactEditView extends Vue {
$router!: Router; $router!: Router;
/** Current contact data */ /** Current contact data */
contact: Contact = { contact: Contact | undefined = {
did: "", did: "",
name: "", name: "",
notes: "", notes: "",
@ -220,7 +222,21 @@ export default class ContactEditView extends Vue {
*/ */
async created() { async created() {
const contactDid = this.$route.params.did; const contactDid = this.$route.params.did;
const contact = await db.contacts.get(contactDid || ""); const platformService = PlatformServiceFactory.getInstance();
const dbContact = await platformService.dbQuery(
"SELECT * FROM contacts WHERE did = ?",
[contactDid],
);
let contact: Contact | undefined = databaseUtil.mapQueryResultToValues(
dbContact,
)[0] as unknown as Contact;
contact.contactMethods = JSON.parse(
(contact?.contactMethods as unknown as string) || "[]",
);
if (USE_DEXIE_DB) {
await db.open();
contact = await db.contacts.get(contactDid || "");
}
if (contact) { if (contact) {
this.contact = contact; this.contact = contact;
this.contactName = contact.name || ""; this.contactName = contact.name || "";
@ -322,12 +338,24 @@ export default class ContactEditView extends Vue {
} }
// Save to database // Save to database
await db.contacts.update(this.contact.did, { const platformService = PlatformServiceFactory.getInstance();
name: this.contactName, const contactMethodsString = JSON.stringify(contactMethods);
notes: this.contactNotes, await platformService.dbExec(
contactMethods: contactMethods, "UPDATE contacts SET name = ?, notes = ?, contactMethods = ? WHERE did = ?",
}); [
this.contactName,
this.contactNotes,
contactMethodsString,
this.contact?.did || "",
],
);
if (USE_DEXIE_DB) {
await db.contacts.update(this.contact?.did || "", {
name: this.contactName,
notes: this.contactNotes,
contactMethods: contactMethods,
});
}
// Notify success and redirect // Notify success and redirect
this.$notify({ this.$notify({
group: "alert", group: "alert",
@ -336,7 +364,7 @@ export default class ContactEditView extends Vue {
text: "The contact info has been updated successfully.", text: "The contact info has been updated successfully.",
}); });
(this.$router as Router).push({ (this.$router as Router).push({
path: "/did/" + encodeURIComponent(this.contact.did), path: "/did/" + encodeURIComponent(this.contact?.did || ""),
}); });
} }
} }

24
src/views/ContactGiftingView.vue

@ -76,11 +76,13 @@ import { RouteLocationNormalizedLoaded, Router } from "vue-router";
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 { 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 { GiverReceiverInputInfo } from "../libs/util"; import { GiverReceiverInputInfo } from "../libs/util";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
@Component({ @Component({
components: { GiftedDialog, QuickNav, EntityIcon }, components: { GiftedDialog, QuickNav, EntityIcon },
}) })
@ -102,12 +104,22 @@ export default class ContactGiftingView extends Vue {
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
// .orderBy("name") wouldn't retrieve any entries with a blank name const platformService = PlatformServiceFactory.getInstance();
// .toCollection.sortBy("name") didn't sort in an order I understood const dbAllContacts = await platformService.dbQuery(
const baseContacts = await db.contacts.toArray(); "SELECT * FROM contacts ORDER BY name",
this.allContacts = baseContacts.sort((a, b) =>
(a.name || "").localeCompare(b.name || ""),
); );
this.allContacts = databaseUtil.mapQueryResultToValues(
dbAllContacts,
) as unknown as Contact[];
if (USE_DEXIE_DB) {
await db.open();
// .orderBy("name") wouldn't retrieve any entries with a blank name
// .toCollection.sortBy("name") didn't sort in an order I understood
const baseContacts = await db.contacts.toArray();
this.allContacts = baseContacts.sort((a, b) =>
(a.name || "").localeCompare(b.name || ""),
);
}
this.projectId = (this.$route.query["projectId"] as string) || ""; this.projectId = (this.$route.query["projectId"] as string) || "";
this.prompt = (this.$route.query["prompt"] as string) ?? this.prompt; this.prompt = (this.$route.query["prompt"] as string) ?? this.prompt;

36
src/views/ContactImportView.vue

@ -200,13 +200,19 @@ import { RouteLocationNormalizedLoaded, Router } from "vue-router";
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 OfferDialog from "../components/OfferDialog.vue"; import OfferDialog from "../components/OfferDialog.vue";
import { APP_SERVER, AppString, NotificationIface } from "../constants/app"; import {
APP_SERVER,
AppString,
NotificationIface,
USE_DEXIE_DB,
} from "../constants/app";
import { import {
db, db,
logConsoleAndDb, logConsoleAndDb,
retrieveSettingsForActiveAccount, retrieveSettingsForActiveAccount,
} from "../db/index"; } from "../db/index";
import { Contact, ContactMethod } from "../db/tables/contacts"; import { Contact, ContactMethod } from "../db/tables/contacts";
import * as databaseUtil from "../db/databaseUtil";
import * as libsUtil from "../libs/util"; import * as libsUtil from "../libs/util";
import { import {
capitalizeAndInsertSpacesBeforeCaps, capitalizeAndInsertSpacesBeforeCaps,
@ -215,6 +221,7 @@ import {
} from "../libs/endorserServer"; } from "../libs/endorserServer";
import { getContactJwtFromJwtUrl } from "../libs/crypto"; import { getContactJwtFromJwtUrl } from "../libs/crypto";
import { decodeEndorserJwt } from "../libs/crypto/vc"; import { decodeEndorserJwt } from "../libs/crypto/vc";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
/** /**
* Contact Import View Component * Contact Import View Component
@ -401,8 +408,17 @@ export default class ContactImportView extends Vue {
this.contactsImporting = contacts; this.contactsImporting = contacts;
this.contactsSelected = new Array(this.contactsImporting.length).fill(true); this.contactsSelected = new Array(this.contactsImporting.length).fill(true);
await db.open(); const platformService = PlatformServiceFactory.getInstance();
const baseContacts = await db.contacts.toArray(); const dbAllContacts = await platformService.dbQuery(
"SELECT * FROM contacts",
);
let baseContacts = databaseUtil.mapQueryResultToValues(
dbAllContacts,
) as unknown as Contact[];
if (USE_DEXIE_DB) {
await db.open();
baseContacts = await db.contacts.toArray();
}
// Check for existing contacts and differences // Check for existing contacts and differences
for (let i = 0; i < this.contactsImporting.length; i++) { for (let i = 0; i < this.contactsImporting.length; i++) {
@ -515,7 +531,19 @@ export default class ContactImportView extends Vue {
const contact = this.contactsImporting[i]; const contact = this.contactsImporting[i];
const existingContact = this.contactsExisting[contact.did]; const existingContact = this.contactsExisting[contact.did];
if (existingContact) { if (existingContact) {
await db.contacts.update(contact.did, contact); const platformService = PlatformServiceFactory.getInstance();
// @ts-expect-error because we're just using the value to store to the DB
contact.contactMethods = JSON.stringify(contact.contactMethods);
const { sql, params } = databaseUtil.generateUpdateStatement(
contact as unknown as Record<string, unknown>,
"contacts",
"did = ?",
[contact.did],
);
await platformService.dbExec(sql, params);
if (USE_DEXIE_DB) {
await db.contacts.update(contact.did, contact);
}
updatedCount++; updatedCount++;
} else { } else {
// without explicit clone on the Proxy, we get: DataCloneError: Failed to execute 'add' on 'IDBObjectStore': #<Object> could not be cloned. // without explicit clone on the Proxy, we get: DataCloneError: Failed to execute 'add' on 'IDBObjectStore': #<Object> could not be cloned.

37
src/views/ContactQRScanFullView.vue

@ -104,23 +104,26 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import QRCodeVue3 from "qr-code-generator-vue3";
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 { useClipboard } from "@vueuse/core";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { QRScannerFactory } from "../services/QRScanner/QRScannerFactory"; import { QRScannerFactory } from "../services/QRScanner/QRScannerFactory";
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 { db } from "../db/index"; import { db } from "../db/index";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import { getContactJwtFromJwtUrl } from "../libs/crypto"; import { getContactJwtFromJwtUrl } from "../libs/crypto";
import { decodeEndorserJwt, ETHR_DID_PREFIX } from "../libs/crypto/vc"; import { decodeEndorserJwt, ETHR_DID_PREFIX } from "../libs/crypto/vc";
import { retrieveSettingsForActiveAccount } from "../db/index"; import { retrieveSettingsForActiveAccount } from "../db/index";
import * as databaseUtil from "../db/databaseUtil";
import { setVisibilityUtil } from "../libs/endorserServer"; import { setVisibilityUtil } from "../libs/endorserServer";
import { useClipboard } from "@vueuse/core";
import QRCodeVue3 from "qr-code-generator-vue3";
import UserNameDialog from "../components/UserNameDialog.vue"; import UserNameDialog from "../components/UserNameDialog.vue";
import { generateEndorserJwtUrlForAccount } from "../libs/endorserServer"; import { generateEndorserJwtUrlForAccount } from "../libs/endorserServer";
import { retrieveAccountMetadata } from "../libs/util"; import { retrieveAccountMetadata } from "../libs/util";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
interface QRScanResult { interface QRScanResult {
rawValue?: string; rawValue?: string;
@ -434,13 +437,22 @@ export default class ContactQRScan extends Vue {
async addNewContact(contact: Contact) { async addNewContact(contact: Contact) {
try { try {
logger.info("Opening database connection for new contact"); logger.info("Opening database connection for new contact");
await db.open();
// Check if contact already exists // Check if contact already exists
const existingContacts = await db.contacts.toArray(); const platformService = PlatformServiceFactory.getInstance();
const existingContact = existingContacts.find( const dbAllContacts = await platformService.dbQuery(
(c) => c.did === contact.did, "SELECT * FROM contacts WHERE did = ?",
[contact.did],
); );
const existingContacts = databaseUtil.mapQueryResultToValues(
dbAllContacts,
) as unknown as Contact[];
let existingContact: Contact | undefined = existingContacts[0];
if (USE_DEXIE_DB) {
await db.open();
const existingContacts = await db.contacts.toArray();
existingContact = existingContacts.find((c) => c.did === contact.did);
}
if (existingContact) { if (existingContact) {
logger.info("Contact already exists", { did: contact.did }); logger.info("Contact already exists", { did: contact.did });
@ -457,7 +469,16 @@ export default class ContactQRScan extends Vue {
} }
// Add new contact // Add new contact
await db.contacts.add(contact); // @ts-expect-error because we're just using the value to store to the DB
contact.contactMethods = JSON.stringify(contact.contactMethods);
const { sql, params } = databaseUtil.generateInsertStatement(
contact as unknown as Record<string, unknown>,
"contacts",
);
await platformService.dbExec(sql, params);
if (USE_DEXIE_DB) {
await db.contacts.add(contact);
}
if (this.activeDid) { if (this.activeDid) {
logger.info("Setting contact visibility", { did: contact.did }); logger.info("Setting contact visibility", { did: contact.did });

67
src/views/ContactQRScanShowView.vue

@ -190,10 +190,11 @@ import { QrcodeStream } from "vue-qrcode-reader";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import UserNameDialog from "../components/UserNameDialog.vue"; import UserNameDialog from "../components/UserNameDialog.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 { MASTER_SETTINGS_KEY } from "../db/tables/settings"; import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
import * as databaseUtil from "../db/databaseUtil";
import { getContactJwtFromJwtUrl } from "../libs/crypto"; import { getContactJwtFromJwtUrl } from "../libs/crypto";
import { import {
generateEndorserJwtUrlForAccount, generateEndorserJwtUrlForAccount,
@ -206,6 +207,7 @@ import { Router } from "vue-router";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { QRScannerFactory } from "@/services/QRScanner/QRScannerFactory"; import { QRScannerFactory } from "@/services/QRScanner/QRScannerFactory";
import { CameraState } from "@/services/QRScanner/types"; import { CameraState } from "@/services/QRScanner/types";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
interface QRScanResult { interface QRScanResult {
rawValue?: string; rawValue?: string;
@ -591,7 +593,14 @@ export default class ContactQRScanShow extends Vue {
); );
if (regResult.success) { if (regResult.success) {
contact.registered = true; contact.registered = true;
db.contacts.update(contact.did, { 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 });
}
logger.info("Contact registration successful", { did: contact.did }); logger.info("Contact registration successful", { did: contact.did });
this.$notify( this.$notify(
@ -759,13 +768,22 @@ export default class ContactQRScanShow extends Vue {
async addNewContact(contact: Contact) { async addNewContact(contact: Contact) {
try { try {
logger.info("Opening database connection for new contact"); logger.info("Opening database connection for new contact");
await db.open();
// Check if contact already exists // Check if contact already exists
const existingContacts = await db.contacts.toArray(); const platformService = PlatformServiceFactory.getInstance();
const existingContact = existingContacts.find( const dbAllContacts = await platformService.dbQuery(
(c) => c.did === contact.did, "SELECT * FROM contacts WHERE did = ?",
[contact.did],
); );
const existingContacts = databaseUtil.mapQueryResultToValues(
dbAllContacts,
) as unknown as Contact[];
let existingContact: Contact | undefined = existingContacts[0];
if (USE_DEXIE_DB) {
await db.open();
const existingContacts = await db.contacts.toArray();
existingContact = existingContacts.find((c) => c.did === contact.did);
}
if (existingContact) { if (existingContact) {
logger.info("Contact already exists", { did: contact.did }); logger.info("Contact already exists", { did: contact.did });
@ -782,7 +800,16 @@ export default class ContactQRScanShow extends Vue {
} }
// Add new contact // Add new contact
await db.contacts.add(contact); // @ts-expect-error because we're just using the value to store to the DB
contact.contactMethods = JSON.stringify(contact.contactMethods);
const { sql, params } = databaseUtil.generateInsertStatement(
contact as unknown as Record<string, unknown>,
"contacts",
);
await platformService.dbExec(sql, params);
if (USE_DEXIE_DB) {
await db.contacts.add(contact);
}
if (this.activeDid) { if (this.activeDid) {
logger.info("Setting contact visibility", { did: contact.did }); logger.info("Setting contact visibility", { did: contact.did });
@ -816,17 +843,31 @@ export default class ContactQRScanShow 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 db.settings.update(MASTER_SETTINGS_KEY, { const platformService = PlatformServiceFactory.getInstance();
hideRegisterPromptOnNewContact: stopAsking, await platformService.dbExec(
}); "UPDATE settings SET hideRegisterPromptOnNewContact = ? WHERE key = ?",
[stopAsking, MASTER_SETTINGS_KEY],
);
if (USE_DEXIE_DB) {
await db.settings.update(MASTER_SETTINGS_KEY, {
hideRegisterPromptOnNewContact: stopAsking,
});
}
this.hideRegisterPromptOnNewContact = stopAsking; this.hideRegisterPromptOnNewContact = stopAsking;
} }
}, },
onNo: async (stopAsking?: boolean) => { onNo: async (stopAsking?: boolean) => {
if (stopAsking) { if (stopAsking) {
await db.settings.update(MASTER_SETTINGS_KEY, { const platformService = PlatformServiceFactory.getInstance();
hideRegisterPromptOnNewContact: stopAsking, await platformService.dbExec(
}); "UPDATE settings SET hideRegisterPromptOnNewContact = ? WHERE key = ?",
[stopAsking, MASTER_SETTINGS_KEY],
);
if (USE_DEXIE_DB) {
await db.settings.update(MASTER_SETTINGS_KEY, {
hideRegisterPromptOnNewContact: stopAsking,
});
}
this.hideRegisterPromptOnNewContact = stopAsking; this.hideRegisterPromptOnNewContact = stopAsking;
} }
}, },

89
src/views/ContactsView.vue

@ -361,7 +361,12 @@ import GiftedDialog from "../components/GiftedDialog.vue";
import OfferDialog from "../components/OfferDialog.vue"; import OfferDialog from "../components/OfferDialog.vue";
import ContactNameDialog from "../components/ContactNameDialog.vue"; import ContactNameDialog from "../components/ContactNameDialog.vue";
import TopMessage from "../components/TopMessage.vue"; import TopMessage from "../components/TopMessage.vue";
import { APP_SERVER, AppString, NotificationIface } from "../constants/app"; import {
APP_SERVER,
AppString,
NotificationIface,
USE_DEXIE_DB,
} from "../constants/app";
import { import {
db, db,
logConsoleAndDb, logConsoleAndDb,
@ -370,6 +375,7 @@ import {
updateDefaultSettings, updateDefaultSettings,
} from "../db/index"; } from "../db/index";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import * as databaseUtil from "../db/databaseUtil";
import { getContactJwtFromJwtUrl } from "../libs/crypto"; import { getContactJwtFromJwtUrl } from "../libs/crypto";
import { decodeEndorserJwt } from "../libs/crypto/vc"; import { decodeEndorserJwt } from "../libs/crypto/vc";
import { import {
@ -390,6 +396,7 @@ import {
import * as libsUtil from "../libs/util"; import * as libsUtil from "../libs/util";
import { generateSaveAndActivateIdentity } from "../libs/util"; import { generateSaveAndActivateIdentity } from "../libs/util";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
@Component({ @Component({
components: { components: {
GiftedDialog, GiftedDialog,
@ -438,8 +445,11 @@ export default class ContactsView extends Vue {
libsUtil = libsUtil; libsUtil = libsUtil;
public async created() { public async created() {
await db.open(); let settings = await databaseUtil.retrieveSettingsForActiveAccount();
const settings = await 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 || "";
this.isRegistered = !!settings.isRegistered; this.isRegistered = !!settings.isRegistered;
@ -457,12 +467,22 @@ export default class ContactsView extends Vue {
this.loadGives(); this.loadGives();
} }
// .orderBy("name") wouldn't retrieve any entries with a blank name const platformService = PlatformServiceFactory.getInstance();
// .toCollection.sortBy("name") didn't sort in an order I understood const dbAllContacts = await platformService.dbQuery(
const baseContacts = await db.contacts.toArray(); "SELECT * FROM contacts ORDER BY name",
this.contacts = baseContacts.sort((a, b) =>
(a.name || "").localeCompare(b.name || ""),
); );
this.contacts = databaseUtil.mapQueryResultToValues(
dbAllContacts,
) as unknown as Contact[];
if (USE_DEXIE_DB) {
await db.open();
// .orderBy("name") wouldn't retrieve any entries with a blank name
// .toCollection.sortBy("name") didn't sort in an order I understood
const baseContacts = await db.contacts.toArray();
this.contacts = baseContacts.sort((a, b) =>
(a.name || "").localeCompare(b.name || ""),
);
}
} }
private async processContactJwt() { private async processContactJwt() {
@ -820,12 +840,22 @@ export default class ContactsView extends Vue {
this.danger("An error occurred. Some contacts may have been added."); this.danger("An error occurred. Some contacts may have been added.");
} }
// .orderBy("name") wouldn't retrieve any entries with a blank name const platformService = PlatformServiceFactory.getInstance();
// .toCollection.sortBy("name") didn't sort in an order I understood const dbAllContacts = await platformService.dbQuery(
const baseContacts = await db.contacts.toArray(); "SELECT * FROM contacts ORDER BY name",
this.contacts = baseContacts.sort((a, b) =>
(a.name || "").localeCompare(b.name || ""),
); );
this.contacts = databaseUtil.mapQueryResultToValues(
dbAllContacts,
) as unknown as Contact[];
if (USE_DEXIE_DB) {
await db.open();
// .orderBy("name") wouldn't retrieve any entries with a blank name
// .toCollection.sortBy("name") didn't sort in an order I understood
const baseContacts = await db.contacts.toArray();
this.contacts = baseContacts.sort((a, b) =>
(a.name || "").localeCompare(b.name || ""),
);
}
return; return;
} }
@ -934,7 +964,15 @@ export default class ContactsView extends Vue {
seesMe, seesMe,
registered, registered,
}; };
return db.contacts.add(newContact); const platformService = PlatformServiceFactory.getInstance();
const { sql, params } = databaseUtil.generateInsertStatement(
newContact as unknown as Record<string, unknown>,
"contacts",
);
await platformService.dbExec(sql, params);
if (USE_DEXIE_DB) {
await db.contacts.add(newContact);
}
} }
private async addContact(newContact: Contact) { private async addContact(newContact: Contact) {
@ -946,8 +984,18 @@ export default class ContactsView extends Vue {
this.danger("The DID must begin with 'did:'", "Invalid DID"); this.danger("The DID must begin with 'did:'", "Invalid DID");
return; return;
} }
return db.contacts
.add(newContact) const platformService = PlatformServiceFactory.getInstance();
const { sql, params } = databaseUtil.generateInsertStatement(
newContact as unknown as Record<string, unknown>,
"contacts",
);
let contactPromise = platformService.dbExec(sql, params);
if (USE_DEXIE_DB) {
// @ts-expect-error since the result of this promise won't be used, and this will go away soon
contactPromise = db.contacts.add(newContact);
}
return contactPromise
.then(() => { .then(() => {
const allContacts = this.contacts.concat([newContact]); const allContacts = this.contacts.concat([newContact]);
this.contacts = R.sort( this.contacts = R.sort(
@ -1063,7 +1111,14 @@ export default class ContactsView extends Vue {
); );
if (regResult.success) { if (regResult.success) {
contact.registered = true; contact.registered = true;
await db.contacts.update(contact.did, { 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 });
}
this.$notify( this.$notify(
{ {

Loading…
Cancel
Save