fix: on mobile open links from editor in external browser (#1860)
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
class WebProcessDeviceInterface {
|
class WebProcessDeviceInterface {
|
||||||
constructor(messageSender) {
|
constructor(messageSender) {
|
||||||
this.appVersion = '1.2.3'
|
this.appVersion = '1.2.3'
|
||||||
this.environment = 4
|
this.environment = 3
|
||||||
this.databases = []
|
this.databases = []
|
||||||
this.messageSender = messageSender
|
this.messageSender = messageSender
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
RawKeychainValue,
|
RawKeychainValue,
|
||||||
removeFromArray,
|
removeFromArray,
|
||||||
TransferPayload,
|
TransferPayload,
|
||||||
|
UuidString,
|
||||||
} from '@standardnotes/snjs'
|
} from '@standardnotes/snjs'
|
||||||
import { Alert, Linking, PermissionsAndroid, Platform, StatusBar } from 'react-native'
|
import { Alert, Linking, PermissionsAndroid, Platform, StatusBar } from 'react-native'
|
||||||
import FileViewer from 'react-native-file-viewer'
|
import FileViewer from 'react-native-file-viewer'
|
||||||
@@ -79,6 +80,7 @@ export class MobileDevice implements MobileDeviceInterface {
|
|||||||
private eventObservers: MobileDeviceEventHandler[] = []
|
private eventObservers: MobileDeviceEventHandler[] = []
|
||||||
public isDarkMode = false
|
public isDarkMode = false
|
||||||
public statusBarBgColor: string | undefined
|
public statusBarBgColor: string | undefined
|
||||||
|
private componentUrls: Map<UuidString, string> = new Map()
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private stateObserverService?: AppStateObserverService,
|
private stateObserverService?: AppStateObserverService,
|
||||||
@@ -596,4 +598,16 @@ export class MobileDevice implements MobileDeviceInterface {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addComponentUrl(componentUuid: UuidString, componentUrl: string) {
|
||||||
|
this.componentUrls.set(componentUuid, componentUrl)
|
||||||
|
}
|
||||||
|
|
||||||
|
removeComponentUrl(componentUuid: UuidString) {
|
||||||
|
this.componentUrls.delete(componentUuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
isUrlComponentUrl(url: string): boolean {
|
||||||
|
return Array.from(this.componentUrls.values()).includes(url)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
|||||||
import { Keyboard, Platform } from 'react-native'
|
import { Keyboard, Platform } from 'react-native'
|
||||||
import VersionInfo from 'react-native-version-info'
|
import VersionInfo from 'react-native-version-info'
|
||||||
import { WebView, WebViewMessageEvent } from 'react-native-webview'
|
import { WebView, WebViewMessageEvent } from 'react-native-webview'
|
||||||
|
import { OnShouldStartLoadWithRequest } from 'react-native-webview/lib/WebViewTypes'
|
||||||
import pjson from '../package.json'
|
import pjson from '../package.json'
|
||||||
import { AndroidBackHandlerService } from './AndroidBackHandlerService'
|
import { AndroidBackHandlerService } from './AndroidBackHandlerService'
|
||||||
import { AppStateObserverService } from './AppStateObserverService'
|
import { AppStateObserverService } from './AppStateObserverService'
|
||||||
@@ -23,6 +24,7 @@ export const MobileWebAppContainer = () => {
|
|||||||
|
|
||||||
const MobileWebAppContents = ({ destroyAndReload }: { destroyAndReload: () => void }) => {
|
const MobileWebAppContents = ({ destroyAndReload }: { destroyAndReload: () => void }) => {
|
||||||
const webViewRef = useRef<WebView>(null)
|
const webViewRef = useRef<WebView>(null)
|
||||||
|
|
||||||
const sourceUri = (Platform.OS === 'android' ? 'file:///android_asset/' : '') + 'Web.bundle/src/index.html'
|
const sourceUri = (Platform.OS === 'android' ? 'file:///android_asset/' : '') + 'Web.bundle/src/index.html'
|
||||||
const stateService = useMemo(() => new AppStateObserverService(), [])
|
const stateService = useMemo(() => new AppStateObserverService(), [])
|
||||||
const androidBackHandlerService = useMemo(() => new AndroidBackHandlerService(), [])
|
const androidBackHandlerService = useMemo(() => new AndroidBackHandlerService(), [])
|
||||||
@@ -99,7 +101,7 @@ const MobileWebAppContents = ({ destroyAndReload }: { destroyAndReload: () => vo
|
|||||||
class WebProcessDeviceInterface {
|
class WebProcessDeviceInterface {
|
||||||
constructor(messageSender) {
|
constructor(messageSender) {
|
||||||
this.appVersion = '${pjson.version} (${VersionInfo.buildVersion})'
|
this.appVersion = '${pjson.version} (${VersionInfo.buildVersion})'
|
||||||
this.environment = 4
|
this.environment = 3
|
||||||
this.platform = ${device.platform}
|
this.platform = ${device.platform}
|
||||||
this.databases = []
|
this.databases = []
|
||||||
this.messageSender = messageSender
|
this.messageSender = messageSender
|
||||||
@@ -195,6 +197,34 @@ const MobileWebAppContents = ({ destroyAndReload }: { destroyAndReload: () => vo
|
|||||||
webViewRef.current?.postMessage(JSON.stringify({ messageId, returnValue, messageType: 'reply' }))
|
webViewRef.current?.postMessage(JSON.stringify({ messageId, returnValue, messageType: 'reply' }))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onShouldStartLoadWithRequest: OnShouldStartLoadWithRequest = (request) => {
|
||||||
|
/**
|
||||||
|
* We want to handle link clicks within an editor by opening the browser
|
||||||
|
* instead of loading inline. On iOS, onShouldStartLoadWithRequest is
|
||||||
|
* called for all requests including the initial request to load the editor.
|
||||||
|
* On iOS, clicks in the editors have a navigationType of 'click', but on
|
||||||
|
* Android, this is not the case (no navigationType).
|
||||||
|
* However, on Android, this function is not called for the initial request.
|
||||||
|
* So that might be one way to determine if this request is a click or the
|
||||||
|
* actual editor load request. But I don't think it's safe to rely on this
|
||||||
|
* being the case in the future. So on Android, we'll handle url loads only
|
||||||
|
* if the url isn't equal to the editor url.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const shouldStopRequest =
|
||||||
|
(Platform.OS === 'ios' && request.navigationType === 'click') ||
|
||||||
|
(Platform.OS === 'android' && request.url !== sourceUri)
|
||||||
|
|
||||||
|
const isComponentUrl = device.isUrlComponentUrl(request.url)
|
||||||
|
|
||||||
|
if (shouldStopRequest && !isComponentUrl) {
|
||||||
|
device.openUrl(request.url)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WebView
|
<WebView
|
||||||
ref={webViewRef}
|
ref={webViewRef}
|
||||||
@@ -210,6 +240,7 @@ const MobileWebAppContents = ({ destroyAndReload }: { destroyAndReload: () => vo
|
|||||||
onRenderProcessGone={() => {
|
onRenderProcessGone={() => {
|
||||||
webViewRef.current?.reload()
|
webViewRef.current?.reload()
|
||||||
}}
|
}}
|
||||||
|
onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
|
||||||
allowFileAccess={true}
|
allowFileAccess={true}
|
||||||
allowUniversalAccessFromFileURLs={true}
|
allowUniversalAccessFromFileURLs={true}
|
||||||
injectedJavaScriptBeforeContentLoaded={injectedJS}
|
injectedJavaScriptBeforeContentLoaded={injectedJS}
|
||||||
|
|||||||
@@ -2,5 +2,4 @@ export enum Environment {
|
|||||||
Web = 1,
|
Web = 1,
|
||||||
Desktop = 2,
|
Desktop = 2,
|
||||||
Mobile = 3,
|
Mobile = 3,
|
||||||
NativeMobileWeb = 4,
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,4 +17,7 @@ export interface MobileDeviceInterface extends DeviceInterface {
|
|||||||
downloadBase64AsFile(base64: string, filename: string, saveInTempLocation?: boolean): Promise<string | undefined>
|
downloadBase64AsFile(base64: string, filename: string, saveInTempLocation?: boolean): Promise<string | undefined>
|
||||||
previewFile(base64: string, filename: string): Promise<boolean>
|
previewFile(base64: string, filename: string): Promise<boolean>
|
||||||
exitApp(confirm?: boolean): void
|
exitApp(confirm?: boolean): void
|
||||||
|
addComponentUrl(componentUuid: string, componentUrl: string): void
|
||||||
|
removeComponentUrl(componentUuid: string): void
|
||||||
|
isUrlComponentUrl(url: string): boolean
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* @jest-environment jsdom
|
||||||
|
*/
|
||||||
|
|
||||||
import { SNLog } from './../Log'
|
import { SNLog } from './../Log'
|
||||||
import { PureCryptoInterface } from '@standardnotes/sncrypto-common'
|
import { PureCryptoInterface } from '@standardnotes/sncrypto-common'
|
||||||
import { AlertService, DeviceInterface, namespacedKey, RawStorageKey } from '@standardnotes/services'
|
import { AlertService, DeviceInterface, namespacedKey, RawStorageKey } from '@standardnotes/services'
|
||||||
|
|||||||
@@ -940,7 +940,7 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
|
|||||||
}
|
}
|
||||||
|
|
||||||
isNativeMobileWeb() {
|
isNativeMobileWeb() {
|
||||||
return this.environment === Environment.NativeMobileWeb
|
return this.environment === Environment.Mobile
|
||||||
}
|
}
|
||||||
|
|
||||||
getDeinitMode(): DeinitMode {
|
getDeinitMode(): DeinitMode {
|
||||||
@@ -1353,10 +1353,7 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
|
|||||||
}
|
}
|
||||||
|
|
||||||
private createComponentManager() {
|
private createComponentManager() {
|
||||||
const MaybeSwappedComponentManager = this.getClass<typeof InternalServices.SNComponentManager>(
|
this.componentManagerService = new InternalServices.SNComponentManager(
|
||||||
InternalServices.SNComponentManager,
|
|
||||||
)
|
|
||||||
this.componentManagerService = new MaybeSwappedComponentManager(
|
|
||||||
this.itemManager,
|
this.itemManager,
|
||||||
this.syncService,
|
this.syncService,
|
||||||
this.featuresService,
|
this.featuresService,
|
||||||
@@ -1365,6 +1362,7 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
|
|||||||
this.environment,
|
this.environment,
|
||||||
this.platform,
|
this.platform,
|
||||||
this.internalEventBus,
|
this.internalEventBus,
|
||||||
|
this.deviceInterface,
|
||||||
)
|
)
|
||||||
this.services.push(this.componentManagerService)
|
this.services.push(this.componentManagerService)
|
||||||
}
|
}
|
||||||
@@ -1647,13 +1645,4 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
|
|||||||
this.statusService = new ExternalServices.StatusService(this.internalEventBus)
|
this.statusService = new ExternalServices.StatusService(this.internalEventBus)
|
||||||
this.services.push(this.statusService)
|
this.services.push(this.statusService)
|
||||||
}
|
}
|
||||||
|
|
||||||
private getClass<T>(base: T) {
|
|
||||||
const swapClass = this.options.swapClasses?.find((candidate) => candidate.swap === base)
|
|
||||||
if (swapClass) {
|
|
||||||
return swapClass.with as T
|
|
||||||
} else {
|
|
||||||
return base
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,14 +10,6 @@ export interface ApplicationDisplayOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ApplicationOptionalConfiguratioOptions {
|
export interface ApplicationOptionalConfiguratioOptions {
|
||||||
/**
|
|
||||||
* Gives consumers the ability to provide their own custom
|
|
||||||
* subclass for a service. swapClasses should be an array of key/value pairs
|
|
||||||
* consisting of keys 'swap' and 'with'. 'swap' is the base class you wish to replace,
|
|
||||||
* and 'with' is the custom subclass to use.
|
|
||||||
*/
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
swapClasses?: { swap: any; with: any }[]
|
|
||||||
/**
|
/**
|
||||||
* URL for WebSocket providing permissions and roles information.
|
* URL for WebSocket providing permissions and roles information.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -28,22 +28,11 @@ export function platformToString(platform: Platform) {
|
|||||||
return map[platform]
|
return map[platform]
|
||||||
}
|
}
|
||||||
|
|
||||||
export function environmentFromString(string: string) {
|
|
||||||
const map: Record<string, Environment> = {
|
|
||||||
web: Environment.Web,
|
|
||||||
desktop: Environment.Desktop,
|
|
||||||
mobile: Environment.Mobile,
|
|
||||||
nativeMobileWeb: Environment.NativeMobileWeb,
|
|
||||||
}
|
|
||||||
return map[string]
|
|
||||||
}
|
|
||||||
|
|
||||||
export function environmentToString(environment: Environment) {
|
export function environmentToString(environment: Environment) {
|
||||||
const map = {
|
const map = {
|
||||||
[Environment.Web]: 'web',
|
[Environment.Web]: 'web',
|
||||||
[Environment.Desktop]: 'desktop',
|
[Environment.Desktop]: 'desktop',
|
||||||
[Environment.Mobile]: 'mobile',
|
[Environment.Mobile]: 'native-mobile-web',
|
||||||
[Environment.NativeMobileWeb]: 'native-mobile-web',
|
|
||||||
}
|
}
|
||||||
return map[environment]
|
return map[environment]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,12 @@ import {
|
|||||||
} from '@standardnotes/features'
|
} from '@standardnotes/features'
|
||||||
import { ContentType } from '@standardnotes/common'
|
import { ContentType } from '@standardnotes/common'
|
||||||
import { GenericItem, SNComponent, Environment, Platform } from '@standardnotes/models'
|
import { GenericItem, SNComponent, Environment, Platform } from '@standardnotes/models'
|
||||||
import { DesktopManagerInterface, InternalEventBusInterface, AlertService } from '@standardnotes/services'
|
import {
|
||||||
|
DesktopManagerInterface,
|
||||||
|
InternalEventBusInterface,
|
||||||
|
AlertService,
|
||||||
|
DeviceInterface,
|
||||||
|
} from '@standardnotes/services'
|
||||||
import { ItemManager } from '@Lib/Services/Items/ItemManager'
|
import { ItemManager } from '@Lib/Services/Items/ItemManager'
|
||||||
import { SNFeaturesService } from '@Lib/Services/Features/FeaturesService'
|
import { SNFeaturesService } from '@Lib/Services/Features/FeaturesService'
|
||||||
import { SNComponentManager } from './ComponentManager'
|
import { SNComponentManager } from './ComponentManager'
|
||||||
@@ -27,6 +32,7 @@ describe('featuresService', () => {
|
|||||||
let syncService: SNSyncService
|
let syncService: SNSyncService
|
||||||
let prefsService: SNPreferencesService
|
let prefsService: SNPreferencesService
|
||||||
let internalEventBus: InternalEventBusInterface
|
let internalEventBus: InternalEventBusInterface
|
||||||
|
let device: DeviceInterface
|
||||||
|
|
||||||
const desktopExtHost = 'http://localhost:123'
|
const desktopExtHost = 'http://localhost:123'
|
||||||
|
|
||||||
@@ -53,6 +59,7 @@ describe('featuresService', () => {
|
|||||||
environment,
|
environment,
|
||||||
platform,
|
platform,
|
||||||
internalEventBus,
|
internalEventBus,
|
||||||
|
device,
|
||||||
)
|
)
|
||||||
manager.setDesktopManager(desktopManager)
|
manager.setDesktopManager(desktopManager)
|
||||||
return manager
|
return manager
|
||||||
@@ -81,6 +88,8 @@ describe('featuresService', () => {
|
|||||||
|
|
||||||
internalEventBus = {} as jest.Mocked<InternalEventBusInterface>
|
internalEventBus = {} as jest.Mocked<InternalEventBusInterface>
|
||||||
internalEventBus.publish = jest.fn()
|
internalEventBus.publish = jest.fn()
|
||||||
|
|
||||||
|
device = {} as jest.Mocked<DeviceInterface>
|
||||||
})
|
})
|
||||||
|
|
||||||
const nativeComponent = (identifier?: FeatureIdentifier, file_type?: FeatureDescription['file_type']) => {
|
const nativeComponent = (identifier?: FeatureIdentifier, file_type?: FeatureDescription['file_type']) => {
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ import {
|
|||||||
DesktopManagerInterface,
|
DesktopManagerInterface,
|
||||||
InternalEventBusInterface,
|
InternalEventBusInterface,
|
||||||
AlertService,
|
AlertService,
|
||||||
|
DeviceInterface,
|
||||||
|
isMobileDevice,
|
||||||
} from '@standardnotes/services'
|
} from '@standardnotes/services'
|
||||||
|
|
||||||
const DESKTOP_URL_PREFIX = 'sn://'
|
const DESKTOP_URL_PREFIX = 'sn://'
|
||||||
@@ -82,23 +84,21 @@ export class SNComponentManager
|
|||||||
private environment: Environment,
|
private environment: Environment,
|
||||||
private platform: Platform,
|
private platform: Platform,
|
||||||
protected override internalEventBus: InternalEventBusInterface,
|
protected override internalEventBus: InternalEventBusInterface,
|
||||||
|
private device: DeviceInterface,
|
||||||
) {
|
) {
|
||||||
super(internalEventBus)
|
super(internalEventBus)
|
||||||
this.loggingEnabled = false
|
this.loggingEnabled = false
|
||||||
|
|
||||||
this.addItemObserver()
|
this.addItemObserver()
|
||||||
|
|
||||||
/* On mobile, events listeners are handled by a respective component */
|
window.addEventListener
|
||||||
if (environment !== Environment.Mobile) {
|
? window.addEventListener('focus', this.detectFocusChange, true)
|
||||||
window.addEventListener
|
: window.attachEvent('onfocusout', this.detectFocusChange)
|
||||||
? window.addEventListener('focus', this.detectFocusChange, true)
|
window.addEventListener
|
||||||
: window.attachEvent('onfocusout', this.detectFocusChange)
|
? window.addEventListener('blur', this.detectFocusChange, true)
|
||||||
window.addEventListener
|
: window.attachEvent('onblur', this.detectFocusChange)
|
||||||
? window.addEventListener('blur', this.detectFocusChange, true)
|
|
||||||
: window.attachEvent('onblur', this.detectFocusChange)
|
|
||||||
|
|
||||||
window.addEventListener('message', this.onWindowMessage, true)
|
window.addEventListener('message', this.onWindowMessage, true)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get isDesktop(): boolean {
|
get isDesktop(): boolean {
|
||||||
@@ -143,7 +143,7 @@ export class SNComponentManager
|
|||||||
this.removeItemObserver?.()
|
this.removeItemObserver?.()
|
||||||
;(this.removeItemObserver as unknown) = undefined
|
;(this.removeItemObserver as unknown) = undefined
|
||||||
|
|
||||||
if (window && !this.isMobile) {
|
if (window) {
|
||||||
window.removeEventListener('focus', this.detectFocusChange, true)
|
window.removeEventListener('focus', this.detectFocusChange, true)
|
||||||
window.removeEventListener('blur', this.detectFocusChange, true)
|
window.removeEventListener('blur', this.detectFocusChange, true)
|
||||||
window.removeEventListener('message', this.onWindowMessage, true)
|
window.removeEventListener('message', this.onWindowMessage, true)
|
||||||
@@ -221,9 +221,23 @@ export class SNComponentManager
|
|||||||
addItemObserver(): void {
|
addItemObserver(): void {
|
||||||
this.removeItemObserver = this.itemManager.addObserver<SNComponent>(
|
this.removeItemObserver = this.itemManager.addObserver<SNComponent>(
|
||||||
[ContentType.Component, ContentType.Theme],
|
[ContentType.Component, ContentType.Theme],
|
||||||
({ changed, inserted, source }) => {
|
({ changed, inserted, removed, source }) => {
|
||||||
const items = [...changed, ...inserted]
|
const items = [...changed, ...inserted]
|
||||||
this.handleChangedComponents(items, source)
|
this.handleChangedComponents(items, source)
|
||||||
|
|
||||||
|
const device = this.device
|
||||||
|
if (isMobileDevice(device) && 'addComponentUrl' in device) {
|
||||||
|
inserted.forEach((component) => {
|
||||||
|
const url = this.urlForComponent(component)
|
||||||
|
if (url) {
|
||||||
|
device.addComponentUrl(component.uuid, url)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
removed.forEach((component) => {
|
||||||
|
device.removeComponentUrl(component.uuid)
|
||||||
|
})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -271,9 +285,6 @@ export class SNComponentManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
getActiveThemes(): SNTheme[] {
|
getActiveThemes(): SNTheme[] {
|
||||||
if (this.environment === Environment.Mobile) {
|
|
||||||
throw Error('getActiveThemes must be handled separately by mobile')
|
|
||||||
}
|
|
||||||
return this.componentsForArea(ComponentArea.Themes).filter((theme) => {
|
return this.componentsForArea(ComponentArea.Themes).filter((theme) => {
|
||||||
return theme.active
|
return theme.active
|
||||||
}) as SNTheme[]
|
}) as SNTheme[]
|
||||||
@@ -301,14 +312,10 @@ export class SNComponentManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const isWeb = this.environment === Environment.Web
|
const isMobile = this.environment === Environment.Mobile
|
||||||
const isMobileWebView = this.environment === Environment.NativeMobileWeb
|
|
||||||
if (nativeFeature) {
|
if (nativeFeature) {
|
||||||
if (!isWeb && !isMobileWebView) {
|
|
||||||
throw Error('Mobile must override urlForComponent to handle native paths')
|
|
||||||
}
|
|
||||||
let baseUrlRequiredForThemesInsideEditors = window.location.origin
|
let baseUrlRequiredForThemesInsideEditors = window.location.origin
|
||||||
if (isMobileWebView) {
|
if (isMobile) {
|
||||||
baseUrlRequiredForThemesInsideEditors = window.location.href.split('/index.html')[0]
|
baseUrlRequiredForThemesInsideEditors = window.location.href.split('/index.html')[0]
|
||||||
}
|
}
|
||||||
return `${baseUrlRequiredForThemesInsideEditors}/components/assets/${component.identifier}/${nativeFeature.index_path}`
|
return `${baseUrlRequiredForThemesInsideEditors}/components/assets/${component.identifier}/${nativeFeature.index_path}`
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ export class DiskStorageService extends Services.AbstractService implements Serv
|
|||||||
public setEncryptionPolicy(encryptionPolicy: Services.StorageEncryptionPolicy, persist = true): void {
|
public setEncryptionPolicy(encryptionPolicy: Services.StorageEncryptionPolicy, persist = true): void {
|
||||||
if (
|
if (
|
||||||
encryptionPolicy === Services.StorageEncryptionPolicy.Disabled &&
|
encryptionPolicy === Services.StorageEncryptionPolicy.Disabled &&
|
||||||
![Environment.Mobile, Environment.NativeMobileWeb].includes(this.environment)
|
![Environment.Mobile].includes(this.environment)
|
||||||
) {
|
) {
|
||||||
throw Error('Disabling storage encryption is only available on mobile.')
|
throw Error('Disabling storage encryption is only available on mobile.')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export class MobileWebReceiver {
|
|||||||
this.handleNativeEvent(nativeEvent)
|
this.handleNativeEvent(nativeEvent)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('Error parsing message from React Native', error)
|
console.log('[MobileWebReceiver] Error parsing message from React Native', error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export async function openSubscriptionDashboard(application: SNApplication) {
|
|||||||
|
|
||||||
const url = `${window.dashboardUrl}?subscription_token=${token}`
|
const url = `${window.dashboardUrl}?subscription_token=${token}`
|
||||||
|
|
||||||
if (application.deviceInterface.environment === Environment.NativeMobileWeb) {
|
if (application.deviceInterface.environment === Environment.Mobile) {
|
||||||
application.deviceInterface.openUrl(url)
|
application.deviceInterface.openUrl(url)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user