mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-08-31 19:19:34 +02:00
Compare commits
15 Commits
fix/export
...
feat-gecko
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
26a61d4d06 | ||
|
|
847fa3a3ad | ||
|
|
4ab949b398 | ||
|
|
ae43aa8c60 | ||
|
|
edf0a5bed3 | ||
|
|
f20b08edcf | ||
|
|
51858199fd | ||
|
|
26bc156323 | ||
|
|
7907f03dd2 | ||
|
|
5ca58d5e69 | ||
|
|
8826145854 | ||
|
|
6f8ae6f805 | ||
|
|
8dbc74f3c2 | ||
|
|
cae14c351b | ||
|
|
327cb9b208 |
64
.github/workflows/android.publish.internal.yml
vendored
Normal file
64
.github/workflows/android.publish.internal.yml
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
name: Publish @notesnook/android-internal
|
||||
|
||||
on: workflow_dispatch
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 40
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- uses: actions/setup-node@master
|
||||
with:
|
||||
node-version: '16'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: |
|
||||
apps/mobile/package-lock.json
|
||||
apps/web/package-lock.json
|
||||
packages/core/package-lock.json
|
||||
packages/crypto/package-lock.json
|
||||
packages/crypto-worker/package-lock.json
|
||||
packages/editor-mobile/package-lock.json
|
||||
packages/editor/package-lock.json
|
||||
packages/logger/package-lock.json
|
||||
packages/streamable-fs/package-lock.json
|
||||
packages/theme/package-lock.json
|
||||
|
||||
- name: Use specific Java version for the builds
|
||||
uses: joschi/setup-jdk@v2
|
||||
with:
|
||||
java-version: '11'
|
||||
architecture: 'x64'
|
||||
|
||||
- name: Install node modules
|
||||
run: |
|
||||
npm ci
|
||||
- name: Make Gradlew Executable
|
||||
run: cd apps/mobile/native/android && chmod +x ./gradlew
|
||||
|
||||
- name: Build unsigned app bundle
|
||||
run: yarn release:android:bundle
|
||||
|
||||
- name: Sign app bundle for Playstore release
|
||||
id: sign_app
|
||||
uses: r0adkll/sign-android-release@v1
|
||||
with:
|
||||
releaseDirectory: apps/mobile/native/android/app/build/outputs/bundle/release
|
||||
signingKeyBase64: ${{ secrets.SIGNING_KEY }}
|
||||
alias: ${{ secrets.ALIAS }}
|
||||
keyStorePassword: ${{ secrets.KEY_PASSWORD }}
|
||||
keyPassword: ${{ secrets.KEY_PASSWORD }}
|
||||
|
||||
- name: Publish to Playstore
|
||||
id: deploy
|
||||
uses: r0adkll/upload-google-play@v1
|
||||
with:
|
||||
serviceAccountJsonPlainText: ${{ secrets.SERVICE_ACCOUNT_JSON }}
|
||||
packageName: com.streetwriters.notesnook
|
||||
releaseFile: ${{steps.sign_app.outputs.signedReleaseFile}}
|
||||
track: internal
|
||||
status: completed
|
||||
whatsNewDirectory: apps/mobile/native/android/releasenotes/
|
||||
5
apps/mobile/.gitignore
vendored
5
apps/mobile/.gitignore
vendored
@@ -6,6 +6,11 @@ artifacts/
|
||||
|
||||
native/android/app/src/main/assets/
|
||||
|
||||
native/android/geckoview/src/main/jniLibs/arm64-v8a
|
||||
native/android/geckoview/src/main/jniLibs/armeabi-v7a
|
||||
native/android/geckoview/src/main/jniLibs/x86
|
||||
native/android/geckoview/src/main/jniLibs/x86_64
|
||||
|
||||
*Issues.md
|
||||
build_cache/
|
||||
#
|
||||
|
||||
@@ -45,6 +45,7 @@ import { useEditor } from "./tiptap/use-editor";
|
||||
import { useEditorEvents } from "./tiptap/use-editor-events";
|
||||
import { editorController } from "./tiptap/utils";
|
||||
import { useLayoutEffect } from "react";
|
||||
import { useIsGeckoViewEnabled } from "../../utils/split-module-loader";
|
||||
|
||||
const style: ViewStyle = {
|
||||
height: "100%",
|
||||
@@ -53,6 +54,7 @@ const style: ViewStyle = {
|
||||
alignSelf: "center",
|
||||
backgroundColor: "transparent"
|
||||
};
|
||||
|
||||
const onShouldStartLoadWithRequest = (request: ShouldStartLoadRequest) => {
|
||||
if (request.url.includes("https")) {
|
||||
if (Platform.OS === "ios" && !request.isTopFrame) return true;
|
||||
@@ -63,6 +65,7 @@ const onShouldStartLoadWithRequest = (request: ShouldStartLoadRequest) => {
|
||||
}
|
||||
};
|
||||
|
||||
let GeckoView: any = null;
|
||||
const Editor = React.memo(
|
||||
forwardRef<
|
||||
{
|
||||
@@ -89,7 +92,8 @@ const Editor = React.memo(
|
||||
noToolbar,
|
||||
noHeader
|
||||
});
|
||||
|
||||
const { enabled: useGeckoView, loading, view } = useIsGeckoViewEnabled();
|
||||
GeckoView = view.current;
|
||||
useImperativeHandle(ref, () => ({
|
||||
get: () => editor
|
||||
}));
|
||||
@@ -124,8 +128,12 @@ const Editor = React.memo(
|
||||
|
||||
const onError = useCallback(() => {
|
||||
editor.setLoading(true);
|
||||
if (useGeckoView) {
|
||||
//@ts-ignore
|
||||
editor.ref?.connectMessagingPort();
|
||||
}
|
||||
setTimeout(() => editor.setLoading(false), 10);
|
||||
}, [editor]);
|
||||
}, [editor, useGeckoView]);
|
||||
|
||||
useEffect(() => {
|
||||
eSubscribeEvent("webview_reset", onError);
|
||||
@@ -145,48 +153,71 @@ const Editor = React.memo(
|
||||
editorController.current = editor;
|
||||
}
|
||||
|
||||
return editor.loading ? null : (
|
||||
return editor.loading || loading ? null : (
|
||||
<>
|
||||
<WebView
|
||||
testID={notesnook.editor.id}
|
||||
ref={editor.ref}
|
||||
onLoad={editor.onLoad}
|
||||
onRenderProcessGone={onError}
|
||||
nestedScrollEnabled
|
||||
onError={onError}
|
||||
injectedJavaScriptBeforeContentLoaded={`
|
||||
{!useGeckoView || editorId !== "" || !GeckoView ? (
|
||||
<WebView
|
||||
testID={notesnook.editor.id}
|
||||
ref={editor.ref}
|
||||
onLoad={editor.onLoad}
|
||||
onRenderProcessGone={onError}
|
||||
nestedScrollEnabled
|
||||
onError={onError}
|
||||
injectedJavaScriptBeforeContentLoaded={`
|
||||
globalThis.readonly=${readonly};
|
||||
globalThis.noToolbar=${noToolbar};
|
||||
globalThis.noHeader=${noHeader};
|
||||
`}
|
||||
injectedJavaScript={`globalThis.sessionId="${editor.sessionId}";`}
|
||||
javaScriptEnabled={true}
|
||||
focusable={true}
|
||||
setSupportMultipleWindows={false}
|
||||
overScrollMode="never"
|
||||
scrollEnabled={false}
|
||||
keyboardDisplayRequiresUserAction={false}
|
||||
onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
|
||||
cacheMode="LOAD_DEFAULT"
|
||||
cacheEnabled={true}
|
||||
domStorageEnabled={true}
|
||||
bounces={false}
|
||||
setBuiltInZoomControls={false}
|
||||
setDisplayZoomControls={false}
|
||||
allowFileAccess={true}
|
||||
scalesPageToFit={true}
|
||||
hideKeyboardAccessoryView={false}
|
||||
allowsFullscreenVideo={true}
|
||||
allowFileAccessFromFileURLs={true}
|
||||
allowUniversalAccessFromFileURLs={true}
|
||||
originWhitelist={["*"]}
|
||||
source={{
|
||||
uri: EDITOR_URI
|
||||
}}
|
||||
style={style}
|
||||
autoManageStatusBarEnabled={false}
|
||||
onMessage={onMessage || undefined}
|
||||
/>
|
||||
injectedJavaScript={`globalThis.sessionId="${editor.sessionId}";`}
|
||||
javaScriptEnabled={true}
|
||||
focusable={true}
|
||||
setSupportMultipleWindows={false}
|
||||
overScrollMode="never"
|
||||
scrollEnabled={false}
|
||||
keyboardDisplayRequiresUserAction={false}
|
||||
onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
|
||||
cacheMode="LOAD_DEFAULT"
|
||||
cacheEnabled={true}
|
||||
domStorageEnabled={true}
|
||||
bounces={false}
|
||||
setBuiltInZoomControls={false}
|
||||
setDisplayZoomControls={false}
|
||||
allowFileAccess={true}
|
||||
scalesPageToFit={true}
|
||||
hideKeyboardAccessoryView={false}
|
||||
allowsFullscreenVideo={true}
|
||||
allowFileAccessFromFileURLs={true}
|
||||
allowUniversalAccessFromFileURLs={true}
|
||||
originWhitelist={["*"]}
|
||||
source={{
|
||||
uri: EDITOR_URI
|
||||
}}
|
||||
style={style}
|
||||
autoManageStatusBarEnabled={false}
|
||||
onMessage={onMessage || undefined}
|
||||
/>
|
||||
) : (
|
||||
<GeckoView
|
||||
//@ts-ignore
|
||||
ref={editor.ref}
|
||||
source={{
|
||||
uri: EDITOR_URI
|
||||
}}
|
||||
onLoadingStart={(e) => {
|
||||
console.log(e.nativeEvent);
|
||||
}}
|
||||
injectedJavaScript={`globalThis.sessionId="${editor.sessionId}";`}
|
||||
style={style}
|
||||
onLoadingFinish={editor.onLoad}
|
||||
onMessagingDisconnected={() => {
|
||||
//@ts-ignore
|
||||
editor.ref?.connectMessagingPort();
|
||||
}}
|
||||
onLoadingError={onError}
|
||||
onMessage={onMessage}
|
||||
/>
|
||||
)}
|
||||
|
||||
{editorId === "shareEditor" ? null : (
|
||||
<AppSection editor={editor} editorId={editorId} />
|
||||
)}
|
||||
|
||||
@@ -31,7 +31,7 @@ import { sleep } from "../../../utils/time";
|
||||
import { NoteType } from "../../../utils/types";
|
||||
import { Settings } from "./types";
|
||||
import { getResponse, randId, textInput } from "./utils";
|
||||
|
||||
import SettingsService from "../../../services/settings";
|
||||
type Action = { job: string; id: string };
|
||||
|
||||
async function call(webview: RefObject<WebView | undefined>, action?: Action) {
|
||||
@@ -78,13 +78,18 @@ class Commands {
|
||||
focus = async () => {
|
||||
if (!this.ref.current) return;
|
||||
if (Platform.OS === "android") {
|
||||
//this.ref.current?.requestFocus();
|
||||
setTimeout(async () => {
|
||||
if (!this.ref) return;
|
||||
textInput.current?.focus();
|
||||
await this.doAsync("editor.commands.focus()");
|
||||
this.ref?.current?.requestFocus();
|
||||
}, 1);
|
||||
const isGeckoView = SettingsService.get().useGeckoView;
|
||||
setTimeout(
|
||||
async () => {
|
||||
if (!this.ref) return;
|
||||
textInput.current?.focus();
|
||||
setTimeout(async () => {
|
||||
this.ref?.current?.requestFocus();
|
||||
await this.doAsync("editor.commands.focus()");
|
||||
}, 10);
|
||||
},
|
||||
isGeckoView ? 100 : 1
|
||||
);
|
||||
} else {
|
||||
await sleep(200);
|
||||
await this.doAsync("editor.commands.focus()");
|
||||
|
||||
@@ -273,6 +273,10 @@ export const useEditorEvents = (
|
||||
const onMessage = useCallback(
|
||||
(event: WebViewMessageEvent) => {
|
||||
const data = event.nativeEvent.data;
|
||||
if (data?.startsWith("Error")) {
|
||||
console.log("WebView Error", data);
|
||||
return;
|
||||
}
|
||||
const editorMessage = JSON.parse(data) as EditorMessage;
|
||||
if (
|
||||
editorMessage.sessionId !== editor.sessionId &&
|
||||
|
||||
@@ -36,7 +36,7 @@ import { useTagStore } from "../../../stores/use-tag-store";
|
||||
import { ThemeStore, useThemeStore } from "../../../stores/use-theme-store";
|
||||
import { eClearEditor, eOnLoadNote } from "../../../utils/events";
|
||||
import { tabBarRef } from "../../../utils/global-refs";
|
||||
import { timeConverter } from "../../../utils/time";
|
||||
import { sleep, timeConverter } from "../../../utils/time";
|
||||
import { NoteType } from "../../../utils/types";
|
||||
import Commands from "./commands";
|
||||
import { Content, EditorState, Note, SavePayload } from "./types";
|
||||
@@ -52,6 +52,7 @@ import {
|
||||
} from "./utils";
|
||||
import { EVENTS } from "@notesnook/core/common";
|
||||
import SettingsService from "../../../services/settings";
|
||||
import { useSettingStore } from "../../../stores/use-setting-store";
|
||||
|
||||
export const useEditor = (
|
||||
editorId = "",
|
||||
@@ -59,6 +60,7 @@ export const useEditor = (
|
||||
onChange?: (html: string) => void,
|
||||
theme?: ThemeStore["colors"]
|
||||
) => {
|
||||
const useGeckoView = useSettingStore((state) => state.settings.useGeckoView);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [sessionId, setSessionId] = useState<string>(makeSessionId());
|
||||
const sessionIdRef = useRef(sessionId);
|
||||
@@ -119,11 +121,12 @@ export const useEditor = (
|
||||
);
|
||||
|
||||
const onReady = useCallback(async () => {
|
||||
if (useGeckoView) await sleep(3000);
|
||||
if (!(await isEditorLoaded(editorRef, sessionIdRef.current))) {
|
||||
overlay(true);
|
||||
setLoading(true);
|
||||
}
|
||||
}, [overlay]);
|
||||
}, [overlay,useGeckoView]);
|
||||
|
||||
useEffect(() => {
|
||||
state.current.saveCount = 0;
|
||||
|
||||
@@ -34,12 +34,13 @@ import { DDS } from "../../services/device-detection";
|
||||
import { useSettingStore } from "../../stores/use-setting-store";
|
||||
import { useThemeStore } from "../../stores/use-theme-store";
|
||||
import { editorRef } from "../../utils/global-refs";
|
||||
import { useIsGeckoViewEnabled } from "../../utils/split-module-loader";
|
||||
import { ProgressBar } from "./progress";
|
||||
import { editorController, editorState, textInput } from "./tiptap/utils";
|
||||
export const EditorWrapper = ({ width }) => {
|
||||
const colors = useThemeStore((state) => state.colors);
|
||||
const deviceMode = useSettingStore((state) => state.deviceMode);
|
||||
const loading = false;
|
||||
const { loading } = useIsGeckoViewEnabled();
|
||||
const insets = useGlobalSafeAreaInsets();
|
||||
const floating = useIsFloatingKeyboard();
|
||||
const introCompleted = useSettingStore(
|
||||
|
||||
@@ -22,6 +22,7 @@ import { AccentColorPicker, HomagePageSelector } from "./appearance";
|
||||
import { AutomaticBackupsSelector } from "./backup-restore";
|
||||
import DebugLogs from "./debug";
|
||||
import { ConfigureToolbar } from "./editor/configure-toolbar";
|
||||
import { GeckoViewLoader } from "./gecko-view-loader";
|
||||
import SoundPicker from "./sound-picker";
|
||||
import { Subscription } from "./subscription";
|
||||
export const components: { [name: string]: ReactElement } = {
|
||||
@@ -31,5 +32,6 @@ export const components: { [name: string]: ReactElement } = {
|
||||
subscription: <Subscription />,
|
||||
configuretoolbar: <ConfigureToolbar />,
|
||||
"debug-logs": <DebugLogs />,
|
||||
"sound-picker": <SoundPicker />
|
||||
"sound-picker": <SoundPicker />,
|
||||
"gecko-view-loader": <GeckoViewLoader />
|
||||
};
|
||||
|
||||
@@ -18,10 +18,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import Clipboard from "@react-native-clipboard/clipboard";
|
||||
import { LogMessage } from "@streetwriters/logger";
|
||||
import { LogMessage } from "@notesnook/logger";
|
||||
import { format, LogLevel, logManager } from "@notesnook/core/logger";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { FlatList, Platform, TouchableOpacity, View } from "react-native";
|
||||
import { Platform, TouchableOpacity, View } from "react-native";
|
||||
import { FlashList } from "@shopify/flash-list";
|
||||
import * as ScopedStorage from "react-native-scoped-storage";
|
||||
import RNFetchBlob from "rn-fetch-blob";
|
||||
import Storage from "../../common/database/storage";
|
||||
@@ -226,110 +227,102 @@ export default function DebugLogs() {
|
||||
/>
|
||||
</View>
|
||||
|
||||
{currentLog && (
|
||||
<FlatList
|
||||
ListHeaderComponent={
|
||||
<View
|
||||
style={{
|
||||
paddingHorizontal: 12,
|
||||
marginBottom: 10,
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
backgroundColor: colors.bg,
|
||||
justifyContent: "space-between"
|
||||
}}
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
alignItems: "center"
|
||||
}}
|
||||
>
|
||||
<Paragraph>{currentLog.key}</Paragraph>
|
||||
|
||||
<IconButton
|
||||
customStyle={{
|
||||
width: 30,
|
||||
height: 30,
|
||||
marginHorizontal: 5
|
||||
}}
|
||||
onPress={() => {
|
||||
const index = logs.findIndex(
|
||||
(l) => l.key === currentLog.key
|
||||
);
|
||||
if (index === 0) return;
|
||||
setCurrentLog(logs[index - 1]);
|
||||
}}
|
||||
size={20}
|
||||
name="chevron-left"
|
||||
color={colors.icon}
|
||||
/>
|
||||
|
||||
<IconButton
|
||||
customStyle={{
|
||||
width: 30,
|
||||
height: 30
|
||||
}}
|
||||
onPress={() => {
|
||||
const index = logs.findIndex(
|
||||
(l) => l.key === currentLog.key
|
||||
);
|
||||
if (index === logs.length - 1) return;
|
||||
setCurrentLog(logs[index + 1]);
|
||||
}}
|
||||
size={20}
|
||||
name="chevron-right"
|
||||
color={colors.icon}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row"
|
||||
}}
|
||||
>
|
||||
<IconButton
|
||||
onPress={copyLogs}
|
||||
size={20}
|
||||
customStyle={{
|
||||
width: 30,
|
||||
height: 30,
|
||||
marginRight: 5
|
||||
}}
|
||||
name="content-copy"
|
||||
color={colors.gray}
|
||||
/>
|
||||
<IconButton
|
||||
onPress={downloadLogs}
|
||||
customStyle={{
|
||||
width: 30,
|
||||
height: 30,
|
||||
marginRight: 5
|
||||
}}
|
||||
size={20}
|
||||
name="download"
|
||||
color={colors.gray}
|
||||
/>
|
||||
|
||||
<IconButton
|
||||
onPress={clearLogs}
|
||||
customStyle={{
|
||||
width: 30,
|
||||
height: 30,
|
||||
marginRight: 5
|
||||
}}
|
||||
size={20}
|
||||
name="delete"
|
||||
color={colors.gray}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
}
|
||||
{currentLog ? (
|
||||
<View
|
||||
style={{
|
||||
flex: 1,
|
||||
width: "100%"
|
||||
paddingHorizontal: 12,
|
||||
marginBottom: 10,
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
backgroundColor: colors.bg,
|
||||
justifyContent: "space-between"
|
||||
}}
|
||||
stickyHeaderIndices={[0]}
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
alignItems: "center"
|
||||
}}
|
||||
>
|
||||
<Paragraph>{currentLog?.key}</Paragraph>
|
||||
|
||||
<IconButton
|
||||
customStyle={{
|
||||
width: 30,
|
||||
height: 30,
|
||||
marginHorizontal: 10
|
||||
}}
|
||||
onPress={() => {
|
||||
const index = logs.findIndex((l) => l.key === currentLog?.key);
|
||||
if (index === 0) return;
|
||||
setCurrentLog(logs[index - 1]);
|
||||
}}
|
||||
size={24}
|
||||
name="chevron-left"
|
||||
color={colors.icon}
|
||||
/>
|
||||
|
||||
<IconButton
|
||||
customStyle={{
|
||||
width: 30,
|
||||
height: 30
|
||||
}}
|
||||
onPress={() => {
|
||||
const index = logs.findIndex((l) => l.key === currentLog?.key);
|
||||
if (index === logs.length - 1) return;
|
||||
setCurrentLog(logs[index + 1]);
|
||||
}}
|
||||
size={24}
|
||||
name="chevron-right"
|
||||
color={colors.icon}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row"
|
||||
}}
|
||||
>
|
||||
<IconButton
|
||||
onPress={copyLogs}
|
||||
size={24}
|
||||
customStyle={{
|
||||
width: 30,
|
||||
height: 30,
|
||||
marginRight: 10
|
||||
}}
|
||||
name="content-copy"
|
||||
color={colors.gray}
|
||||
/>
|
||||
<IconButton
|
||||
onPress={downloadLogs}
|
||||
customStyle={{
|
||||
width: 30,
|
||||
height: 30,
|
||||
marginRight: 10
|
||||
}}
|
||||
size={24}
|
||||
name="download"
|
||||
color={colors.gray}
|
||||
/>
|
||||
|
||||
<IconButton
|
||||
onPress={clearLogs}
|
||||
customStyle={{
|
||||
width: 30,
|
||||
height: 30,
|
||||
marginRight: 10
|
||||
}}
|
||||
size={24}
|
||||
name="delete"
|
||||
color={colors.gray}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
) : null}
|
||||
|
||||
{currentLog ? (
|
||||
<FlashList
|
||||
ListFooterComponent={
|
||||
<View
|
||||
style={{
|
||||
@@ -339,8 +332,9 @@ export default function DebugLogs() {
|
||||
}
|
||||
data={currentLog.logs}
|
||||
renderItem={renderItem}
|
||||
estimatedItemSize={120}
|
||||
/>
|
||||
)}
|
||||
) : null}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
142
apps/mobile/app/screens/settings/gecko-view-loader.tsx
Normal file
142
apps/mobile/app/screens/settings/gecko-view-loader.tsx
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
This file is part of the Notesnook project (https://notesnook.com/)
|
||||
|
||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import React, { useEffect } from "react";
|
||||
import { View } from "react-native";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { ProgressBarComponent } from "../../components/ui/svg/lazy";
|
||||
import Paragraph from "../../components/ui/typography/paragraph";
|
||||
import { ToastEvent } from "../../services/event-manager";
|
||||
import SettingsService from "../../services/settings";
|
||||
import { useThemeStore } from "../../stores/use-theme-store";
|
||||
import { formatBytes } from "../../utils";
|
||||
import { SIZE } from "../../utils/size";
|
||||
import {
|
||||
SplitModuleLoader,
|
||||
useIsGeckoViewEnabled,
|
||||
useSplitInstallSessionState
|
||||
} from "../../utils/split-module-loader";
|
||||
import { toCamelCase } from "../notes/common";
|
||||
export const GeckoViewLoader = () => {
|
||||
const { enabled, installed } = useIsGeckoViewEnabled();
|
||||
const colors = useThemeStore((state) => state.colors);
|
||||
const state = useSplitInstallSessionState();
|
||||
useEffect(() => {
|
||||
if (state?.status === "installed") {
|
||||
SettingsService.set({
|
||||
useGeckoView: true
|
||||
});
|
||||
}
|
||||
}, [state?.status]);
|
||||
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
width: "100%",
|
||||
marginTop: 10
|
||||
}}
|
||||
>
|
||||
<>
|
||||
{state && !installed ? null : (
|
||||
<Paragraph
|
||||
style={{ marginTop: 10, marginBottom: 10 }}
|
||||
color={colors.icon}
|
||||
size={SIZE.sm}
|
||||
>
|
||||
{installed
|
||||
? "GeckoView is already downloaded & installed on this device."
|
||||
: "Installing GeckoView will download additional data on your phone."}
|
||||
</Paragraph>
|
||||
)}
|
||||
|
||||
{!installed && state ? null : (
|
||||
<>
|
||||
{!installed ? (
|
||||
<Button
|
||||
title="Install GeckoView"
|
||||
type="accent"
|
||||
style={{
|
||||
borderRadius: 100,
|
||||
width: 250,
|
||||
alignSelf: "flex-start"
|
||||
}}
|
||||
onPress={async () => {
|
||||
try {
|
||||
SettingsService.set({
|
||||
useGeckoView: true
|
||||
});
|
||||
await SplitModuleLoader.installModule("geckoview");
|
||||
} catch (e) {
|
||||
ToastEvent.error(e as Error);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Button
|
||||
title={enabled ? "Disable GeckoView" : "Enable GeckoView"}
|
||||
type="accent"
|
||||
style={{
|
||||
borderRadius: 100,
|
||||
width: 250,
|
||||
alignSelf: "flex-start"
|
||||
}}
|
||||
onPress={() => {
|
||||
SettingsService.set({
|
||||
useGeckoView: !enabled
|
||||
});
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
{!installed && state ? (
|
||||
<>
|
||||
<Paragraph
|
||||
style={{ marginTop: 10, marginBottom: 5 }}
|
||||
color={colors.icon}
|
||||
size={SIZE.xs + 1}
|
||||
>
|
||||
{toCamelCase(state.status)}
|
||||
{state.status === "downloading"
|
||||
? ` (${formatBytes(state.downloaded)}/${formatBytes(
|
||||
state.total
|
||||
)})`
|
||||
: ""}
|
||||
</Paragraph>
|
||||
<ProgressBarComponent
|
||||
height={5}
|
||||
width={300}
|
||||
animated={true}
|
||||
useNativeDriver
|
||||
indeterminate={state.status !== "downloading"}
|
||||
progress={
|
||||
state.status === "downloading"
|
||||
? (state?.downloaded || 0) / (state?.total || 0)
|
||||
: undefined
|
||||
}
|
||||
unfilledColor={colors.nav}
|
||||
color={colors.accent}
|
||||
borderWidth={0}
|
||||
/>
|
||||
</>
|
||||
) : null}
|
||||
</>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
@@ -949,9 +949,26 @@ export const settingsGroups: SettingSection[] = [
|
||||
"Close and reopen the current opened note or restart the app for changes to take affect."
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "experimental-features",
|
||||
type: "screen",
|
||||
name: "Experimental features",
|
||||
description: "Use these features with caution",
|
||||
sections: [
|
||||
{
|
||||
id: "use-gecko-view",
|
||||
type: "component",
|
||||
name: "Install GeckoView",
|
||||
description:
|
||||
"If you edit large notes on your phone & have experienced lags & slow performance, you can use GeckoView for the editor which performs many times better than the default Android System WebView.",
|
||||
component: "gecko-view-loader"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
id: "help-support",
|
||||
name: "Help and support",
|
||||
|
||||
@@ -73,6 +73,7 @@ export type Settings = {
|
||||
corsProxy: string;
|
||||
disableRealtimeSync?: boolean;
|
||||
notificationSound?: Sound & { platform: PlatformOSType };
|
||||
useGeckoView?:boolean
|
||||
};
|
||||
|
||||
type DimensionsType = {
|
||||
|
||||
109
apps/mobile/app/utils/split-module-loader/index.ts
Normal file
109
apps/mobile/app/utils/split-module-loader/index.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
This file is part of the Notesnook project (https://notesnook.com/)
|
||||
|
||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import { NativeModules, DeviceEventEmitter } from "react-native";
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
import { useSettingStore } from "../../stores/use-setting-store";
|
||||
import { Config } from "react-native-config";
|
||||
import { DatabaseLogger } from "../../common/database";
|
||||
interface SplitInstallSessionState {
|
||||
status:
|
||||
| "pending"
|
||||
| "downloading"
|
||||
| "downloaded"
|
||||
| "installing"
|
||||
| "installed"
|
||||
| "failed"
|
||||
| "cancelled"
|
||||
| "requires_user_confirmation"
|
||||
| "user_permission_granted"
|
||||
| "user_permission_canceled"
|
||||
| "canceling";
|
||||
total?: number;
|
||||
downloaded?: number;
|
||||
errorCode?: number;
|
||||
}
|
||||
|
||||
export const useSplitInstallSessionState = () => {
|
||||
const [state, setState] = useState<SplitInstallSessionState | undefined>();
|
||||
|
||||
useEffect(() => {
|
||||
const subscription = DeviceEventEmitter.addListener(
|
||||
"onModuleLoaderStateUpdate",
|
||||
(data: SplitInstallSessionState) => {
|
||||
DatabaseLogger.log("onModuleLoaderStateUpdate" + data?.status);
|
||||
setState(data);
|
||||
}
|
||||
);
|
||||
return () => {
|
||||
subscription?.remove();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return state;
|
||||
};
|
||||
|
||||
export const SplitModuleLoader: {
|
||||
installModule: (name: string) => Promise<number>;
|
||||
getInstalledModules: () => Promise<string[]>;
|
||||
} = NativeModules.SplitModuleLoader;
|
||||
|
||||
export const useIsGeckoViewEnabled = () => {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [enabled, setEnabled] = useState(false);
|
||||
const useGeckoView = useSettingStore((state) => state.settings.useGeckoView);
|
||||
const ref = useRef();
|
||||
const state = useSplitInstallSessionState();
|
||||
useEffect(() => {
|
||||
if (Config.GITHUB_RELEASE === "true") {
|
||||
if (Config.enableGecko === "true") {
|
||||
ref.current = require("@ammarahmed/react-native-geckoview").default;
|
||||
setEnabled(true);
|
||||
DatabaseLogger.log("Using GeckoView");
|
||||
} else {
|
||||
DatabaseLogger.log("Using Android WebView");
|
||||
}
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
SplitModuleLoader?.getInstalledModules()
|
||||
.then((modules) => {
|
||||
if (modules?.includes("geckoview")) {
|
||||
ref.current = require("@ammarahmed/react-native-geckoview").default;
|
||||
console.log(modules);
|
||||
setEnabled(true);
|
||||
DatabaseLogger.log("Using GeckoView");
|
||||
} else {
|
||||
DatabaseLogger.log("Using Android WebView");
|
||||
}
|
||||
setLoading(false);
|
||||
})
|
||||
.catch((e) => {
|
||||
setLoading(false);
|
||||
setEnabled(false);
|
||||
DatabaseLogger.error(e);
|
||||
DatabaseLogger.log("Using Android WebView");
|
||||
});
|
||||
}, [loading, useGeckoView, state?.status]);
|
||||
return {
|
||||
enabled: enabled && useGeckoView,
|
||||
loading: loading,
|
||||
installed: enabled,
|
||||
view: ref
|
||||
};
|
||||
};
|
||||
@@ -160,12 +160,13 @@ android {
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
multiDexEnabled true
|
||||
versionCode 2024
|
||||
versionCode 2031
|
||||
versionName getNpmVersion()
|
||||
testBuildType System.getProperty('testBuildType', 'debug')
|
||||
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
||||
missingDimensionStrategy "store", "play"
|
||||
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
||||
buildConfigField "boolean", "IS_GITHUB_RELEASE", isGithubRelease().toString()
|
||||
if (isNewArchitectureEnabled()) {
|
||||
// We configure the NDK build only if you decide to opt-in for the New Architecture.
|
||||
externalNativeBuild {
|
||||
@@ -193,7 +194,7 @@ android {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (isNewArchitectureEnabled()) {
|
||||
// We configure the NDK build only if you decide to opt-in for the New Architecture.
|
||||
externalNativeBuild {
|
||||
@@ -234,14 +235,27 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
splits {
|
||||
abi {
|
||||
reset()
|
||||
enable enableSeparateBuildPerCPUArchitecture
|
||||
universalApk false // If true, also generate a universal APK
|
||||
include (*reactNativeArchitectures())
|
||||
if (isGithubRelease()) {
|
||||
splits {
|
||||
abi {
|
||||
reset()
|
||||
enable enableSeparateBuildPerCPUArchitecture
|
||||
universalApk false // If true, also generate a universal APK
|
||||
include (*reactNativeArchitectures())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dynamicFeatures = [':geckoview']
|
||||
bundle {
|
||||
abi {
|
||||
enableSplit true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
signingConfigs {
|
||||
debug {
|
||||
storeFile file('debug.keystore')
|
||||
@@ -256,6 +270,7 @@ android {
|
||||
keyPassword 'android'
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
signingConfig signingConfigs.debug
|
||||
@@ -272,32 +287,53 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
if (!isGeckoEnabled()) {
|
||||
packagingOptions {
|
||||
exclude "lib/**/libmozglue.so"
|
||||
exclude "lib/**/libxul.so"
|
||||
exclude "lib/**/libnss3.so"
|
||||
exclude "lib/**/libnssckbi.so"
|
||||
exclude "lib/**/libmozavutil.so"
|
||||
exclude "lib/**/libsoftokn3.so"
|
||||
exclude "lib/**/libmozavcodec.so"
|
||||
exclude "lib/**/libipcclientcerts.so"
|
||||
exclude "lib/**/libfreebl3.so"
|
||||
exclude "lib/**/libplugin-container.so"
|
||||
//exclude "lib/**/liblgpllibs.so"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// applicationVariants are e.g. debug, release
|
||||
applicationVariants.all { variant ->
|
||||
applicationVariants.all { variant -> {
|
||||
variant.outputs.each { output ->
|
||||
// For each separate APK per architecture, set a unique version code as described here:
|
||||
// https://developer.android.com/studio/build/configure-apk-splits.html
|
||||
def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
|
||||
def abi = output.getFilter(OutputFile.ABI)
|
||||
if (abi != null) { // null for the universal-debug, universal-release variants
|
||||
output.versionCodeOverride =
|
||||
versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
|
||||
if (isGithubRelease()) {
|
||||
def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
|
||||
def abi = output.getFilter(OutputFile.ABI)
|
||||
if (abi != null) { // null for the universal-debug, universal-release variants
|
||||
output.versionCodeOverride =
|
||||
versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
|
||||
}
|
||||
} else {
|
||||
output.versionCodeOverride = 4 * 1048576 + defaultConfig.versionCode
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||
//noinspection GradleDynamicVersion
|
||||
implementation "com.facebook.react:react-native:+" // From node_modules
|
||||
if (!isGithubRelease()) {
|
||||
implementation 'com.google.android.play:feature-delivery:2.0.1'
|
||||
}
|
||||
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
|
||||
implementation 'androidx.multidex:multidex:2.0.1'
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.9.2'
|
||||
@@ -361,8 +397,21 @@ task copyFiles(type: Copy) {
|
||||
from '../../../../../packages/editor-mobile/build.bundle'
|
||||
into './src/main/assets'
|
||||
}
|
||||
|
||||
task deleteFilesMessaging(type: Delete) {
|
||||
delete './src/main/assets/messaging'
|
||||
}
|
||||
|
||||
task copyFilesMessaging(type: Copy) {
|
||||
from '../../../node_modules/@ammarahmed/react-native-geckoview/extensions'
|
||||
into './src/main/assets'
|
||||
}
|
||||
|
||||
copyFilesMessaging.dependsOn(deleteFilesMessaging);
|
||||
preBuild.dependsOn(copyFilesMessaging);
|
||||
|
||||
copyFiles.dependsOn(deleteFiles)
|
||||
preBuild.dependsOn(copyFiles)
|
||||
preBuild.dependsOn(copyFiles);
|
||||
|
||||
|
||||
project.ext.vectoricons = [
|
||||
@@ -382,4 +431,12 @@ def isNewArchitectureEnabled() {
|
||||
return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true"
|
||||
}
|
||||
|
||||
def isGithubRelease() {
|
||||
return project.hasProperty("GITHUB_RELEASE") && project.GITHUB_RELEASE == "true"
|
||||
}
|
||||
|
||||
def isGeckoEnabled() {
|
||||
return project.hasProperty("enableGecko") && project.enableGecko == "true"
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -57,4 +57,8 @@
|
||||
-keep class org.apache.commons.io.** { *; }
|
||||
|
||||
# Background fetch
|
||||
-keep class com.transistorsoft.rnbackgroundfetch.HeadlessTask { *; }
|
||||
-keep class com.transistorsoft.rnbackgroundfetch.HeadlessTask { *; }
|
||||
|
||||
# SplitModuleLoader
|
||||
-keep class com.streetwriters.notesnook.** { *; }
|
||||
-keep class com.google.android.play.core.** { *; }
|
||||
@@ -152,12 +152,12 @@
|
||||
android:resource="@xml/file_viewer_provider_paths" />
|
||||
</provider>
|
||||
|
||||
<receiver android:exported="true" android:name=".BootRecieverService" >
|
||||
<!-- <receiver android:exported="true" android:name=".BootRecieverService" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
</receiver> -->
|
||||
|
||||
|
||||
</application>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.streetwriters.notesnook;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
@@ -18,8 +17,6 @@ import java.util.Map;
|
||||
|
||||
import androidx.multidex.MultiDexApplication;
|
||||
|
||||
import com.facebook.react.bridge.JavaScriptExecutorFactory;
|
||||
//import com.facebook.react.modules.systeminfo.AndroidInfoHelpers;
|
||||
import com.facebook.react.TurboReactPackage;
|
||||
import com.facebook.react.module.model.ReactModuleInfo;
|
||||
import com.facebook.react.module.model.ReactModuleInfoProvider;
|
||||
@@ -34,10 +31,8 @@ import com.streetwriters.notesnook.newarchitecture.MainApplicationReactNativeHos
|
||||
import cl.json.RNShareModule;
|
||||
import px.tooltips.RNTooltipsModule;
|
||||
//import io.csie.kudo.reactnative.v8.executor.V8ExecutorFactory;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class MainApplication extends MultiDexApplication implements ReactApplication {
|
||||
|
||||
private final ReactNativeHost mNewArchitectureNativeHost =
|
||||
new MainApplicationReactNativeHost(this);
|
||||
|
||||
@@ -112,6 +107,24 @@ public class MainApplication extends MultiDexApplication implements ReactApplica
|
||||
|
||||
}
|
||||
});
|
||||
if (!BuildConfig.IS_GITHUB_RELEASE) {
|
||||
try {
|
||||
/**
|
||||
* We use reflection here because SplitModulePackage & PlayCore libraries are not
|
||||
* available in Github/Fdroid release.
|
||||
*/
|
||||
Class<?> SplitCompat = Class.forName("com.google.android.play.core.splitcompat.SplitCompat");
|
||||
SplitCompat.getMethod("install", Context.class)
|
||||
.invoke(null, this.getApplication());
|
||||
|
||||
Class<?> SplitModulePackage = Class.forName("com.streetwriters.notesnook.SplitModulePackage");
|
||||
packages.add((ReactPackage) SplitModulePackage.getConstructor().newInstance());
|
||||
} catch (ClassNotFoundException | InvocationTargetException | NoSuchMethodException | IllegalAccessException | InstantiationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return packages;
|
||||
}
|
||||
|
||||
@@ -140,13 +153,7 @@ public class MainApplication extends MultiDexApplication implements ReactApplica
|
||||
aClass
|
||||
.getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
|
||||
.invoke(null, context, reactInstanceManager);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
package com.streetwriters.notesnook;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.facebook.react.bridge.ActivityEventListener;
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.Promise;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.bridge.WritableArray;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
||||
import com.google.android.play.core.splitcompat.SplitCompat;
|
||||
import com.google.android.play.core.splitinstall.SplitInstallException;
|
||||
import com.google.android.play.core.splitinstall.SplitInstallManager;
|
||||
import com.google.android.play.core.splitinstall.SplitInstallManagerFactory;
|
||||
import com.google.android.play.core.splitinstall.SplitInstallRequest;
|
||||
import com.google.android.play.core.splitinstall.SplitInstallSessionState;
|
||||
import com.google.android.play.core.splitinstall.SplitInstallStateUpdatedListener;
|
||||
import com.google.android.play.core.splitinstall.model.SplitInstallSessionStatus;
|
||||
|
||||
@ReactModule(name = "SplitModuleLoader")
|
||||
public class SplitModuleLoader extends ReactContextBaseJavaModule implements SplitInstallStateUpdatedListener {
|
||||
ReactContext rc;
|
||||
SplitInstallManager manager;
|
||||
ActivityEventListener listener = null;
|
||||
static int REQUEST_CODE = 25609;
|
||||
public SplitModuleLoader(ReactContext context) {
|
||||
rc = context;
|
||||
manager = SplitInstallManagerFactory.create(rc);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void installModule(String name, Promise promise) {
|
||||
SplitInstallRequest request = SplitInstallRequest.newBuilder().addModule(name).build();
|
||||
manager.startInstall(request).addOnFailureListener(e -> {
|
||||
Toast.makeText(rc,((SplitInstallException) e).getMessage(),Toast.LENGTH_LONG);
|
||||
promise.reject(e);
|
||||
}).addOnSuccessListener(integer -> {
|
||||
promise.resolve(integer);
|
||||
});
|
||||
manager.registerListener(this);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void getInstalledModules(Promise promise) {
|
||||
try {
|
||||
WritableArray array = Arguments.createArray();
|
||||
for (String item: manager.getInstalledModules()) {
|
||||
array.pushString(item);
|
||||
}
|
||||
promise.resolve(array);
|
||||
} catch (Exception e) {
|
||||
promise.reject(e);
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void queryClass(String name, Promise promise) {
|
||||
try {
|
||||
String n = Class.forName(name).getName();
|
||||
promise.resolve(n);
|
||||
} catch (ClassNotFoundException e) {
|
||||
promise.resolve("CLASS NOT FOUND");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCatalystInstanceDestroy() {
|
||||
super.onCatalystInstanceDestroy();
|
||||
manager.unregisterListener(this);
|
||||
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return "SplitModuleLoader";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStateUpdate(@NonNull SplitInstallSessionState splitInstallSessionState) {
|
||||
WritableMap map = Arguments.createMap();
|
||||
switch (splitInstallSessionState.status()) {
|
||||
case SplitInstallSessionStatus.UNKNOWN:
|
||||
|
||||
case SplitInstallSessionStatus.PENDING:
|
||||
map.putString("status", "pending");
|
||||
case SplitInstallSessionStatus.DOWNLOADING:
|
||||
long total = splitInstallSessionState.totalBytesToDownload();
|
||||
long downloaded = splitInstallSessionState.bytesDownloaded();
|
||||
map.putDouble("total", total);
|
||||
map.putDouble("downloaded", downloaded);
|
||||
map.putString("status", "downloading");
|
||||
break;
|
||||
case SplitInstallSessionStatus.DOWNLOADED:
|
||||
map.putString("status", "downloaded");
|
||||
break;
|
||||
case SplitInstallSessionStatus.INSTALLING:
|
||||
map.putString("status", "installing");
|
||||
break;
|
||||
case SplitInstallSessionStatus.INSTALLED:
|
||||
map.putString("status", "installed");
|
||||
break;
|
||||
case SplitInstallSessionStatus.FAILED:
|
||||
map.putString("status", "failed");
|
||||
map.putInt("errorCode", splitInstallSessionState.errorCode());
|
||||
break;
|
||||
case SplitInstallSessionStatus.CANCELED:
|
||||
map.putString("status", "canceled");
|
||||
break;
|
||||
case SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION:
|
||||
map.putString("status", "requires_user_confirmation");
|
||||
try {
|
||||
if (listener != null) {
|
||||
rc.removeActivityEventListener(listener);
|
||||
listener = null;
|
||||
}
|
||||
listener = new ActivityEventListener() {
|
||||
@Override
|
||||
public void onActivityResult(Activity activity, int code, int result, @Nullable Intent intent) {
|
||||
if (listener != null) {
|
||||
rc.removeActivityEventListener(listener);
|
||||
}
|
||||
if (code == REQUEST_CODE && result == Activity.RESULT_OK) {
|
||||
WritableMap map = Arguments.createMap();
|
||||
map.putString("status", "user_permission_granted");
|
||||
dispatchEvent("onModuleLoaderStateUpdate", map);
|
||||
} else if (code == REQUEST_CODE && result == Activity.RESULT_CANCELED) {
|
||||
WritableMap map = Arguments.createMap();
|
||||
map.putString("status", "user_permission_canceled");
|
||||
dispatchEvent("onModuleLoaderStateUpdate", map);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onNewIntent(Intent intent) {
|
||||
|
||||
}
|
||||
};
|
||||
rc.addActivityEventListener(listener);
|
||||
manager.startConfirmationDialogForResult(splitInstallSessionState,getCurrentActivity(),REQUEST_CODE);
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
break;
|
||||
case SplitInstallSessionStatus.CANCELING:
|
||||
map.putString("status", "canceling");
|
||||
break;
|
||||
}
|
||||
dispatchEvent("onModuleLoaderStateUpdate", map);
|
||||
}
|
||||
|
||||
protected void dispatchEvent(String eventName, WritableMap event) {
|
||||
rc.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
||||
.emit(eventName, event);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.streetwriters.notesnook;
|
||||
|
||||
import com.facebook.react.ReactPackage;
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.uimanager.ViewManager;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class SplitModulePackage implements ReactPackage {
|
||||
|
||||
@Override
|
||||
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
|
||||
return Arrays.asList(new SplitModuleLoader(reactContext));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
@@ -3,5 +3,5 @@
|
||||
<string name="title_activity_share">NotesnookShare</string>
|
||||
<string name="appwidget_text">EXAMPLE</string>
|
||||
<string name="add_widget">Add widget</string>
|
||||
|
||||
<string name="title_dynamic_geckoview">geckoview</string>
|
||||
</resources>
|
||||
|
||||
@@ -12,6 +12,7 @@ buildscript {
|
||||
androidXCoreVersion = "1.7.0"
|
||||
androidXCore = "1.7.0"
|
||||
androidXBrowser = "1.0.0"
|
||||
geckoviewVersion = "109.0.20230112150232"
|
||||
if (System.properties['os.arch'] == "aarch64") {
|
||||
// For M1 Users we need to use the NDK 24 which added support for aarch64
|
||||
ndkVersion = "24.0.8215888"
|
||||
@@ -72,5 +73,6 @@ allprojects {
|
||||
maven {
|
||||
url("${project(':react-native-background-fetch').projectDir}/libs")
|
||||
}
|
||||
maven { url "https://maven.mozilla.org/maven2/" }
|
||||
}
|
||||
}
|
||||
|
||||
100
apps/mobile/native/android/geckoview/build.gradle
Normal file
100
apps/mobile/native/android/geckoview/build.gradle
Normal file
@@ -0,0 +1,100 @@
|
||||
plugins {
|
||||
id("com.android.dynamic-feature")
|
||||
}
|
||||
|
||||
def DEFAULT_COMPILE_SDK_VERSION = 31
|
||||
def DEFAULT_BUILD_TOOLS_VERSION = '31.0.0'
|
||||
def DEFAULT_MIN_SDK_VERSION = 21
|
||||
def DEFAULT_TARGET_SDK_VERSION = 31
|
||||
// https://maven.mozilla.org/?prefix=maven2/org/mozilla/geckoview/geckoview/
|
||||
def DEFAULT_GECKOVIEW_VERSION = "109.0.20230112150232"
|
||||
|
||||
def safeExtGet(prop, fallback) {
|
||||
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
|
||||
}
|
||||
android {
|
||||
compileSdkVersion safeExtGet('compileSdkVersion', DEFAULT_COMPILE_SDK_VERSION)
|
||||
buildToolsVersion safeExtGet('buildToolsVersion', DEFAULT_BUILD_TOOLS_VERSION)
|
||||
defaultConfig {
|
||||
minSdkVersion safeExtGet('minSdkVersion', DEFAULT_MIN_SDK_VERSION)
|
||||
targetSdkVersion safeExtGet('targetSdkVersion', DEFAULT_TARGET_SDK_VERSION)
|
||||
missingDimensionStrategy "store", "play"
|
||||
}
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
extractSO
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
exclude "lib/**/liblgpllibs.so"
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
// ref: https://www.baeldung.com/maven-local-repository
|
||||
mavenLocal()
|
||||
maven {
|
||||
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
|
||||
url "$rootDir/../node_modules/react-native/android"
|
||||
}
|
||||
maven {
|
||||
// Android JSC is installed from npm
|
||||
url "$rootDir/../node_modules/jsc-android/dist"
|
||||
}
|
||||
google()
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':app')
|
||||
def geckoviewVersion = safeExtGet('geckoviewVersion', DEFAULT_GECKOVIEW_VERSION)
|
||||
//noinspection GradleDynamicVersion
|
||||
extractSO("org.mozilla.geckoview:geckoview:${geckoviewVersion}")
|
||||
}
|
||||
|
||||
|
||||
task extractSOFiles {
|
||||
def soFilesExist = new File("${buildDir}/../src/main/jniLibs/arm64-v8a/libxul.so").exists();
|
||||
if (soFilesExist) {
|
||||
println("GeckoView .so files already copied to jniLibs folder");
|
||||
return;
|
||||
}
|
||||
doLast {
|
||||
configurations.extractSO.files.each {
|
||||
def file = it.absoluteFile
|
||||
copy {
|
||||
from (zipTree(file)) {
|
||||
include "jni/**"
|
||||
eachFile { fcd ->
|
||||
fcd.relativePath = new RelativePath(true, fcd.relativePath.segments.drop(1))
|
||||
}
|
||||
includeEmptyDirs = false
|
||||
}
|
||||
into "${buildDir}/../src/main/jniLibs"
|
||||
}
|
||||
|
||||
// copy {
|
||||
// from (zipTree(file)) {
|
||||
// include "assets/**"
|
||||
// eachFile { fcd ->
|
||||
// fcd.relativePath = new RelativePath(true, fcd.relativePath.segments.drop(1))
|
||||
// }
|
||||
// includeEmptyDirs = false
|
||||
// }
|
||||
// into "${buildDir}/../src/main/assets"
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
tasks.whenTaskAdded { task ->
|
||||
task.dependsOn(extractSOFiles)
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:dist="http://schemas.android.com/apk/distribution"
|
||||
package="com.geckonative.module"
|
||||
split="geckoview-module">
|
||||
|
||||
<dist:module
|
||||
dist:instant="false"
|
||||
dist:title="@string/title_dynamic_geckoview">
|
||||
<dist:delivery>
|
||||
<dist:on-demand />
|
||||
<!-- <dist:install-time /> -->
|
||||
</dist:delivery>
|
||||
<dist:fusing dist:include="true" />
|
||||
</dist:module>
|
||||
|
||||
<application android:hasCode="false">
|
||||
</application>
|
||||
</manifest>
|
||||
@@ -42,4 +42,4 @@ newArchEnabled=false
|
||||
|
||||
# V8 Cache Mode Config
|
||||
# v8.cacheMode=none
|
||||
# v8.android.tools.dir=/home/ammarahm-ed/Repos/notesnook-mobile/node_modules/v8-android-jit-nointl/dist/tools/android
|
||||
# v8.android.tools.dir=/home/ammarahm-ed/Repos/notesnook-mobile/node_modules/v8-android-jit-nointl/dist/tools/android
|
||||
|
||||
@@ -8,3 +8,7 @@ if (settings.hasProperty("newArchEnabled") && settings.newArchEnabled == "true")
|
||||
include(":ReactAndroid:hermes-engine")
|
||||
project(":ReactAndroid:hermes-engine").projectDir = file('../../node_modules/react-native/ReactAndroid/hermes-engine')
|
||||
}
|
||||
|
||||
if (!settings.hasProperty("GITHUB_RELEASE")) {
|
||||
include ':geckoview'
|
||||
}
|
||||
|
||||
@@ -1087,7 +1087,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 2024;
|
||||
CURRENT_PROJECT_VERSION = 2026;
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
ENABLE_BITCODE = NO;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
@@ -1161,7 +1161,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.4.1;
|
||||
MARKETING_VERSION = 2.4.3;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
@@ -1191,7 +1191,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = Notesnook/Notesnook.entitlements;
|
||||
CODE_SIGN_IDENTITY = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 2024;
|
||||
CURRENT_PROJECT_VERSION = 2026;
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
@@ -1264,7 +1264,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.4.1;
|
||||
MARKETING_VERSION = 2.4.3;
|
||||
ONLY_ACTIVE_ARCH = NO;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
@@ -1422,7 +1422,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 2024;
|
||||
CURRENT_PROJECT_VERSION = 2026;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
@@ -1434,7 +1434,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.4.1;
|
||||
MARKETING_VERSION = 2.4.3;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
|
||||
@@ -1464,7 +1464,7 @@
|
||||
CODE_SIGN_IDENTITY = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 2024;
|
||||
CURRENT_PROJECT_VERSION = 2026;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
@@ -1476,7 +1476,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.4.1;
|
||||
MARKETING_VERSION = 2.4.3;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
@@ -1505,7 +1505,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "Make Note/Make Note.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 2024;
|
||||
CURRENT_PROJECT_VERSION = 2026;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
@@ -1579,7 +1579,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.4.1;
|
||||
MARKETING_VERSION = 2.4.3;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
|
||||
@@ -1609,7 +1609,7 @@
|
||||
CODE_SIGN_IDENTITY = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 2024;
|
||||
CURRENT_PROJECT_VERSION = 2026;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
@@ -1683,7 +1683,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.4.1;
|
||||
MARKETING_VERSION = 2.4.3;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
||||
@@ -57,7 +57,8 @@
|
||||
"@react-native-community/datetimepicker":"6.6.0",
|
||||
"react-native-date-picker": "4.2.6",
|
||||
"react-native-notification-sounds": "0.5.5",
|
||||
"react-native-background-fetch": "4.1.7"
|
||||
"react-native-background-fetch": "4.1.7",
|
||||
"@ammarahmed/react-native-geckoview": "^1.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.12.9",
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
|
||||
const isGithubRelease = process.env.GITHUB_RELEASE;
|
||||
const isGithubRelease = false;
|
||||
const config = {
|
||||
commands: require('@callstack/repack/commands'),
|
||||
project: {
|
||||
|
||||
20
apps/mobile/package-lock.json
generated
20
apps/mobile/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@notesnook/mobile",
|
||||
"version": "2.4.0",
|
||||
"version": "2.4.1",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@notesnook/mobile",
|
||||
"version": "2.4.0",
|
||||
"version": "2.4.1",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"workspaces": [
|
||||
"native/",
|
||||
@@ -61,6 +61,7 @@
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@ammarahmed/notifee-react-native": "7.3.1",
|
||||
"@ammarahmed/react-native-geckoview": "^1.4.0",
|
||||
"@ammarahmed/react-native-sodium": "1.2.0",
|
||||
"@callstack/repack": "^3.0.0",
|
||||
"@react-native-clipboard/clipboard": "^1.9.0",
|
||||
@@ -162,6 +163,15 @@
|
||||
"react-native": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@ammarahmed/react-native-geckoview": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@ammarahmed/react-native-geckoview/-/react-native-geckoview-1.4.0.tgz",
|
||||
"integrity": "sha512-ys4dSZS+Dtw6mHeHVOy3/16uOhU+b+kb5PJL/wfqUhccmeipJK46qPVkqBft1YdxJ/4cc6W/4nIGXRpeCivESQ==",
|
||||
"peerDependencies": {
|
||||
"react": "*",
|
||||
"react-native": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@ammarahmed/react-native-sodium": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@ammarahmed/react-native-sodium/-/react-native-sodium-1.2.0.tgz",
|
||||
@@ -21520,6 +21530,11 @@
|
||||
"resolved": "https://registry.npmjs.org/@ammarahmed/notifee-react-native/-/notifee-react-native-7.3.1.tgz",
|
||||
"integrity": "sha512-kzBDw2NAt9kGD0CJ193JME4bS4uQolY+UubGiTnJwHfaLH7dFNju6RC15/u8tzG59ebDuCalkMLr+rAONtg2Rw=="
|
||||
},
|
||||
"@ammarahmed/react-native-geckoview": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@ammarahmed/react-native-geckoview/-/react-native-geckoview-1.4.0.tgz",
|
||||
"integrity": "sha512-ys4dSZS+Dtw6mHeHVOy3/16uOhU+b+kb5PJL/wfqUhccmeipJK46qPVkqBft1YdxJ/4cc6W/4nIGXRpeCivESQ=="
|
||||
},
|
||||
"@ammarahmed/react-native-sodium": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@ammarahmed/react-native-sodium/-/react-native-sodium-1.2.0.tgz",
|
||||
@@ -24317,6 +24332,7 @@
|
||||
"version": "file:native",
|
||||
"requires": {
|
||||
"@ammarahmed/notifee-react-native": "7.3.1",
|
||||
"@ammarahmed/react-native-geckoview": "^1.4.0",
|
||||
"@ammarahmed/react-native-sodium": "1.2.0",
|
||||
"@babel/core": "^7.12.9",
|
||||
"@babel/eslint-parser": "^7.16.5",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@notesnook/mobile",
|
||||
"version": "2.4.1",
|
||||
"version": "2.4.8",
|
||||
"private": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
"workspaces": [
|
||||
@@ -19,8 +19,10 @@
|
||||
"e2e-android": "cd native && detox test --configuration android.emu.release --detectOpenHandles",
|
||||
"e2e-ios": "cd native && detox test -c ios.sim.release --detectOpenHandles",
|
||||
"bump": "cd native && npx react-native bump-version --skip-semver-for android",
|
||||
"release-android": "cd native/android && GITHUB_RELEASE=true ENVFILE=.env.public ./gradlew assembleRelease --no-daemon",
|
||||
"release-android-bundle": "cd native/android && ./gradlew bundleRelease --no-daemon"
|
||||
"release-android": "./scripts/gh-release.sh",
|
||||
"release-gecko-android": "./scripts/gh-geckoview-release.sh",
|
||||
"release-android-bundle": "cd native/android && ./gradlew bundleRelease --no-daemon",
|
||||
"debug-dynamic-module": "./scripts/debug-dynamic-module.sh"
|
||||
},
|
||||
"devDependencies": {
|
||||
"patch-package": "^6.4.7",
|
||||
|
||||
8
apps/mobile/scripts/debug-dynamic-module.sh
Executable file
8
apps/mobile/scripts/debug-dynamic-module.sh
Executable file
@@ -0,0 +1,8 @@
|
||||
tc() { set ${*,,} ; echo ${*^} ; }
|
||||
adb reverse tcp:8081 tcp:8081 || true
|
||||
rm -rf $(PWD)/native/android/app/build/outputs/bundle || true
|
||||
cd native/android && ./gradlew bundle$2
|
||||
cd ../../
|
||||
java -jar $HOME/bundletool/bundletool-all-1.13.2.jar build-apks --overwrite --local-testing --bundle $(PWD)/native/android/app/build/outputs/bundle/$1/app-$1.aab --output $(PWD)/native/android/app/build/outputs/bundle/$0/apkset.apks
|
||||
java -jar $HOME/bundletool/bundletool-all-1.13.2.jar install-apks --apks $(PWD)/native/android/app/build/outputs/bundle/$0/apkset.apks
|
||||
adb shell monkey -p com.streetwriters.notesnook 1
|
||||
8
apps/mobile/scripts/gh-geckoview-release.sh
Executable file
8
apps/mobile/scripts/gh-geckoview-release.sh
Executable file
@@ -0,0 +1,8 @@
|
||||
echo enableGecko=true >> $(PWD)/native/android/gradle.properties
|
||||
echo GITHUB_RELEASE=true >> $(PWD)/native/android/gradle.properties
|
||||
echo GITHUB_RELEASE=true > $(PWD)/native/.env
|
||||
echo enableGecko=true >> $(PWD)/native/.env
|
||||
rm $(PWD)/native/android/app/src/main/java/com/streetwriters/notesnook/SplitModuleLoader.java || true
|
||||
rm $(PWD)/native/android/app/src/main/java/com/streetwriters/notesnook/SplitModulePackage.java || true
|
||||
cd native/android
|
||||
./gradlew assembleRelease --no-daemon
|
||||
7
apps/mobile/scripts/gh-release.sh
Executable file
7
apps/mobile/scripts/gh-release.sh
Executable file
@@ -0,0 +1,7 @@
|
||||
echo GITHUB_RELEASE=true >> $(PWD)/native/android/gradle.properties
|
||||
echo GITHUB_RELEASE=true > $(PWD)/native/.env
|
||||
sed s/false/true/g < react-native.config.js > react-native.config.jss && mv react-native.config.jss react-native.config.js
|
||||
rm $(PWD)/native/android/app/src/main/java/com/streetwriters/notesnook/SplitModuleLoader.java || true
|
||||
rm $(PWD)/native/android/app/src/main/java/com/streetwriters/notesnook/SplitModulePackage.java || true
|
||||
cd native/android
|
||||
./gradlew assembleRelease --no-daemon
|
||||
1
apps/web/package-lock.json
generated
1
apps/web/package-lock.json
generated
@@ -449,6 +449,7 @@
|
||||
},
|
||||
"node_modules/@azure/msal-node-extensions": {
|
||||
"version": "1.0.0-alpha.28",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@azure/msal-common": "^9.0.1",
|
||||
|
||||
@@ -13,11 +13,13 @@
|
||||
"test:web": "nx test @notesnook/web",
|
||||
"test:core": "nx test @notesnook/core",
|
||||
"start:android": "nx run-android @notesnook/mobile",
|
||||
"start:android:dynamic-module": "nx debug-dynamic-module @notesnook/mobile",
|
||||
"start:ios": "nx run-ios @notesnook/mobile",
|
||||
"prepare:ios": "nx install-pods @notesnook/mobile",
|
||||
"build:ios": "nx build-ios @notesnook/mobile",
|
||||
"build:android": "nx build-android @notesnook/mobile",
|
||||
"release:android": "nx release-android @notesnook/mobile",
|
||||
"release:android:gecko": "nx release-gecko-android @notesnook/mobile",
|
||||
"release:android:bundle": "nx release-android-bundle @notesnook/mobile",
|
||||
"test:ios": "nx e2e-ios @notesnook/mobile",
|
||||
"test:android": "nx e2e-android @notesnook/mobile",
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
body {
|
||||
height: 100%;
|
||||
font-family: "Open Sans";
|
||||
background-color: var(--nn_bg);
|
||||
}
|
||||
|
||||
p {
|
||||
|
||||
Reference in New Issue
Block a user