forked from trent_larson/crowd-funder-for-time-pwa
add support for deep-link query parameters
This commit is contained in:
@@ -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,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
|
||||
Reference in New Issue
Block a user