feat(mobile): add setting to always open web view on launch (#1500)

This commit is contained in:
Aman Harwara
2022-09-09 13:32:23 +05:30
committed by GitHub
parent e2715709d4
commit 320fc3fd96
8 changed files with 64 additions and 16 deletions

View File

@@ -2,11 +2,12 @@
class WebProcessDeviceInterface { class WebProcessDeviceInterface {
constructor(messageSender) { constructor(messageSender) {
this.appVersion = '1.2.3' this.appVersion = '1.2.3'
this.environment = 1 this.environment = 4
this.databases = [] this.databases = []
this.messageSender = messageSender this.messageSender = messageSender
} }
// eslint-disable-next-line @typescript-eslint/no-empty-function
setApplication() {} setApplication() {}
sendMessage(functionName, args) { sendMessage(functionName, args) {

View File

@@ -1,18 +1,19 @@
import { AppStateEventType, AppStateType, TabletModeChangeData } from '@Lib/ApplicationState' import { AppStateEventType, AppStateType, TabletModeChangeData } from '@Lib/ApplicationState'
import { AlwaysOpenWebAppOnLaunchKey } from '@Lib/constants'
import { useHasEditor, useIsLocked } from '@Lib/SnjsHelperHooks' import { useHasEditor, useIsLocked } from '@Lib/SnjsHelperHooks'
import { ScreenStatus } from '@Lib/StatusManager' import { ScreenStatus } from '@Lib/StatusManager'
import { IsDev } from '@Lib/Utils' import { IsDev } from '@Lib/Utils'
import { CompositeNavigationProp, RouteProp } from '@react-navigation/native' import { CompositeNavigationProp, RouteProp, useNavigation } from '@react-navigation/native'
import { createStackNavigator, StackNavigationProp } from '@react-navigation/stack' import { createStackNavigator, StackNavigationProp } from '@react-navigation/stack'
import { HeaderTitleView } from '@Root/Components/HeaderTitleView' import { HeaderTitleView } from '@Root/Components/HeaderTitleView'
import { IoniconsHeaderButton } from '@Root/Components/IoniconsHeaderButton' import { IoniconsHeaderButton } from '@Root/Components/IoniconsHeaderButton'
import { Compose } from '@Root/Screens/Compose/Compose' import { Compose } from '@Root/Screens/Compose/Compose'
import { SCREEN_COMPOSE, SCREEN_NOTES, SCREEN_VIEW_PROTECTED_NOTE } from '@Root/Screens/screens' import { SCREEN_COMPOSE, SCREEN_NOTES, SCREEN_VIEW_PROTECTED_NOTE, SCREEN_WEB_APP } from '@Root/Screens/screens'
import { MainSideMenu } from '@Root/Screens/SideMenu/MainSideMenu' import { MainSideMenu } from '@Root/Screens/SideMenu/MainSideMenu'
import { NoteSideMenu } from '@Root/Screens/SideMenu/NoteSideMenu' import { NoteSideMenu } from '@Root/Screens/SideMenu/NoteSideMenu'
import { ViewProtectedNote } from '@Root/Screens/ViewProtectedNote/ViewProtectedNote' import { ViewProtectedNote } from '@Root/Screens/ViewProtectedNote/ViewProtectedNote'
import { Root } from '@Screens/Root' import { Root } from '@Screens/Root'
import { UuidString } from '@standardnotes/snjs' import { ApplicationEvent, StorageValueModes, UuidString } from '@standardnotes/snjs'
import { ICON_MENU } from '@Style/Icons' import { ICON_MENU } from '@Style/Icons'
import { ThemeService } from '@Style/ThemeService' import { ThemeService } from '@Style/ThemeService'
import { getDefaultDrawerWidth } from '@Style/Utils' import { getDefaultDrawerWidth } from '@Style/Utils'
@@ -123,6 +124,28 @@ export const AppStackComponent = (props: ModalStackNavigationProp<'AppStack'>) =
[application], [application],
) )
const navigation = useNavigation<ModalStackNavigationProp<'AppStack'>['navigation']>()
useEffect(() => {
if (!application) {
return
}
const removeObserver = application.addEventObserver(async (event) => {
if (event === ApplicationEvent.Launched) {
const value = (await application.getValue(AlwaysOpenWebAppOnLaunchKey, StorageValueModes.Nonwrapped)) as
| boolean
| undefined
const shouldAlwaysOpenWebAppOnLaunch = value ?? false
if (shouldAlwaysOpenWebAppOnLaunch) {
navigation.push(SCREEN_WEB_APP)
}
}
})
return removeObserver
}, [application, navigation])
return ( return (
<DrawerLayout <DrawerLayout
ref={drawerRef} ref={drawerRef}

View File

@@ -1,7 +1,5 @@
import { IsDev } from '@Lib/Utils'
export enum ErrorMessage { export enum ErrorMessage {
GeneralText = 'An error occurred. Please try again later.', GeneralText = 'An error occurred. Please try again later.',
} }
export const WebAppOptionEnabled = IsDev export const AlwaysOpenWebAppOnLaunchKey = 'AlwaysOpenWebAppOnLaunch'

View File

@@ -37,7 +37,7 @@ export const MobileWebAppContainer = () => {
class WebProcessDeviceInterface { class WebProcessDeviceInterface {
constructor(messageSender) { constructor(messageSender) {
this.appVersion = '1.2.3' this.appVersion = '1.2.3'
this.environment = 1 this.environment = 4
this.databases = [] this.databases = []
this.messageSender = messageSender this.messageSender = messageSender
} }

View File

@@ -1,4 +1,4 @@
import { WebAppOptionEnabled } from '@Lib/constants' import { AlwaysOpenWebAppOnLaunchKey } from '@Lib/constants'
import { useSignedIn } from '@Lib/SnjsHelperHooks' import { useSignedIn } from '@Lib/SnjsHelperHooks'
import { useNavigation } from '@react-navigation/native' import { useNavigation } from '@react-navigation/native'
import { ButtonCell } from '@Root/Components/ButtonCell' import { ButtonCell } from '@Root/Components/ButtonCell'
@@ -9,9 +9,9 @@ import { TableSection } from '@Root/Components/TableSection'
import { useSafeApplicationContext } from '@Root/Hooks/useSafeApplicationContext' import { useSafeApplicationContext } from '@Root/Hooks/useSafeApplicationContext'
import { ModalStackNavigationProp } from '@Root/ModalStack' import { ModalStackNavigationProp } from '@Root/ModalStack'
import { SCREEN_MANAGE_SESSIONS, SCREEN_SETTINGS, SCREEN_WEB_APP } from '@Root/Screens/screens' import { SCREEN_MANAGE_SESSIONS, SCREEN_SETTINGS, SCREEN_WEB_APP } from '@Root/Screens/screens'
import { ButtonType, PrefKey } from '@standardnotes/snjs' import { ButtonType, PrefKey, StorageValueModes } from '@standardnotes/snjs'
import moment from 'moment' import moment from 'moment'
import React, { useCallback, useMemo, useState } from 'react' import React, { useCallback, useEffect, useMemo, useState } from 'react'
import { Platform } from 'react-native' import { Platform } from 'react-native'
import DocumentPicker from 'react-native-document-picker' import DocumentPicker from 'react-native-document-picker'
import RNFS from 'react-native-fs' import RNFS from 'react-native-fs'
@@ -183,6 +183,18 @@ export const OptionsSection = ({ title, encryptionAvailable }: Props) => {
) )
}, [application.alertService]) }, [application.alertService])
const [shouldAlwaysOpenWebAppOnLaunch, setShouldAlwaysOpenWebAppOnLaunch] = useState(false)
useEffect(() => {
const getSetting = async () => {
const value = (await application.getValue(AlwaysOpenWebAppOnLaunchKey, StorageValueModes.Nonwrapped)) as
| boolean
| undefined
setShouldAlwaysOpenWebAppOnLaunch(value ?? false)
}
void getSetting()
}, [application])
const openWebApp = useCallback(() => { const openWebApp = useCallback(() => {
navigation.push(SCREEN_WEB_APP) navigation.push(SCREEN_WEB_APP)
}, [navigation]) }, [navigation])
@@ -226,9 +238,16 @@ export const OptionsSection = ({ title, encryptionAvailable }: Props) => {
onPress={onExportPress} onPress={onExportPress}
/> />
{WebAppOptionEnabled && ( <ButtonCell testID="openWebApp" leftAligned title="Open Web App" onPress={() => openWebApp()} />
<ButtonCell testID="openWebApp" leftAligned title={'Open Web App'} onPress={() => openWebApp()} /> <SectionedAccessoryTableCell
)} onPress={() => {
const newValue = !shouldAlwaysOpenWebAppOnLaunch
setShouldAlwaysOpenWebAppOnLaunch(newValue)
void application.setValue(AlwaysOpenWebAppOnLaunchKey, newValue, StorageValueModes.Nonwrapped)
}}
text="Always Open Web App On Launch"
selected={() => shouldAlwaysOpenWebAppOnLaunch}
/>
{!signedIn && ( {!signedIn && (
<SectionedAccessoryTableCell <SectionedAccessoryTableCell

View File

@@ -2,6 +2,7 @@ export enum Environment {
Web = 1, Web = 1,
Desktop = 2, Desktop = 2,
Mobile = 3, Mobile = 3,
NativeMobileWeb = 4,
} }
export enum Platform { export enum Platform {

View File

@@ -33,6 +33,7 @@ export function environmentFromString(string: string) {
web: Environment.Web, web: Environment.Web,
desktop: Environment.Desktop, desktop: Environment.Desktop,
mobile: Environment.Mobile, mobile: Environment.Mobile,
nativeMobileWeb: Environment.NativeMobileWeb,
} }
return map[string] return map[string]
} }
@@ -42,6 +43,7 @@ export function environmentToString(environment: Environment) {
[Environment.Web]: 'web', [Environment.Web]: 'web',
[Environment.Desktop]: 'desktop', [Environment.Desktop]: 'desktop',
[Environment.Mobile]: 'mobile', [Environment.Mobile]: 'mobile',
[Environment.NativeMobileWeb]: 'native-mobile-web',
} }
return map[environment] return map[environment]
} }

View File

@@ -291,11 +291,15 @@ export class SNComponentManager
} }
const isWeb = this.environment === Environment.Web const isWeb = this.environment === Environment.Web
const isMobileWebView = this.environment === Environment.NativeMobileWeb
if (nativeFeature) { if (nativeFeature) {
if (!isWeb) { if (!isWeb && !isMobileWebView) {
throw Error('Mobile must override urlForComponent to handle native paths') throw Error('Mobile must override urlForComponent to handle native paths')
} }
const baseUrlRequiredForThemesInsideEditors = window.location.origin let baseUrlRequiredForThemesInsideEditors = window.location.origin
if (isMobileWebView) {
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}`
} }