-
-
Notifications
You must be signed in to change notification settings - Fork 5.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mobile: Support building for web #10650
Mobile: Support building for web #10650
Conversation
Browser dialogs can show at most two buttons.
…to work/mobile-web
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've left a few comments that might help while reviewing this pull request!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DialogManager.tsx
was added due to the lack of support for Alert.alert
in react-native-web
. On web, it manages showing custom dialogs based on react-native-paper
, with an Alert.alert
compatible API. On other platforms, it continues to show dialogs with Alert.alert
.
It also sets shim.showMessageBox
, allowing plugins and other related code to use the custom dialogs.
@@ -215,6 +217,7 @@ class Dropdown extends Component<DropdownProps, DropdownState> { | |||
<TouchableWithoutFeedback | |||
accessibilityElementsHidden={true} | |||
importantForAccessibility='no-hide-descendants' | |||
aria-hidden={true} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
aria-hidden={true}
is the web version of the "hide from screen readers and other accessibility tools". Currently, we use accessibilityElementsHidden={true}
for this on iOS and importantForAccessibility='no-hide-descendants'
on Android.
Also see the new components/accessibility/AccessibleView.tsx
file.
// allow-popups-to-escape-sandbox: Allows PDF previews to work on target="_blank" links. | ||
// allow-popups: Allows links to open in a new tab. | ||
permissions: 'allow-scripts allow-modals allow-popups allow-popups-to-escape-sandbox', | ||
allow: 'clipboard-write=(self) fullscreen=(self) autoplay=(self) local-fonts=* encrypted-media=*', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// (web only) On web, touching buttons can cause the on-screen keyboard to be dismissed. | ||
// Setting preventKeyboardDismiss overrides this behavior. | ||
preventKeyboardDismiss?: boolean; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently, this is used by the markdown toolbar.
// Intended for web, where resources can't be linked to normally. | ||
public async setResourceFile(id: string, file: Blob) { | ||
this.resourcePathOverrides[id] = URL.createObjectURL(file); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On web, resources are stored in a virtual file system (OPFS). As such, to show them with <img>
/<video>
and tags, we need to create URLs for them.
@@ -53,6 +53,7 @@ const configScreenStyles = (themeId: number): ConfigScreenStyles => { | |||
const settingContainerStyle: ViewStyle = { | |||
flex: 1, | |||
flexDirection: 'row', | |||
flexBasis: 'auto', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
flex
styling is handled slightly differently in react-native-web
when compared to react-native
. In particular, flex-basis
(the default flex
size) seems to default to 0
in some cases.
@@ -225,6 +219,7 @@ class LogScreenComponent extends BaseScreenComponent<Props, State> { | |||
{this.state.filter !== undefined ? filterInput : null} | |||
<FlatList | |||
data={this.state.logEntries} | |||
initialNumToRender={100} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Works around an issue where log lines weren't showing on web.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Related regression testing:
- On Android 13, I have verified that:
- The "select date time" dialog can be opened from the note actions menu for a to-do (from "set alarm").
- Clicking "set date" shows a date/time selection dialog.
- Clicking "save alarm" asks for alarm permissions (I hadn't previously granted them to Joplin).
- Clicking "clear alarm" clears the alarm.
/* | ||
When installed on iOS, this ensures that the status bar color matches the | ||
system light/dark theme. | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure that this is true...
const { reg } = require('../../registry.js'); | ||
const { reg } = require('../../registry'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using registry.js
here was causing two copies of registry
to be included — the copy from files that require('registry')
and the copy from files that require('registry.js')
. As a result, certain global variables/properties in registry
were not initialized in one copy, but were in the other.
To work around this issue, this pull request changes all registry.js
imports to registry
imports. Perhaps using metro
instead of webpack
would be a different way to address this issue?
@personalizedrefrigerator, please let me know when you think this is ready to review |
This should be ready for review! |
Well I'm not going to say I reviewed these 156 files in detail, but what I did review looked good to me. It says there are conflicts though - could you check please? It's a bit strange since it doesn't say on which file. |
this is very interesting |
is there or would there be a docker image with docker compose deployment instructions? |
I don't think that a docker image will be created for this — hosting the web app should just involve hosting static HTML. Hosting requirements:
Additional notes:
|
ok, thank you, that was informative. We have packaged a Joplinserver app for nethserver 8 here https://github.com/geniusdynamics/ns8-joplinserver Hopefully, we can figure out best way to attach or implement the web app on the root doain of the hosted application. |
Summary
[ Try it | Forum post | Implementation progress ]
This pull request allows running Joplin Mobile in a web browser using
react-native-web
and@sqlite.org/sqlite-wasm
.Note: The demo URL has been updated to
https://joplin.github.io/web-app/
.Possible use-cases
Running Joplin on devices that can't easily install software.
Getting feedback on proposed mobile app changes — clicking on a link in a web browser is much easier than installing an Android APK.
Developing and testing plugins for mobile without access to an Android device.
Installing non-recommended plugins on iOS.
Could allow users to try plugins without installing them:
May simplify developing and testing the mobile app:
Related projects
Demo
The
work/mobile-web
branch is deployed to https://personalizedrefrigerator.github.io/joplin/web-client/.Note that this demo works best in a Chromium-based browser. While it loads in Firefox, the initial setup is very slow.
Why not Joplin Desktop?
It seemed simpler to add support for web to the mobile app than the desktop app. In particular, Joplin Desktop depends on a large number of NodeJS-only libraries and APIs (e.g.
fs-extra
).Tasks
@sqlite.org/sqlite-wasm
sqlite-wasm
.bundle.js
— extract plugin assets to separate files.