From 546c3b73bd53502b9b8bb5f01ef4dc8300f5e03d Mon Sep 17 00:00:00 2001 From: Fernando Valverde Date: Tue, 25 Jan 2022 09:01:59 -0600 Subject: [PATCH] Android Runtime Banner - Chrome Intent support (#15181) * Android - Chrome Intent * Remove old inline comment * Use regex for context check * Update banner intent + playstore URL * Use single constant for app launch scheme launch * Use location.href instead of location.host * Don't display banner on Firefox (Android) * fix linter changes --- .../runtimeBanner/RuntimeBanner.jsx | 48 ++++++++++++------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/app/javascript/runtimeBanner/RuntimeBanner.jsx b/app/javascript/runtimeBanner/RuntimeBanner.jsx index eae65af85..809bad47a 100644 --- a/app/javascript/runtimeBanner/RuntimeBanner.jsx +++ b/app/javascript/runtimeBanner/RuntimeBanner.jsx @@ -6,6 +6,10 @@ import CloseIcon from '@images/x.svg'; import LogoForem from '@images/logo-forem-app.svg'; const BANNER_DISMISS_KEY = 'runtimeBannerDismissed'; +const APP_LAUNCH_SCHEME = 'com.forem.app'; +const FOREM_APP_STORE_URL = 'https://apps.apple.com/us/app/forem/id1536933197'; +const FOREM_GOOGLE_PLAY_URL = + 'https://play.google.com/store/apps/details?id=com.forem.android'; function dismissBanner() { localStorage.setItem(BANNER_DISMISS_KEY, true); @@ -17,6 +21,18 @@ function removeFromDOM() { container?.remove(); } +function androidTargetIntent() { + return ( + 'intent://scan/#Intent;' + + 'action=android.intent.action.SEND;' + + 'type=text/plain;' + + `S.browser_fallback_url=${FOREM_GOOGLE_PLAY_URL};` + + `S.android.intent.extra.TEXT=${window.location.href};` + + `scheme=${APP_LAUNCH_SCHEME};` + + 'package=com.forem.android;end' + ); +} + function handleDeepLinkFallback() { // These buttons should exist in the DOM in order to attempt the fallback // mechanism (they only exist in the path `/r/mobile`) @@ -30,32 +46,20 @@ function handleDeepLinkFallback() { const urlParams = new URLSearchParams(window.location.search); const targetPath = urlParams.get('deep_link'); - // Constants - they will become dynamic (configurable by creators) in upcoming releases - const FOREM_IOS_SCHEME = 'com.forem.app'; - const FOREM_APP_STORE_URL = - 'https://apps.apple.com/us/app/forem/id1536933197'; - const FOREM_GOOGLE_PLAY_URL = - 'https://play.google.com/store/apps/details?id=to.dev.dev_android'; - if (Runtime.currentOS() === 'iOS') { // The install now must target Apple's AppStore installNowButton.href = FOREM_APP_STORE_URL; // We try to deep link directly by launching a custom scheme and populate // the retry button in case the user will need it - const targetLink = `${FOREM_IOS_SCHEME}://${window.location.host}${targetPath}`; + const targetLink = `${APP_LAUNCH_SCHEME}://${window.location.host}${targetPath}`; retryButton.href = targetLink; window.location.href = targetLink; } else if (Runtime.currentOS() === 'Android') { - const targetIntent = - 'intent://scan/#Intent;scheme=com.forem.app;package=com.forem.app;end'; + const targetIntent = androidTargetIntent(); retryButton.href = targetIntent; installNowButton.href = FOREM_GOOGLE_PLAY_URL; - - // Android support isn't available yet. Android users visiting `/r/mobile` - // will be redirected to the home page so they don't land on a unsupported - // page until this feature is ready for them. - window.location.href = '/'; + window.location.href = targetIntent; } } @@ -68,7 +72,7 @@ export const RuntimeBanner = () => { // The banner shouldn't appear if it was already dismissed or if it doesn't match the context if ( localStorage.getItem(BANNER_DISMISS_KEY) || - Runtime.currentContext() !== 'Browser-iOS' + Runtime.currentContext().match(/Browser-((iOS)|(Android))/) === null ) { removeFromDOM(); return; @@ -85,7 +89,17 @@ export const RuntimeBanner = () => { } const targetPath = `https://${window.location.host}/r/mobile?deep_link=${window.location.pathname}`; - const targetURL = `https://udl.forem.com/${encodeURIComponent(targetPath)}`; + let targetURL = `https://udl.forem.com/${encodeURIComponent(targetPath)}`; + if (Runtime.currentOS() === 'Android') { + if (navigator.userAgent.match(/Gecko\/.+Firefox\/.+$/)) { + // This is the Firefox browser on Android and we can't display the banner + // here because of a bug. Read more: https://github.com/mozilla-mobile/fenix/issues/23397 + return; + } + // Android handles Intents with a fallback URL: playstore URL to install the + // app if not available. It's best to redirect with the intent directly + targetURL = androidTargetIntent(); + } return (