You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
227 lines
7.5 KiB
227 lines
7.5 KiB
<template>
|
|
<!-- CONTENT -->
|
|
<section id="Content" class="relative w-[100vw] h-[100vh]">
|
|
<div
|
|
class="p-6 bg-white w-full max-w-[calc((100vh-env(safe-area-inset-top)-env(safe-area-inset-bottom))*0.4)] mx-auto"
|
|
>
|
|
<div class="mb-4">
|
|
<h1 class="text-xl text-center font-semibold relative mb-4">
|
|
Redirecting to Time Safari
|
|
</h1>
|
|
|
|
<div v-if="destinationUrl" class="space-y-4">
|
|
<!-- Platform-specific messaging -->
|
|
<div class="text-center text-gray-600 mb-4">
|
|
<p v-if="isMobile">
|
|
{{
|
|
isIOS
|
|
? "Opening Time Safari app on your iPhone..."
|
|
: "Opening Time Safari app on your Android device..."
|
|
}}
|
|
</p>
|
|
<p v-else>Opening Time Safari app...</p>
|
|
<p class="text-sm mt-2">
|
|
<span v-if="isMobile"
|
|
>If the app doesn't open automatically, use one of these
|
|
options:</span
|
|
>
|
|
<span v-else>Choose how you'd like to open this link:</span>
|
|
</p>
|
|
</div>
|
|
|
|
<!-- Deep Link Button -->
|
|
<div class="text-center">
|
|
<a
|
|
:href="deepLinkUrl || '#'"
|
|
class="inline-block bg-blue-600 text-white px-6 py-3 rounded-lg font-medium hover:bg-blue-700 transition-colors"
|
|
@click="handleDeepLinkClick"
|
|
>
|
|
<span v-if="isMobile">Open in Time Safari App</span>
|
|
<span v-else>Try Opening in Time Safari App</span>
|
|
</a>
|
|
</div>
|
|
|
|
<!-- Web Fallback Link -->
|
|
<div class="text-center">
|
|
<a
|
|
:href="webUrl || '#'"
|
|
target="_blank"
|
|
class="inline-block bg-gray-600 text-white px-6 py-3 rounded-lg font-medium hover:bg-gray-700 transition-colors"
|
|
@click="handleWebFallbackClick"
|
|
>
|
|
<span v-if="isMobile">Open in Web Browser Instead</span>
|
|
<span v-else>Open in Web Browser</span>
|
|
</a>
|
|
</div>
|
|
|
|
<!-- Manual Instructions -->
|
|
<div class="text-center text-sm text-gray-500 mt-4">
|
|
<p v-if="isMobile">
|
|
Or manually open:
|
|
<code class="bg-gray-100 px-2 py-1 rounded">{{
|
|
deepLinkUrl
|
|
}}</code>
|
|
</p>
|
|
<p v-else>
|
|
If you have the Time Safari app installed, you can also copy this
|
|
link:
|
|
<code class="bg-gray-100 px-2 py-1 rounded">{{
|
|
deepLinkUrl
|
|
}}</code>
|
|
</p>
|
|
</div>
|
|
|
|
<!-- Platform info for debugging -->
|
|
<div
|
|
v-if="isDevelopment"
|
|
class="text-center text-xs text-gray-400 mt-4"
|
|
>
|
|
<p>
|
|
Platform: {{ isMobile ? (isIOS ? "iOS" : "Android") : "Desktop" }}
|
|
</p>
|
|
<p>User Agent: {{ userAgent.substring(0, 50) }}...</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div v-else-if="pageError" class="text-center text-red-500 mb-4">
|
|
{{ pageError }}
|
|
</div>
|
|
|
|
<div v-else class="text-center text-gray-600">
|
|
<p>Processing redirect...</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { Component, Vue } from "vue-facing-decorator";
|
|
import { RouteLocationNormalizedLoaded, Router } from "vue-router";
|
|
|
|
import { APP_SERVER } from "@/constants/app";
|
|
import { logger } from "@/utils/logger";
|
|
import { errorStringForLog } from "@/libs/endorserServer";
|
|
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
|
|
|
|
@Component({})
|
|
export default class DeepLinkRedirectView extends Vue {
|
|
$router!: Router;
|
|
$route!: RouteLocationNormalizedLoaded;
|
|
pageError: string | null = null;
|
|
destinationUrl: string | null = null; // full path after "/deep-link/"
|
|
deepLinkUrl: string | null = null; // mobile link starting "timesafari://"
|
|
webUrl: string | null = null; // web link, eg "https://timesafari.app/..."
|
|
isDevelopment: boolean = false;
|
|
userAgent: string = "";
|
|
private platformService = PlatformServiceFactory.getInstance();
|
|
|
|
mounted() {
|
|
// Get the path from the route parameter (catch-all parameter)
|
|
const pathParam = this.$route.params.path;
|
|
|
|
// If pathParam is an array (catch-all parameter), join it
|
|
const fullPath = Array.isArray(pathParam) ? pathParam.join("/") : pathParam;
|
|
|
|
// 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;
|
|
|
|
this.openDeepLink();
|
|
}
|
|
|
|
private openDeepLink() {
|
|
if (!this.deepLinkUrl || !this.webUrl) {
|
|
this.pageError =
|
|
"No deep link was provided. Check the URL and try again.";
|
|
return;
|
|
}
|
|
|
|
try {
|
|
// For mobile, try the deep link URL; for desktop, use the web URL
|
|
const redirectUrl = this.isMobile ? this.deepLinkUrl : this.webUrl;
|
|
|
|
// Method 1: Try window.location.href (works on most browsers)
|
|
window.location.href = redirectUrl;
|
|
|
|
// Method 2: Fallback - create and click a link element
|
|
setTimeout(() => {
|
|
try {
|
|
const link = document.createElement("a");
|
|
link.href = redirectUrl;
|
|
link.style.display = "none";
|
|
document.body.appendChild(link);
|
|
link.click();
|
|
document.body.removeChild(link);
|
|
} catch (error) {
|
|
logger.error(
|
|
"Fallback deep link failed: " + errorStringForLog(error),
|
|
);
|
|
this.pageError =
|
|
"Redirecting to the Time Safari app failed. Please use a manual option below.";
|
|
}
|
|
}, 100);
|
|
} catch (error) {
|
|
logger.error("Deep link redirect failed: " + errorStringForLog(error));
|
|
this.pageError =
|
|
"Unable to open the Time Safari app. Please use a manual option below.";
|
|
}
|
|
}
|
|
|
|
private handleDeepLinkClick(event: Event) {
|
|
if (!this.deepLinkUrl) return;
|
|
|
|
// Prevent default to handle the click manually
|
|
event.preventDefault();
|
|
|
|
this.openDeepLink();
|
|
}
|
|
|
|
private handleWebFallbackClick(event: Event) {
|
|
if (!this.webUrl) return;
|
|
|
|
// Get platform capabilities
|
|
const capabilities = this.platformService.getCapabilities();
|
|
|
|
// For mobile, try to open in a new tab/window
|
|
if (capabilities.isMobile) {
|
|
event.preventDefault();
|
|
window.open(this.webUrl, "_blank");
|
|
}
|
|
// For desktop, let the default behavior happen (opens in same tab)
|
|
}
|
|
|
|
// Computed properties for template
|
|
get isMobile(): boolean {
|
|
return this.platformService.getCapabilities().isMobile;
|
|
}
|
|
|
|
get isIOS(): boolean {
|
|
return this.platformService.getCapabilities().isIOS;
|
|
}
|
|
}
|
|
</script>
|
|
|