Browse Source

add support for deep-link query parameters

pull/139/head
Trent Larson 1 day ago
parent
commit
e9a8a3c1e7
  1. 64
      src/services/deepLinks.ts
  2. 44
      src/views/DeepLinkRedirectView.vue

64
src/services/deepLinks.ts

@ -115,7 +115,7 @@ export class DeepLinkHandler {
const [path, queryString] = parts[1].split("?");
const [routePath, ...pathParams] = path.split("/");
// logger.log(
// logger.info(
// "[DeepLink] Debug:",
// "Route Path:",
// routePath,
@ -150,37 +150,6 @@ export class DeepLinkHandler {
return { path: routePath, params, query };
}
/**
* Processes incoming deep links and routes them appropriately.
* Handles validation, error handling, and routing to the correct view.
*
* @param url - The deep link URL to process
* @throws {DeepLinkError} If URL processing fails
*/
async handleDeepLink(url: string): Promise<void> {
try {
logConsoleAndDb("[DeepLink] Processing URL: " + url, false);
const { path, params, query } = this.parseDeepLink(url);
// Ensure params is always a Record<string,string> by converting undefined to empty string
const sanitizedParams = Object.fromEntries(
Object.entries(params).map(([key, value]) => [key, value ?? ""]),
);
await this.validateAndRoute(path, sanitizedParams, query);
} catch (error) {
const deepLinkError = error as DeepLinkError;
logConsoleAndDb(
`[DeepLink] Error (${deepLinkError.code}): ${deepLinkError.message}`,
true,
);
throw {
code: deepLinkError.code || "UNKNOWN_ERROR",
message: deepLinkError.message,
details: deepLinkError.details,
};
}
}
/**
* Routes the deep link to appropriate view with validated parameters.
* Validates route and parameters using Zod schemas before routing.
@ -256,4 +225,35 @@ export class DeepLinkHandler {
};
}
}
/**
* Processes incoming deep links and routes them appropriately.
* Handles validation, error handling, and routing to the correct view.
*
* @param url - The deep link URL to process
* @throws {DeepLinkError} If URL processing fails
*/
async handleDeepLink(url: string): Promise<void> {
try {
logConsoleAndDb("[DeepLink] Processing URL: " + url, false);
const { path, params, query } = this.parseDeepLink(url);
// Ensure params is always a Record<string,string> by converting undefined to empty string
const sanitizedParams = Object.fromEntries(
Object.entries(params).map(([key, value]) => [key, value ?? ""]),
);
await this.validateAndRoute(path, sanitizedParams, query);
} catch (error) {
const deepLinkError = error as DeepLinkError;
logConsoleAndDb(
`[DeepLink] Error (${deepLinkError.code}): ${deepLinkError.message}`,
true,
);
throw {
code: deepLinkError.code || "UNKNOWN_ERROR",
message: deepLinkError.message,
details: deepLinkError.details,
};
}
}
}

44
src/views/DeepLinkRedirectView.vue

@ -122,17 +122,31 @@ export default class DeepLinkRedirectView extends Vue {
// If pathParam is an array (catch-all parameter), join it
const fullPath = Array.isArray(pathParam) ? pathParam.join("/") : pathParam;
this.destinationUrl = fullPath;
this.deepLinkUrl = `timesafari://${fullPath}`;
this.webUrl = `${APP_SERVER}/${fullPath}`;
// Log for debugging
logger.info("Deep link processing:", {
fullPath,
deepLinkUrl: this.deepLinkUrl,
webUrl: this.webUrl,
userAgent: this.userAgent,
});
// Get query parameters from the route
const queryParams = this.$route.query;
// Build query string if there are query parameters
let queryString = "";
if (Object.keys(queryParams).length > 0) {
const searchParams = new URLSearchParams();
Object.entries(queryParams).forEach(([key, value]) => {
if (value !== undefined && value !== null) {
const stringValue = Array.isArray(value) ? value[0] : value;
if (stringValue !== null && stringValue !== undefined) {
searchParams.append(key, stringValue);
}
}
});
queryString = "?" + searchParams.toString();
}
// Combine path with query parameters
const fullPathWithQuery = fullPath + queryString;
this.destinationUrl = fullPathWithQuery;
this.deepLinkUrl = `timesafari://${fullPathWithQuery}`;
this.webUrl = `${APP_SERVER}/${fullPathWithQuery}`;
this.isDevelopment = process.env.NODE_ENV !== "production";
this.userAgent = navigator.userAgent;
@ -147,13 +161,6 @@ export default class DeepLinkRedirectView extends Vue {
return;
}
logger.info("Attempting deep link redirect:", {
deepLinkUrl: this.deepLinkUrl,
webUrl: this.webUrl,
isMobile: this.isMobile,
userAgent: this.userAgent,
});
try {
// For mobile, try the deep link URL; for desktop, use the web URL
const redirectUrl = this.isMobile ? this.deepLinkUrl : this.webUrl;
@ -170,7 +177,6 @@ export default class DeepLinkRedirectView extends Vue {
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
logger.info("Fallback link click completed");
} catch (error) {
logger.error(
"Fallback deep link failed: " + errorStringForLog(error),

Loading…
Cancel
Save