add better support info when there's an error on startup
This commit is contained in:
@@ -49,6 +49,8 @@ export const DEFAULT_PUSH_SERVER =
|
||||
|
||||
export const IMAGE_TYPE_PROFILE = "profile";
|
||||
|
||||
export const SUPPORT_EMAIL = "info@TimeSafari.app";
|
||||
|
||||
export const PASSKEYS_ENABLED =
|
||||
!!import.meta.env.VITE_PASSKEYS_ENABLED || false;
|
||||
|
||||
|
||||
@@ -412,6 +412,18 @@ router.beforeEach(async (to, _from, next) => {
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
|
||||
// Store error details so StartView can display them
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
const errorStack = error instanceof Error ? error.stack || "" : "";
|
||||
try {
|
||||
sessionStorage.setItem(
|
||||
"startupError",
|
||||
JSON.stringify({ message: errorMessage, stack: errorStack }),
|
||||
);
|
||||
} catch {
|
||||
// sessionStorage may be unavailable
|
||||
}
|
||||
|
||||
// Redirect to start page if identity creation fails
|
||||
// This allows users to manually create an identity or troubleshoot
|
||||
logger.info(
|
||||
|
||||
@@ -59,6 +59,7 @@ import {
|
||||
} from "../interfaces/deepLinks";
|
||||
import { logConsoleAndDb } from "../db/databaseUtil";
|
||||
import { logger } from "../utils/logger";
|
||||
import { SUPPORT_EMAIL } from "../constants/app";
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
@@ -105,7 +106,7 @@ const goHome = () => router.replace({ name: "home" });
|
||||
const reportIssue = () => {
|
||||
// Open a support form or email
|
||||
window.open(
|
||||
"mailto:support@timesafari.app?subject=Invalid Deep Link&body=" +
|
||||
`mailto:${SUPPORT_EMAIL}?subject=Invalid Deep Link&body=` +
|
||||
encodeURIComponent(
|
||||
`I encountered an error with a deep link: timesafari://${originalPath.value}\nError: ${errorMessage.value}`,
|
||||
),
|
||||
|
||||
@@ -552,8 +552,8 @@
|
||||
</h2>
|
||||
<p>
|
||||
Contact us at
|
||||
<a href="mailto:info@TimeSafari.app" class="text-blue-500"
|
||||
>info@TimeSafari.app</a
|
||||
<a :href="`mailto:${SUPPORT_EMAIL}`" class="text-blue-500"
|
||||
>{{ SUPPORT_EMAIL }}</a
|
||||
>
|
||||
</p>
|
||||
|
||||
@@ -591,7 +591,7 @@ import { copyToClipboard } from "../services/ClipboardService";
|
||||
|
||||
import * as Package from "../../package.json";
|
||||
import QuickNav from "../components/QuickNav.vue";
|
||||
import { APP_SERVER, NotificationIface } from "../constants/app";
|
||||
import { APP_SERVER, NotificationIface, SUPPORT_EMAIL } from "../constants/app";
|
||||
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
|
||||
import { QRNavigationService } from "@/services/QRNavigationService";
|
||||
import { UNNAMED_ENTITY_NAME } from "@/constants/entities";
|
||||
@@ -643,7 +643,7 @@ export default class HelpView extends Vue {
|
||||
showVerifiable = false;
|
||||
|
||||
APP_SERVER = APP_SERVER;
|
||||
// Capacitor reference removed - using QRNavigationService instead
|
||||
SUPPORT_EMAIL = SUPPORT_EMAIL;
|
||||
|
||||
/**
|
||||
* Initialize notification helpers
|
||||
|
||||
@@ -26,6 +26,31 @@
|
||||
</router-link>
|
||||
</div>
|
||||
|
||||
<!-- Startup error banner -->
|
||||
<div
|
||||
v-if="startupError"
|
||||
class="max-w-3xl mx-auto mb-6 p-4 bg-red-50 border border-red-300 rounded-lg"
|
||||
>
|
||||
<h2 class="text-red-800 font-semibold text-lg mb-2">Startup Error</h2>
|
||||
<p class="text-red-700 mb-3">
|
||||
The app encountered a critical error during startup. This is often
|
||||
caused by a database problem. Please send the details below to
|
||||
<a :href="`mailto:${SUPPORT_EMAIL}`" class="underline font-semibold">{{
|
||||
SUPPORT_EMAIL
|
||||
}}</a>
|
||||
so we can help resolve it.
|
||||
</p>
|
||||
<details class="bg-white border border-red-200 rounded p-3">
|
||||
<summary class="cursor-pointer text-red-700 font-medium">
|
||||
Error details
|
||||
</summary>
|
||||
<pre
|
||||
class="mt-2 text-xs text-red-900 whitespace-pre-wrap break-words"
|
||||
>{{ startupError }}</pre
|
||||
>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<!-- id used by puppeteer test script -->
|
||||
<div id="start-question">
|
||||
<div class="max-w-3xl mx-auto">
|
||||
@@ -139,7 +164,7 @@
|
||||
import { Component, Vue } from "vue-facing-decorator";
|
||||
import { Router } from "vue-router";
|
||||
|
||||
import { AppString, PASSKEYS_ENABLED } from "../constants/app";
|
||||
import { AppString, PASSKEYS_ENABLED, SUPPORT_EMAIL } from "../constants/app";
|
||||
import { PlatformServiceMixin } from "../utils/PlatformServiceMixin";
|
||||
import { logger } from "../utils/logger";
|
||||
|
||||
@@ -157,10 +182,12 @@ export default class StartView extends Vue {
|
||||
|
||||
// Feature flags and application constants
|
||||
PASSKEYS_ENABLED = PASSKEYS_ENABLED;
|
||||
SUPPORT_EMAIL = SUPPORT_EMAIL;
|
||||
|
||||
// Component state for identity generation
|
||||
givenName = "";
|
||||
numAccounts = 0;
|
||||
startupError = "";
|
||||
|
||||
/**
|
||||
* Computed property for primary action button styling
|
||||
@@ -201,11 +228,26 @@ export default class StartView extends Vue {
|
||||
*/
|
||||
async mounted() {
|
||||
try {
|
||||
// Load user settings using platform service
|
||||
const raw = sessionStorage.getItem("startupError");
|
||||
if (raw) {
|
||||
sessionStorage.removeItem("startupError");
|
||||
try {
|
||||
const parsed = JSON.parse(raw);
|
||||
const parts = [parsed.message, parsed.stack].filter(Boolean);
|
||||
this.startupError = parts.length > 0 ? parts.join("\n\n") : raw;
|
||||
logger.error("[StartView] Displaying startup error to user", parsed);
|
||||
} catch {
|
||||
this.startupError = raw;
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// sessionStorage or JSON parse may fail; non-critical
|
||||
}
|
||||
|
||||
try {
|
||||
const settings = await this.$accountSettings();
|
||||
this.givenName = settings.firstName || "";
|
||||
|
||||
// Load account count for display logic
|
||||
this.numAccounts = await retrieveAccountCount();
|
||||
|
||||
logger.debug("[StartView] Component mounted", {
|
||||
@@ -215,7 +257,6 @@ export default class StartView extends Vue {
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error("[StartView] Failed to load initialization data", error);
|
||||
// Continue with default behavior if settings load fails
|
||||
this.givenName = "";
|
||||
this.numAccounts = 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user