Browse Source

fix: standardize FontAwesome usage and improve error handling

- Change <fa> to <font-awesome> for consistent component naming
- Add structured error logging in QR scanner services
- Fix cacheImage event handling in ActivityListItem
- Improve code formatting and error wrapping
pull/132/head
Matthew Raymer 4 weeks ago
parent
commit
3ce2ea9b4e
  1. 9
      src/components/ActivityListItem.vue
  2. 60
      src/services/QRScanner/CapacitorQRScanner.ts
  3. 7
      src/services/QRScanner/WebDialogQRScanner.ts
  4. 24
      src/views/ContactQRScanShowView.vue
  5. 2
      src/views/ContactsView.vue

9
src/components/ActivityListItem.vue

@ -57,7 +57,7 @@
class="w-full h-auto max-w-lg max-h-96 object-contain mx-auto drop-shadow-md" class="w-full h-auto max-w-lg max-h-96 object-contain mx-auto drop-shadow-md"
:src="record.image" :src="record.image"
alt="Activity image" alt="Activity image"
@load="$emit('cacheImage', record.image)" @load="cacheImage(record.image)"
/> />
</a> </a>
</div> </div>
@ -182,7 +182,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-facing-decorator"; import { Component, Prop, Vue, Emit } from "vue-facing-decorator";
import { GiveRecordWithContactInfo } from "../types"; import { GiveRecordWithContactInfo } from "../types";
import EntityIcon from "./EntityIcon.vue"; import EntityIcon from "./EntityIcon.vue";
import { isGiveClaimType, notifyWhyCannotConfirm } from "../libs/util"; import { isGiveClaimType, notifyWhyCannotConfirm } from "../libs/util";
@ -202,6 +202,11 @@ export default class ActivityListItem extends Vue {
@Prop() activeDid!: string; @Prop() activeDid!: string;
@Prop() confirmerIdList?: string[]; @Prop() confirmerIdList?: string[];
@Emit()
cacheImage(image: string) {
return image;
}
get fetchAmount(): string { get fetchAmount(): string {
const claim = const claim =
(this.record.fullClaim as unknown).claim || this.record.fullClaim; (this.record.fullClaim as unknown).claim || this.record.fullClaim;

60
src/services/QRScanner/CapacitorQRScanner.ts

@ -19,8 +19,11 @@ export class CapacitorQRScanner implements QRScannerService {
const { camera } = await BarcodeScanner.checkPermissions(); const { camera } = await BarcodeScanner.checkPermissions();
return camera === "granted"; return camera === "granted";
} catch (error) { } catch (error) {
const wrappedError = error instanceof Error ? error : new Error(String(error)); const wrappedError =
logger.error("Error checking camera permissions:", { error: wrappedError.message }); error instanceof Error ? error : new Error(String(error));
logger.error("Error checking camera permissions:", {
error: wrappedError.message,
});
return false; return false;
} }
} }
@ -39,8 +42,11 @@ export class CapacitorQRScanner implements QRScannerService {
logger.debug(`Camera permissions ${granted ? "granted" : "denied"}`); logger.debug(`Camera permissions ${granted ? "granted" : "denied"}`);
return granted; return granted;
} catch (error) { } catch (error) {
const wrappedError = error instanceof Error ? error : new Error(String(error)); const wrappedError =
logger.error("Error requesting camera permissions:", { error: wrappedError.message }); error instanceof Error ? error : new Error(String(error));
logger.error("Error requesting camera permissions:", {
error: wrappedError.message,
});
return false; return false;
} }
} }
@ -52,8 +58,11 @@ export class CapacitorQRScanner implements QRScannerService {
logger.debug(`Scanner support: ${supported}`); logger.debug(`Scanner support: ${supported}`);
return supported; return supported;
} catch (error) { } catch (error) {
const wrappedError = error instanceof Error ? error : new Error(String(error)); const wrappedError =
logger.error("Error checking scanner support:", { error: wrappedError.message }); error instanceof Error ? error : new Error(String(error));
logger.error("Error checking scanner support:", {
error: wrappedError.message,
});
return false; return false;
} }
} }
@ -89,27 +98,32 @@ export class CapacitorQRScanner implements QRScannerService {
const scanOptions: StartScanOptions = { const scanOptions: StartScanOptions = {
formats: [BarcodeFormat.QrCode], formats: [BarcodeFormat.QrCode],
lensFacing: options?.camera === "front" ? LensFacing.Front : LensFacing.Back, lensFacing:
options?.camera === "front" ? LensFacing.Front : LensFacing.Back,
}; };
logger.debug("Scanner options:", scanOptions); logger.debug("Scanner options:", scanOptions);
// Add listener for barcode scans // Add listener for barcode scans
const handle = await BarcodeScanner.addListener("barcodeScanned", (result) => { const handle = await BarcodeScanner.addListener(
if (this.scanListener && result.barcode?.rawValue) { "barcodeScanned",
this.scanListener.onScan(result.barcode.rawValue); (result) => {
} if (this.scanListener && result.barcode?.rawValue) {
}); this.scanListener.onScan(result.barcode.rawValue);
}
},
);
this.listenerHandles.push(handle.remove); this.listenerHandles.push(handle.remove);
// Start continuous scanning // Start continuous scanning
await BarcodeScanner.startScan(scanOptions); await BarcodeScanner.startScan(scanOptions);
logger.info("MLKit scanner started successfully"); logger.info("MLKit scanner started successfully");
} catch (error) { } catch (error) {
const wrappedError = error instanceof Error ? error : new Error(String(error)); const wrappedError =
logger.error("Error during QR scan:", { error instanceof Error ? error : new Error(String(error));
logger.error("Error during QR scan:", {
error: wrappedError.message, error: wrappedError.message,
stack: wrappedError.stack stack: wrappedError.stack,
}); });
this.isScanning = false; this.isScanning = false;
await this.cleanup(); await this.cleanup();
@ -129,10 +143,11 @@ export class CapacitorQRScanner implements QRScannerService {
await BarcodeScanner.stopScan(); await BarcodeScanner.stopScan();
logger.info("QR scanner stopped successfully"); logger.info("QR scanner stopped successfully");
} catch (error) { } catch (error) {
const wrappedError = error instanceof Error ? error : new Error(String(error)); const wrappedError =
logger.error("Error stopping QR scan:", { error instanceof Error ? error : new Error(String(error));
logger.error("Error stopping QR scan:", {
error: wrappedError.message, error: wrappedError.message,
stack: wrappedError.stack stack: wrappedError.stack,
}); });
this.scanListener?.onError?.(wrappedError); this.scanListener?.onError?.(wrappedError);
throw wrappedError; throw wrappedError;
@ -154,7 +169,7 @@ export class CapacitorQRScanner implements QRScannerService {
this.cleanupPromise = (async () => { this.cleanupPromise = (async () => {
try { try {
logger.debug("Starting QR scanner cleanup"); logger.debug("Starting QR scanner cleanup");
// Stop scanning if active // Stop scanning if active
if (this.isScanning) { if (this.isScanning) {
await this.stopScan(); await this.stopScan();
@ -171,10 +186,11 @@ export class CapacitorQRScanner implements QRScannerService {
logger.info("QR scanner cleanup completed"); logger.info("QR scanner cleanup completed");
} catch (error) { } catch (error) {
const wrappedError = error instanceof Error ? error : new Error(String(error)); const wrappedError =
logger.error("Error during cleanup:", { error instanceof Error ? error : new Error(String(error));
logger.error("Error during cleanup:", {
error: wrappedError.message, error: wrappedError.message,
stack: wrappedError.stack stack: wrappedError.stack,
}); });
throw wrappedError; throw wrappedError;
} finally { } finally {

7
src/services/QRScanner/WebDialogQRScanner.ts

@ -32,9 +32,10 @@ export class WebDialogQRScanner implements QRScannerService {
stream.getTracks().forEach((track) => track.stop()); stream.getTracks().forEach((track) => track.stop());
return true; return true;
} catch (error) { } catch (error) {
const wrappedError = logger.error("Error requesting camera permissions:", {
error instanceof Error ? error : new Error(String(error)); error: error instanceof Error ? error.message : String(error),
logger.error("Error requesting camera permissions:", wrappedError); stack: error instanceof Error ? error.stack : undefined,
});
return false; return false;
} }
} }

24
src/views/ContactQRScanShowView.vue

@ -114,7 +114,6 @@ import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
import { getContactJwtFromJwtUrl } from "../libs/crypto"; import { getContactJwtFromJwtUrl } from "../libs/crypto";
import { import {
generateEndorserJwtUrlForAccount, generateEndorserJwtUrlForAccount,
isDid,
register, register,
setVisibilityUtil, setVisibilityUtil,
} from "../libs/endorserServer"; } from "../libs/endorserServer";
@ -170,12 +169,15 @@ export default class ContactQRScanShow extends Vue {
this.activeDid = settings.activeDid || ""; this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
this.givenName = settings.firstName || ""; this.givenName = settings.firstName || "";
this.hideRegisterPromptOnNewContact = !!settings.hideRegisterPromptOnNewContact; this.hideRegisterPromptOnNewContact =
!!settings.hideRegisterPromptOnNewContact;
this.isRegistered = !!settings.isRegistered; this.isRegistered = !!settings.isRegistered;
const account = await retrieveAccountMetadata(this.activeDid); const account = await retrieveAccountMetadata(this.activeDid);
if (account) { if (account) {
const name = (settings.firstName || "") + (settings.lastName ? ` ${settings.lastName}` : ""); const name =
(settings.firstName || "") +
(settings.lastName ? ` ${settings.lastName}` : "");
this.qrValue = await generateEndorserJwtUrlForAccount( this.qrValue = await generateEndorserJwtUrlForAccount(
account, account,
!!settings.isRegistered, !!settings.isRegistered,
@ -294,7 +296,10 @@ export default class ContactQRScanShow extends Vue {
async onScanDetect(result: string | QRScanResult) { async onScanDetect(result: string | QRScanResult) {
try { try {
// Extract raw value from different possible formats // Extract raw value from different possible formats
const rawValue = typeof result === 'string' ? result : (result?.rawValue || result?.barcode); const rawValue =
typeof result === "string"
? result
: result?.rawValue || result?.barcode;
if (!rawValue) { if (!rawValue) {
logger.warn("Invalid scan result - no value found:", result); logger.warn("Invalid scan result - no value found:", result);
return; return;
@ -558,7 +563,7 @@ export default class ContactQRScanShow extends Vue {
async handleAppPause() { async handleAppPause() {
if (!this.isMounted) return; if (!this.isMounted) return;
logger.info("App paused, stopping scanner"); logger.info("App paused, stopping scanner");
await this.stopScanning(); await this.stopScanning();
} }
@ -574,11 +579,13 @@ export default class ContactQRScanShow extends Vue {
try { try {
logger.info("Opening database connection for new contact"); logger.info("Opening database connection for new contact");
await db.open(); await db.open();
// Check if contact already exists // Check if contact already exists
const existingContacts = await db.contacts.toArray(); const existingContacts = await db.contacts.toArray();
const existingContact = existingContacts.find(c => c.did === contact.did); const 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 });
this.$notify( this.$notify(
@ -676,4 +683,3 @@ export default class ContactQRScanShow extends Vue {
aspect-ratio: 1 / 1; aspect-ratio: 1 / 1;
} }
</style> </style>

2
src/views/ContactsView.vue

@ -289,7 +289,7 @@
class="text-sm bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-2 py-1.5 rounded-md border border-slate-400" class="text-sm bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-2 py-1.5 rounded-md border border-slate-400"
title="See more given activity" title="See more given activity"
> >
<fa icon="file-lines" class="fa-fw" /> <font-awesome icon="file-lines" class="fa-fw" />
</router-link> </router-link>
</div> </div>
</div> </div>

Loading…
Cancel
Save