feat(dev): option to render web app inside the mobile app (#1164)
* feat (WIP): render web app inside the mobile app * fix: web app loading * chore: build scripts related to mobile web bundle * feat: show WebView header, which lets to close the WebView * refactor: remove extra component * chore: correct type * chore: remove TODO Co-authored-by: Mo <mo@standardnotes.com>
This commit is contained in:
4
packages/mobile/.gitignore
vendored
4
packages/mobile/.gitignore
vendored
@@ -21,6 +21,8 @@ DerivedData
|
||||
*.ipa
|
||||
*.xcuserstate
|
||||
|
||||
html/Web.bundle/src/web-src
|
||||
|
||||
.env
|
||||
|
||||
# Android/IntelliJ
|
||||
@@ -75,4 +77,4 @@ ios-release.bundle.map
|
||||
|
||||
codeqldb
|
||||
|
||||
vendor/bundle
|
||||
vendor/bundle
|
||||
|
||||
29
packages/mobile/MobileWebAppContainer.tsx
Normal file
29
packages/mobile/MobileWebAppContainer.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import React from 'react'
|
||||
import { Platform } from 'react-native'
|
||||
import { WebView } from 'react-native-webview'
|
||||
|
||||
export const MobileWebAppContainer = () => {
|
||||
const sourceUri = (Platform.OS === 'android' ? 'file:///android_asset/' : '') + 'Web.bundle/loader.html'
|
||||
const params = 'platform=' + Platform.OS
|
||||
const injectedJS = `
|
||||
if (!window.location.search) {
|
||||
var link = document.getElementById('web-bundle-progress-bar');
|
||||
link.href = './src/index.html?${params}';
|
||||
link.click();
|
||||
}`
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-empty-function */
|
||||
return (
|
||||
<WebView
|
||||
source={{ uri: sourceUri }}
|
||||
originWhitelist={['*']}
|
||||
onLoad={() => {}}
|
||||
onError={(err) => console.error('An error has occurred', err)}
|
||||
onHttpError={() => console.error('An HTTP error occurred')}
|
||||
onMessage={() => {}}
|
||||
allowFileAccess={true}
|
||||
injectedJavaScript={injectedJS}
|
||||
/>
|
||||
)
|
||||
/* eslint-enable @typescript-eslint/no-empty-function */
|
||||
}
|
||||
@@ -219,6 +219,9 @@ android {
|
||||
}
|
||||
}
|
||||
}
|
||||
sourceSets {
|
||||
main { assets.srcDirs = ['src/main/assets', '../../html'] }
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
1
packages/mobile/html/Web.bundle/loader.html
Normal file
1
packages/mobile/html/Web.bundle/loader.html
Normal file
@@ -0,0 +1 @@
|
||||
<a id="web-bundle-progress-bar" href="#"/></a>
|
||||
25
packages/mobile/html/Web.bundle/src/index.html
Normal file
25
packages/mobile/html/Web.bundle/src/index.html
Normal file
@@ -0,0 +1,25 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible" />
|
||||
<meta content="width=device-width, initial-scale=1" name="viewport" />
|
||||
<link rel="stylesheet" href="web-src/app.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script>
|
||||
window.defaultSyncServer = "https://api.standardnotes.com";
|
||||
window.defaultFilesHost = "https://files.standardnotes.com";
|
||||
window.enabledUnfinishedFeatures = "" === 'true';
|
||||
window.websocketUrl = "";
|
||||
window.purchaseUrl = "https://standardnotes.com/purchase";
|
||||
window.plansUrl = "https://standardnotes.com/plans";
|
||||
window.dashboardUrl = "https://standardnotes.com/dashboard";
|
||||
</script>
|
||||
|
||||
<script src="web-src/app.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -434,7 +434,7 @@ PODS:
|
||||
- RNZipArchive/Core (6.0.8):
|
||||
- React-Core
|
||||
- SSZipArchive (= 2.2.3)
|
||||
- sn-textview (1.0.2):
|
||||
- sn-textview (1.1.0):
|
||||
- React-Core
|
||||
- SNReactNative (1.0.1):
|
||||
- React-Core
|
||||
@@ -749,7 +749,7 @@ SPEC CHECKSUMS:
|
||||
RNSVG: 302bfc9905bd8122f08966dc2ce2d07b7b52b9f8
|
||||
RNVectorIcons: fcc2f6cb32f5735b586e66d14103a74ce6ad61f8
|
||||
RNZipArchive: 3f89b114cfeb89dac027fc5c7afd7e58d3dc4ebf
|
||||
sn-textview: aaeeb41791e7d1784072adfb6b610db9b764acda
|
||||
sn-textview: 494186ad03660daa52b1d3fd7b50b116b550f925
|
||||
SNReactNative: b5e9e529c175c13f3a618e27c76cf3071213d5e1
|
||||
SSZipArchive: 62d4947b08730e4cda640473b0066d209ff033c9
|
||||
TrustKit: 073855e3adecd317417bda4ac9e9ac54a2e3b9f2
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
CD7D8400277FF8CB00915D89 /* Red@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = CD7D83FD277FF8CB00915D89 /* Red@3x.png */; };
|
||||
CD7D8401277FF8CB00915D89 /* Red.png in Resources */ = {isa = PBXBuildFile; fileRef = CD7D83FE277FF8CB00915D89 /* Red.png */; };
|
||||
CD7D8402277FF8CB00915D89 /* Red@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = CD7D83FF277FF8CB00915D89 /* Red@2x.png */; };
|
||||
D261494528699DCE00B17102 /* Web.bundle in Resources */ = {isa = PBXBuildFile; fileRef = D261494428699DCE00B17102 /* Web.bundle */; };
|
||||
D261494628699DCE00B17102 /* Web.bundle in Resources */ = {isa = PBXBuildFile; fileRef = D261494428699DCE00B17102 /* Web.bundle */; };
|
||||
DD3D1CE428EC1C8BA0C49211 /* libPods-StandardNotes.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 41388EB4F886116157DA092C /* libPods-StandardNotes.a */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
@@ -67,6 +69,7 @@
|
||||
CD7D83FD277FF8CB00915D89 /* Red@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Red@3x.png"; sourceTree = "<group>"; };
|
||||
CD7D83FE277FF8CB00915D89 /* Red.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Red.png; sourceTree = "<group>"; };
|
||||
CD7D83FF277FF8CB00915D89 /* Red@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Red@2x.png"; sourceTree = "<group>"; };
|
||||
D261494428699DCE00B17102 /* Web.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = Web.bundle; path = ../html/Web.bundle; sourceTree = "<group>"; };
|
||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
@@ -132,6 +135,7 @@
|
||||
13B07FAE1A68108700A75B9A /* StandardNotes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D261494428699DCE00B17102 /* Web.bundle */,
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.m */,
|
||||
CD7D5EE527801F10005FE1BF /* StandardNotes.entitlements */,
|
||||
@@ -308,6 +312,7 @@
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D261494528699DCE00B17102 /* Web.bundle in Resources */,
|
||||
CD7D8401277FF8CB00915D89 /* Red.png in Resources */,
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
||||
CD7D8402277FF8CB00915D89 /* Red@2x.png in Resources */,
|
||||
@@ -321,6 +326,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
CD7D5ED4278015D2005FE1BF /* Red.png in Resources */,
|
||||
D261494628699DCE00B17102 /* Web.bundle in Resources */,
|
||||
CD7D5EE3278016E3005FE1BF /* Dev.xcassets in Resources */,
|
||||
CD7D5ED5278015D2005FE1BF /* Images.xcassets in Resources */,
|
||||
CD7D5ED6278015D2005FE1BF /* Red@2x.png in Resources */,
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
"lint:fix": "yarn lint --fix",
|
||||
"format": "prettier ./src",
|
||||
"format:fix": "yarn format --write",
|
||||
"build": "yarn android:bundle && yarn install:pods",
|
||||
"build": "yarn web:bundle && yarn install:pods && yarn android:bundle",
|
||||
"web:bundle": "cp -r ../web/dist/. html/Web.bundle/src/web-src/",
|
||||
"pods": "yarn install:pods",
|
||||
"tsc": "tsc --noEmit",
|
||||
"start": "react-native start",
|
||||
@@ -43,6 +44,7 @@
|
||||
"@standardnotes/sncrypto-common": "1.9.0",
|
||||
"@standardnotes/snjs": "^2.118.3",
|
||||
"@standardnotes/stylekit": "5.29.3",
|
||||
"@standardnotes/web": "workspace:^",
|
||||
"@types/styled-components-react-native": "5.1.3",
|
||||
"js-base64": "^3.7.2",
|
||||
"moment": "^2.29.2",
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
import { IsDev } from '@Lib/Utils'
|
||||
|
||||
export enum ErrorMessage {
|
||||
GeneralText = 'An error occurred. Please try again later.',
|
||||
}
|
||||
|
||||
export const WebAppOptionEnabled = IsDev
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
SCREEN_MANAGE_SESSIONS,
|
||||
SCREEN_SETTINGS,
|
||||
SCREEN_UPLOADED_FILES_LIST,
|
||||
SCREEN_WEB_APP,
|
||||
} from '@Root/Screens/screens'
|
||||
import { Settings } from '@Root/Screens/Settings/Settings'
|
||||
import { UploadedFilesList } from '@Root/Screens/UploadedFilesList/UploadedFilesList'
|
||||
@@ -29,6 +30,7 @@ import React, { memo, useContext } from 'react'
|
||||
import { Platform } from 'react-native'
|
||||
import { HeaderButtons, Item } from 'react-navigation-header-buttons'
|
||||
import { ThemeContext } from 'styled-components'
|
||||
import { MobileWebAppContainer } from '../MobileWebAppContainer'
|
||||
import { HeaderTitleParams, TEnvironment } from './App'
|
||||
import { ApplicationContext } from './ApplicationContext'
|
||||
import { AppStackComponent } from './AppStack'
|
||||
@@ -63,6 +65,7 @@ export type ModalStackNavigatorParamList = {
|
||||
title?: string
|
||||
text: string
|
||||
}
|
||||
[SCREEN_WEB_APP]: undefined
|
||||
}
|
||||
|
||||
export type ModalStackNavigationProp<T extends keyof ModalStackNavigatorParamList> = {
|
||||
@@ -303,6 +306,7 @@ export const MainStackComponent = ({ env }: { env: TEnvironment }) => {
|
||||
})}
|
||||
component={WorkspaceInputModal}
|
||||
/>
|
||||
<MainStack.Screen name={SCREEN_WEB_APP} options={() => ({ title: 'App' })} component={MobileWebAppContainer} />
|
||||
</MainStack.Navigator>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { WebAppOptionEnabled } from '@Lib/constants'
|
||||
import { useSignedIn } from '@Lib/SnjsHelperHooks'
|
||||
import { useNavigation } from '@react-navigation/native'
|
||||
import { ButtonCell } from '@Root/Components/ButtonCell'
|
||||
@@ -7,7 +8,7 @@ import { SectionHeader } from '@Root/Components/SectionHeader'
|
||||
import { TableSection } from '@Root/Components/TableSection'
|
||||
import { useSafeApplicationContext } from '@Root/Hooks/useSafeApplicationContext'
|
||||
import { ModalStackNavigationProp } from '@Root/ModalStack'
|
||||
import { SCREEN_MANAGE_SESSIONS, SCREEN_SETTINGS } from '@Root/Screens/screens'
|
||||
import { SCREEN_MANAGE_SESSIONS, SCREEN_SETTINGS, SCREEN_WEB_APP } from '@Root/Screens/screens'
|
||||
import { ButtonType, PrefKey } from '@standardnotes/snjs'
|
||||
import moment from 'moment'
|
||||
import React, { useCallback, useMemo, useState } from 'react'
|
||||
@@ -182,6 +183,10 @@ export const OptionsSection = ({ title, encryptionAvailable }: Props) => {
|
||||
)
|
||||
}, [application.alertService])
|
||||
|
||||
const openWebApp = useCallback(() => {
|
||||
navigation.push(SCREEN_WEB_APP)
|
||||
}, [navigation])
|
||||
|
||||
return (
|
||||
<TableSection>
|
||||
<SectionHeader title={title} />
|
||||
@@ -221,6 +226,10 @@ export const OptionsSection = ({ title, encryptionAvailable }: Props) => {
|
||||
onPress={onExportPress}
|
||||
/>
|
||||
|
||||
{WebAppOptionEnabled && (
|
||||
<ButtonCell testID="openWebApp" leftAligned title={'Open Web App'} onPress={() => openWebApp()} />
|
||||
)}
|
||||
|
||||
{!signedIn && (
|
||||
<SectionedAccessoryTableCell
|
||||
testID="lastExportDate"
|
||||
|
||||
@@ -16,3 +16,5 @@ export const SCREEN_MANAGE_SESSIONS = 'ManageSessions' as const
|
||||
export const MODAL_BLOCKING_ALERT = 'ModalBlockingAlert' as const
|
||||
|
||||
export const SCREEN_VIEW_PROTECTED_NOTE = 'ViewProtectedNote' as const
|
||||
|
||||
export const SCREEN_WEB_APP = 'WebApp' as const
|
||||
|
||||
@@ -5718,6 +5718,7 @@ __metadata:
|
||||
"@standardnotes/sncrypto-common": 1.9.0
|
||||
"@standardnotes/snjs": ^2.118.3
|
||||
"@standardnotes/stylekit": 5.29.3
|
||||
"@standardnotes/web": "workspace:^"
|
||||
"@types/detox": ^18.1.0
|
||||
"@types/faker": ^6.6.9
|
||||
"@types/jest": ^27.4.1
|
||||
@@ -6187,7 +6188,7 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@standardnotes/web@workspace:*, @standardnotes/web@workspace:packages/web":
|
||||
"@standardnotes/web@workspace:*, @standardnotes/web@workspace:^, @standardnotes/web@workspace:packages/web":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@standardnotes/web@workspace:packages/web"
|
||||
dependencies:
|
||||
|
||||
Reference in New Issue
Block a user