Use intent and timeout for open in mobile app
This commit is contained in:
parent
bdcc626347
commit
a93ad97aa1
8 changed files with 142 additions and 17 deletions
|
@ -1,7 +1,7 @@
|
|||
<div *ngIf="mobileMsg" class="mobile-msg">
|
||||
<div class="msg ellipsis me-auto" i18n>Open in the application?</div>
|
||||
|
||||
<a class="peertube-button-link secondary-button me-3" [href]="mobileAppUrl">Open</a>
|
||||
<a class="peertube-button-link secondary-button me-3" [href]="androidAppUrl || iosAppUrl" (click)="onOpenClientClick()">Open</a>
|
||||
|
||||
<button class="border-0 p-0" title="Close this message" i18n-title (click)="hideMobileMsg()">
|
||||
<my-global-icon iconName="cross"></my-global-icon>
|
||||
|
|
|
@ -22,7 +22,7 @@ import { SignupLabelComponent } from '@app/shared/shared-main/users/signup-label
|
|||
import { NgbDropdown, NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { ServerConfig } from '@peertube/peertube-models'
|
||||
import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage'
|
||||
import { isAndroid } from '@root-helpers/web-browser'
|
||||
import { isAndroid, isIOS, isIphone } from '@root-helpers/web-browser'
|
||||
import { Subscription } from 'rxjs'
|
||||
import { GlobalIconComponent } from '../shared/shared-icons/global-icon.component'
|
||||
import { ButtonComponent } from '../shared/shared-main/buttons/button.component'
|
||||
|
@ -66,7 +66,8 @@ export class HeaderComponent implements OnInit, OnDestroy {
|
|||
currentInterfaceLanguage: string
|
||||
|
||||
mobileMsg = false
|
||||
mobileAppUrl = ''
|
||||
androidAppUrl = ''
|
||||
iosAppUrl = ''
|
||||
|
||||
private serverConfig: ServerConfig
|
||||
|
||||
|
@ -159,12 +160,15 @@ export class HeaderComponent implements OnInit, OnDestroy {
|
|||
private setupMobileMsg () {
|
||||
if (!this.isInMobileView()) return
|
||||
if (peertubeLocalStorage.getItem(HeaderComponent.LS_HIDE_MOBILE_MSG) === 'true') return
|
||||
if (!isAndroid()) return
|
||||
|
||||
if (!isAndroid() && !isIphone()) return
|
||||
|
||||
this.mobileMsg = true
|
||||
document.body.classList.add('mobile-app-msg')
|
||||
|
||||
const host = window.location.host
|
||||
const intentConfig = this.serverConfig.client.openInApp.android.intent
|
||||
const iosConfig = this.serverConfig.client.openInApp.ios
|
||||
|
||||
const getVideoId = (url: string) => {
|
||||
const matches = url.match(/^\/w\/([^/]+)$/)
|
||||
|
@ -183,19 +187,39 @@ export class HeaderComponent implements OnInit, OnDestroy {
|
|||
|
||||
const url = event.url
|
||||
|
||||
const baseAndroid = `intent://${intentConfig.host}`
|
||||
const fallbackAndroid = `#Intent;scheme=${intentConfig.scheme};S.browser_fallback_url=${intentConfig.fallbackUrl};end`
|
||||
|
||||
const baseIOS = `peertube://${iosConfig.host}`
|
||||
|
||||
const videoId = getVideoId(url)
|
||||
if (videoId) {
|
||||
this.mobileAppUrl = `peertube://joinpeertube.org/video/${videoId}?host=${host}`
|
||||
return
|
||||
}
|
||||
|
||||
const channelId = getChannelId(url)
|
||||
if (channelId) {
|
||||
this.mobileAppUrl = `peertube://joinpeertube.org/video-channel/${channelId}?host=${host}`
|
||||
|
||||
if (videoId) {
|
||||
if (isAndroid()) {
|
||||
this.androidAppUrl = `${baseAndroid}/video/${videoId}?host=${host}${fallbackAndroid}`
|
||||
} else {
|
||||
this.iosAppUrl = `${baseIOS}/video/${videoId}?host=${host}`
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
this.mobileAppUrl = `peertube://joinpeertube.org/?host=${host}`
|
||||
if (channelId) {
|
||||
if (isAndroid()) {
|
||||
this.androidAppUrl = `${baseAndroid}/video-channel/${channelId}?host=${host}${fallbackAndroid}`
|
||||
} else {
|
||||
this.iosAppUrl = `${baseIOS}/video/${videoId}?host=${host}`
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (isAndroid()) {
|
||||
this.androidAppUrl = `${baseAndroid}/?host=${host}${fallbackAndroid}`
|
||||
} else {
|
||||
this.iosAppUrl = `${baseIOS}/?host=${host}`
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -206,6 +230,14 @@ export class HeaderComponent implements OnInit, OnDestroy {
|
|||
peertubeLocalStorage.setItem(HeaderComponent.LS_HIDE_MOBILE_MSG, 'true')
|
||||
}
|
||||
|
||||
onOpenClientClick () {
|
||||
if (!isIOS()) return
|
||||
|
||||
setTimeout(() => {
|
||||
window.location.href = this.serverConfig.client.openInApp.ios.fallbackUrl
|
||||
}, 2500)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
isRegistrationAllowed () {
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import { NgClass, NgIf, NgTemplateOutlet } from '@angular/common'
|
||||
import { Component, Input, OnChanges, ViewChild } from '@angular/core'
|
||||
import { AuthService, Notifier, RedirectService } from '@app/core'
|
||||
import { NgbDropdown, NgbDropdownItem, NgbDropdownMenu, NgbDropdownToggle } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { NgbDropdown, NgbDropdownMenu, NgbDropdownToggle } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { FeedFormat } from '@peertube/peertube-models'
|
||||
import { concat, forkJoin, merge } from 'rxjs'
|
||||
import { Account } from '../shared-main/account/account.model'
|
||||
import { VideoChannel } from '../shared-main/channel/video-channel.model'
|
||||
import { NumberFormatterPipe } from '../shared-main/common/number-formatter.pipe'
|
||||
import { VideoService } from '../shared-main/video/video.service'
|
||||
import { RemoteSubscribeComponent } from './remote-subscribe.component'
|
||||
import { UserSubscriptionService } from './user-subscription.service'
|
||||
|
@ -22,9 +21,7 @@ import { UserSubscriptionService } from './user-subscription.service'
|
|||
NgbDropdown,
|
||||
NgbDropdownToggle,
|
||||
NgbDropdownMenu,
|
||||
NgbDropdownItem,
|
||||
RemoteSubscribeComponent,
|
||||
NumberFormatterPipe
|
||||
RemoteSubscribeComponent
|
||||
]
|
||||
})
|
||||
export class SubscribeButtonComponent implements OnChanges {
|
||||
|
|
|
@ -1077,6 +1077,29 @@ client:
|
|||
# You can automatically redirect your users on this external platform when they click on the login button
|
||||
redirect_on_single_external_auth: false
|
||||
|
||||
open_in_app:
|
||||
android:
|
||||
# Use an intent URL: https://developer.chrome.com/docs/android/intents
|
||||
intent:
|
||||
enabled: true
|
||||
# Host registered by the mobile app
|
||||
host: 'joinpeertube.org'
|
||||
# Scheme registered by the mobile app
|
||||
scheme: 'peertube'
|
||||
# If not having the app on the mobile device, open this page
|
||||
# F-Droid alternative: https://f-droid.org/packages/org.framasoft.peertube/
|
||||
fallback_url: 'https://play.google.com/store/apps/details?id=org.framasoft.peertube'
|
||||
|
||||
ios:
|
||||
# We use a timeout for iOS: if the app is not opened after a few seconds, open the fallback URL
|
||||
enabled: true
|
||||
# Host registered by the mobile app
|
||||
host: 'joinpeertube.org'
|
||||
# Scheme registered by the mobile app
|
||||
scheme: 'peertube'
|
||||
# If not having the app on the mobile device, open this page
|
||||
fallback_url: 'https://apps.apple.com/fr/app/peertube/id6737834858'
|
||||
|
||||
storyboards:
|
||||
# Generate storyboards of local videos using ffmpeg so users can see the video preview in the player while scrubbing the video
|
||||
enabled: true
|
||||
|
|
|
@ -1087,6 +1087,29 @@ client:
|
|||
# You can automatically redirect your users on this external platform when they click on the login button
|
||||
redirect_on_single_external_auth: false
|
||||
|
||||
open_in_app:
|
||||
android:
|
||||
# Use an intent URL: https://developer.chrome.com/docs/android/intents
|
||||
intent:
|
||||
enabled: true
|
||||
# Host registered by the mobile app
|
||||
host: 'joinpeertube.org'
|
||||
# Scheme registered by the mobile app
|
||||
scheme: 'peertube'
|
||||
# If not having the app on the mobile device, open this page
|
||||
# F-Droid alternative: https://f-droid.org/packages/org.framasoft.peertube/
|
||||
fallback_url: 'https://play.google.com/store/apps/details?id=org.framasoft.peertube'
|
||||
|
||||
ios:
|
||||
# We use a timeout for iOS: if the app is not opened after a few seconds, open the fallback URL
|
||||
enabled: true
|
||||
# Host registered by the mobile app
|
||||
host: 'joinpeertube.org'
|
||||
# Scheme registered by the mobile app
|
||||
scheme: 'peertube'
|
||||
# If not having the app on the mobile device, open this page
|
||||
fallback_url: 'https://apps.apple.com/fr/app/peertube/id6737834858'
|
||||
|
||||
storyboards:
|
||||
# Generate storyboards of local videos using ffmpeg so users can see the video preview in the player while scrubbing the video
|
||||
enabled: true
|
||||
|
|
|
@ -51,6 +51,24 @@ export interface ServerConfig {
|
|||
redirectOnSingleExternalAuth: boolean
|
||||
}
|
||||
}
|
||||
|
||||
openInApp: {
|
||||
android: {
|
||||
intent: {
|
||||
enabled: boolean
|
||||
host: string
|
||||
scheme: string
|
||||
fallbackUrl: string
|
||||
}
|
||||
}
|
||||
|
||||
ios: {
|
||||
enabled: boolean
|
||||
host: string
|
||||
scheme: string
|
||||
fallbackUrl: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defaults: {
|
||||
|
|
|
@ -87,6 +87,22 @@ const CONFIG = {
|
|||
LOGIN: {
|
||||
get REDIRECT_ON_SINGLE_EXTERNAL_AUTH () { return config.get<boolean>('client.menu.login.redirect_on_single_external_auth') }
|
||||
}
|
||||
},
|
||||
OPEN_IN_APP: {
|
||||
ANDROID: {
|
||||
INTENT: {
|
||||
get ENABLED () { return config.get<boolean>('client.open_in_app.android.intent.enabled') },
|
||||
get HOST () { return config.get<string>('client.open_in_app.android.intent.host') },
|
||||
get SCHEME () { return config.get<string>('client.open_in_app.android.intent.scheme') },
|
||||
get FALLBACK_URL () { return config.get<string>('client.open_in_app.android.intent.fallback_url') }
|
||||
}
|
||||
},
|
||||
IOS: {
|
||||
get ENABLED () { return config.get<boolean>('client.open_in_app.ios.enabled') },
|
||||
get HOST () { return config.get<string>('client.open_in_app.ios.host') },
|
||||
get SCHEME () { return config.get<string>('client.open_in_app.ios.scheme') },
|
||||
get FALLBACK_URL () { return config.get<string>('client.open_in_app.ios.fallback_url') }
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -66,6 +66,22 @@ class ServerConfigManager {
|
|||
login: {
|
||||
redirectOnSingleExternalAuth: CONFIG.CLIENT.MENU.LOGIN.REDIRECT_ON_SINGLE_EXTERNAL_AUTH
|
||||
}
|
||||
},
|
||||
openInApp: {
|
||||
android: {
|
||||
intent: {
|
||||
enabled: CONFIG.CLIENT.OPEN_IN_APP.ANDROID.INTENT.ENABLED,
|
||||
host: CONFIG.CLIENT.OPEN_IN_APP.ANDROID.INTENT.HOST,
|
||||
scheme: CONFIG.CLIENT.OPEN_IN_APP.ANDROID.INTENT.SCHEME,
|
||||
fallbackUrl: CONFIG.CLIENT.OPEN_IN_APP.ANDROID.INTENT.FALLBACK_URL
|
||||
}
|
||||
},
|
||||
ios: {
|
||||
enabled: CONFIG.CLIENT.OPEN_IN_APP.IOS.ENABLED,
|
||||
host: CONFIG.CLIENT.OPEN_IN_APP.IOS.HOST,
|
||||
scheme: CONFIG.CLIENT.OPEN_IN_APP.IOS.SCHEME,
|
||||
fallbackUrl: CONFIG.CLIENT.OPEN_IN_APP.IOS.FALLBACK_URL
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue