fix: avoid web fallback after app handoff
All checks were successful
Build & Push Docker Image to Gitea Registry / build-and-push (push) Successful in 11s
All checks were successful
Build & Push Docker Image to Gitea Registry / build-and-push (push) Successful in 11s
This commit is contained in:
103
app.js
103
app.js
@@ -60,11 +60,87 @@ function isMobileDevice() {
|
||||
return /Android|iPhone|iPad|iPod/i.test(navigator.userAgent);
|
||||
}
|
||||
|
||||
function getMobileUrl(service) {
|
||||
function getMobilePlatform() {
|
||||
const userAgent = navigator.userAgent || '';
|
||||
if (/Android/i.test(userAgent)) return 'android';
|
||||
if (/iPhone|iPad|iPod/i.test(userAgent)) return 'ios';
|
||||
return 'other';
|
||||
}
|
||||
|
||||
function getMobileLaunch(service) {
|
||||
if (service.id === 'drive') {
|
||||
return 'nextcloud://openFiles';
|
||||
const fallbackUrl = service.url;
|
||||
if (getMobilePlatform() === 'android') {
|
||||
return {
|
||||
url: `intent://openFiles#Intent;scheme=nextcloud;package=com.nextcloud.client;S.browser_fallback_url=${encodeURIComponent(fallbackUrl)};end`,
|
||||
fallbackUrl
|
||||
};
|
||||
}
|
||||
return {
|
||||
url: 'nextcloud://openFiles',
|
||||
fallbackUrl
|
||||
};
|
||||
}
|
||||
return service.mobileUrl;
|
||||
if (!service.mobileUrl) return null;
|
||||
return {
|
||||
url: service.mobileUrl,
|
||||
fallbackUrl: service.url
|
||||
};
|
||||
}
|
||||
|
||||
function openMobileLaunch(url, fallbackUrl) {
|
||||
let didLeavePage = false;
|
||||
let fallbackTimer = null;
|
||||
let cleanupTimer = null;
|
||||
let launcherFrame = null;
|
||||
|
||||
const cleanup = () => {
|
||||
window.removeEventListener('pagehide', markPageLeft);
|
||||
document.removeEventListener('visibilitychange', handleVisibilityChange);
|
||||
if (fallbackTimer) window.clearTimeout(fallbackTimer);
|
||||
if (cleanupTimer) window.clearTimeout(cleanupTimer);
|
||||
if (launcherFrame) launcherFrame.remove();
|
||||
};
|
||||
|
||||
const markPageLeft = () => {
|
||||
didLeavePage = true;
|
||||
cleanup();
|
||||
};
|
||||
|
||||
const handleVisibilityChange = () => {
|
||||
if (document.visibilityState === 'hidden') {
|
||||
markPageLeft();
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('pagehide', markPageLeft, { once: true });
|
||||
document.addEventListener('visibilitychange', handleVisibilityChange);
|
||||
|
||||
fallbackTimer = window.setTimeout(() => {
|
||||
cleanup();
|
||||
if (!didLeavePage && document.visibilityState === 'visible') {
|
||||
window.location.href = fallbackUrl;
|
||||
}
|
||||
}, 2200);
|
||||
|
||||
if (/^https?:\/\//i.test(url) || /^intent:/i.test(url)) {
|
||||
window.location.href = url;
|
||||
return;
|
||||
}
|
||||
|
||||
launcherFrame = document.createElement('iframe');
|
||||
launcherFrame.hidden = true;
|
||||
launcherFrame.style.display = 'none';
|
||||
launcherFrame.setAttribute('aria-hidden', 'true');
|
||||
document.body.appendChild(launcherFrame);
|
||||
launcherFrame.src = url;
|
||||
|
||||
cleanupTimer = window.setTimeout(() => {
|
||||
if (launcherFrame && launcherFrame.parentNode) {
|
||||
launcherFrame.remove();
|
||||
launcherFrame = null;
|
||||
}
|
||||
}, 2600);
|
||||
}
|
||||
|
||||
function createServiceCard(service) {
|
||||
@@ -92,28 +168,13 @@ function createServiceCard(service) {
|
||||
<span class="card-domain">${service.domain}</span>
|
||||
`;
|
||||
|
||||
const mobileUrl = getMobileUrl(service);
|
||||
if (mobileUrl) {
|
||||
const mobileLaunch = getMobileLaunch(service);
|
||||
if (mobileLaunch) {
|
||||
card.addEventListener('click', (e) => {
|
||||
if (!isMobileDevice()) return;
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
if (/^https?:\/\//i.test(mobileUrl)) {
|
||||
window.location.href = mobileUrl;
|
||||
return;
|
||||
}
|
||||
|
||||
const start = Date.now();
|
||||
// Try to open the native mobile app through its registered URL scheme.
|
||||
window.location.href = mobileUrl;
|
||||
|
||||
// Web fallback if the app is not installed or the scheme is not handled.
|
||||
setTimeout(() => {
|
||||
if (Date.now() - start < 1500) {
|
||||
window.open(service.url, '_blank');
|
||||
}
|
||||
}, 800);
|
||||
openMobileLaunch(mobileLaunch.url, mobileLaunch.fallbackUrl);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -119,6 +119,6 @@
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<script src="/app.js?v=30" defer></script>
|
||||
<script src="/app.js?v=31" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user