mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-16 11:47:54 +01:00
lazy load components
This commit is contained in:
@@ -2,6 +2,7 @@ package com.streetwriters.notesnook;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import com.dooboolab.RNIap.RNIapModule;
|
||||
import com.facebook.react.PackageList;
|
||||
@@ -34,6 +35,7 @@ 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 {
|
||||
|
||||
@@ -47,6 +49,17 @@ public class MainApplication extends MultiDexApplication implements ReactApplica
|
||||
return BuildConfig.DEBUG;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected String getBundleAssetName() {
|
||||
final String v8BundleAssetName = V8ExecutorFactory.getBundleAssetName(getApplicationContext(), getUseDeveloperSupport());
|
||||
if (v8BundleAssetName != null) {
|
||||
return v8BundleAssetName;
|
||||
}
|
||||
Log.d("Notesnook:::", "LOADED" + v8BundleAssetName + super.getBundleAssetName());
|
||||
return super.getBundleAssetName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JavaScriptExecutorFactory getJavaScriptExecutorFactory() {
|
||||
return new V8ExecutorFactory(
|
||||
|
||||
@@ -6,9 +6,7 @@
|
||||
<item name="android:windowDisablePreview">true</item>
|
||||
<item name="android:editTextBackground">@drawable/edit_text</item>
|
||||
|
||||
<item name="android:windowTranslucentStatus">true</item>
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
|
||||
</style>
|
||||
|
||||
<style name="Share.Window" parent="Theme.AppCompat">
|
||||
|
||||
@@ -41,5 +41,5 @@ reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
|
||||
newArchEnabled=false
|
||||
|
||||
# V8 Cache Mode Config
|
||||
v8.cacheMode=normal
|
||||
v8.cacheMode=normalWithStubBundle
|
||||
v8.android.tools.dir=/home/ammarahm-ed/Repos/notesnook-mobile/node_modules/v8-android-jit-nointl/dist/tools/android
|
||||
@@ -18,7 +18,7 @@ const configs = {
|
||||
production: {
|
||||
presets: ['module:metro-react-native-babel-preset'],
|
||||
plugins: [
|
||||
'transform-remove-console',
|
||||
//'transform-remove-console',
|
||||
'@babel/plugin-transform-named-capturing-groups-regex',
|
||||
'react-native-reanimated/plugin'
|
||||
]
|
||||
|
||||
@@ -1,5 +1,63 @@
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
global.Buffer = require('buffer').Buffer;
|
||||
import { DOMParser } from './worker';
|
||||
import { ScriptManager, Script } from '@callstack/repack/client';
|
||||
import './src/utils/logger/index';
|
||||
global.DOMParser = DOMParser;
|
||||
|
||||
class DOM {
|
||||
static domparser;
|
||||
|
||||
parseFromString(markupLanguage, mimeType, globals) {
|
||||
return DOM.domparser?.parseFromString(markupLanguage, mimeType, globals);
|
||||
}
|
||||
|
||||
static async prepare() {
|
||||
if (!DOM.domparser) {
|
||||
let module = await import('./worker.js');
|
||||
DOM.domparser = new module.DOMParser();
|
||||
}
|
||||
}
|
||||
}
|
||||
global.DOMParser = DOM;
|
||||
|
||||
try {
|
||||
const shared = ScriptManager.shared;
|
||||
} catch (e) {
|
||||
new ScriptManager({
|
||||
resolve: async (scriptId, caller) => {
|
||||
if (__DEV__) {
|
||||
return {
|
||||
url: Script.getDevServerURL(scriptId),
|
||||
cache: false
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
url: Script.getFileSystemURL(scriptId)
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ScriptManager.shared.on('resolving', (...args) => {
|
||||
console.log('DEBUG/resolving', ...args);
|
||||
});
|
||||
|
||||
ScriptManager.shared.on('resolved', (...args) => {
|
||||
console.log('DEBUG/resolved', ...args);
|
||||
});
|
||||
|
||||
ScriptManager.shared.on('prefetching', (...args) => {
|
||||
console.log('DEBUG/prefetching', ...args);
|
||||
});
|
||||
|
||||
ScriptManager.shared.on('loading', (...args) => {
|
||||
console.log('DEBUG/loading', ...args);
|
||||
});
|
||||
|
||||
ScriptManager.shared.on('loaded', (...args) => {
|
||||
console.log('DEBUG/loaded', ...args);
|
||||
});
|
||||
|
||||
ScriptManager.shared.on('error', (...args) => {
|
||||
console.log('DEBUG/error', ...args);
|
||||
});
|
||||
|
||||
@@ -10,7 +10,6 @@ import { SafeAreaProvider } from 'react-native-safe-area-context';
|
||||
import { enableScreens } from 'react-native-screens';
|
||||
import appJson from './app.json';
|
||||
import Notifications from './src/services/notifications';
|
||||
|
||||
enableLayoutAnimations(true);
|
||||
const appName = appJson.name;
|
||||
if (Config.isTesting) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import { TouchableOpacity, View } from 'react-native';
|
||||
import * as Progress from 'react-native-progress';
|
||||
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import { useAttachmentStore } from '../../stores/use-attachment-store';
|
||||
import { useThemeStore } from '../../stores/use-theme-store';
|
||||
@@ -10,6 +9,7 @@ import { useAttachmentProgress } from '../../utils/hooks/use-attachment-progress
|
||||
import { SIZE } from '../../utils/size';
|
||||
import SheetProvider from '../sheet-provider';
|
||||
import { IconButton } from '../ui/icon-button';
|
||||
import { ProgressCircleComponent } from '../ui/svg/lazy';
|
||||
import Paragraph from '../ui/typography/paragraph';
|
||||
import Actions from './actions';
|
||||
|
||||
@@ -113,24 +113,26 @@ export const AttachmentItem = ({ attachment, encryption, setAttachments }) => {
|
||||
marginRight: -5
|
||||
}}
|
||||
>
|
||||
<Progress.Circle
|
||||
size={SIZE.xxl}
|
||||
progress={
|
||||
encryptionProgress
|
||||
? encryptionProgress
|
||||
: currentProgress?.value
|
||||
? currentProgress?.value / 100
|
||||
: 0
|
||||
}
|
||||
showsText
|
||||
textStyle={{
|
||||
fontSize: 10
|
||||
}}
|
||||
color={colors.accent}
|
||||
formatText={progress => (progress * 100).toFixed(0)}
|
||||
borderWidth={0}
|
||||
thickness={2}
|
||||
/>
|
||||
<React.Suspense fallback={<View />}>
|
||||
<ProgressCircleComponent
|
||||
size={SIZE.xxl}
|
||||
progress={
|
||||
encryptionProgress
|
||||
? encryptionProgress
|
||||
: currentProgress?.value
|
||||
? currentProgress?.value / 100
|
||||
: 0
|
||||
}
|
||||
showsText
|
||||
textStyle={{
|
||||
fontSize: 10
|
||||
}}
|
||||
color={colors.accent}
|
||||
formatText={progress => (progress * 100).toFixed(0)}
|
||||
borderWidth={0}
|
||||
thickness={2}
|
||||
/>
|
||||
</React.Suspense>
|
||||
</TouchableOpacity>
|
||||
) : (
|
||||
<>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { Platform, StatusBar } from 'react-native';
|
||||
import { Platform } from 'react-native';
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
import { eSendEvent, eSubscribeEvent, eUnSubscribeEvent } from '../../services/event-manager';
|
||||
import { eSubscribeEvent, eUnSubscribeEvent } from '../../services/event-manager';
|
||||
import { useThemeStore } from '../../stores/use-theme-store';
|
||||
import { eCloseLoginDialog, eOpenLoginDialog } from '../../utils/events';
|
||||
import { sleep } from '../../utils/time';
|
||||
import BaseDialog from '../dialog/base-dialog';
|
||||
import { Toast } from '../toast';
|
||||
import { IconButton } from '../ui/icon-button';
|
||||
import { initialAuthMode } from './common';
|
||||
import { hideAuth, initialAuthMode } from './common';
|
||||
import { Login } from './login';
|
||||
import { Signup } from './signup';
|
||||
|
||||
@@ -37,7 +37,7 @@ const AuthModal = () => {
|
||||
|
||||
async function open(mode) {
|
||||
setCurrentAuthMode(mode ? mode : AuthMode.login);
|
||||
initialAuthMode.current = -1;
|
||||
initialAuthMode.current = mode ? mode : AuthMode.login;
|
||||
setVisible(true);
|
||||
await sleep(10);
|
||||
actionSheetRef.current?.show();
|
||||
@@ -60,30 +60,36 @@ const AuthModal = () => {
|
||||
bounce={false}
|
||||
background={colors.bg}
|
||||
transparent={false}
|
||||
animated={false}
|
||||
>
|
||||
{currentAuthMode !== AuthMode.login ? (
|
||||
<Signup
|
||||
changeMode={mode => setCurrentAuthMode(mode)}
|
||||
trial={AuthMode.trialSignup === currentAuthMode}
|
||||
welcome={currentAuthMode === AuthMode.welcomeSignup}
|
||||
welcome={initialAuthMode.current === AuthMode.welcomeSignup}
|
||||
/>
|
||||
) : (
|
||||
<Login changeMode={mode => setCurrentAuthMode(mode)} />
|
||||
<Login
|
||||
welcome={initialAuthMode.current === AuthMode.welcomeSignup}
|
||||
changeMode={mode => setCurrentAuthMode(mode)}
|
||||
/>
|
||||
)}
|
||||
|
||||
<IconButton
|
||||
name="arrow-left"
|
||||
onPress={() => {
|
||||
eSendEvent(eCloseLoginDialog);
|
||||
}}
|
||||
color={colors.pri}
|
||||
customStyle={{
|
||||
position: 'absolute',
|
||||
zIndex: 999,
|
||||
left: 12,
|
||||
top: Platform.OS === 'ios' ? 12 + insets.top : 12
|
||||
}}
|
||||
/>
|
||||
{initialAuthMode.current === AuthMode.welcomeSignup ? null : (
|
||||
<IconButton
|
||||
name="arrow-left"
|
||||
onPress={() => {
|
||||
hideAuth();
|
||||
}}
|
||||
color={colors.pri}
|
||||
customStyle={{
|
||||
position: 'absolute',
|
||||
zIndex: 999,
|
||||
left: 12,
|
||||
top: Platform.OS === 'ios' ? 12 + insets.top : insets.top
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
<Toast context="local" />
|
||||
</BaseDialog>
|
||||
|
||||
@@ -7,27 +7,20 @@ import { tabBarRef } from '../../utils/global-refs';
|
||||
|
||||
export const initialAuthMode = createRef(0);
|
||||
export function hideAuth() {
|
||||
if (initialAuthMode.current === -1) {
|
||||
eSendEvent(eCloseLoginDialog);
|
||||
return;
|
||||
}
|
||||
if (initialAuthMode.current === 2) {
|
||||
Navigation.replace(
|
||||
{
|
||||
name: 'Notes'
|
||||
},
|
||||
{
|
||||
menu: true
|
||||
}
|
||||
);
|
||||
} else {
|
||||
Navigation.goBack();
|
||||
}
|
||||
eSendEvent(eCloseLoginDialog);
|
||||
|
||||
tabBarRef.current?.unlock();
|
||||
if (!SettingsService.get().introCompleted) {
|
||||
SettingsService.set({
|
||||
introCompleted: true
|
||||
});
|
||||
}
|
||||
// if (initialAuthMode.current === 2) {
|
||||
// Navigation.replace(
|
||||
// {
|
||||
// name: 'Notes'
|
||||
// },
|
||||
// {
|
||||
// menu: true
|
||||
// }
|
||||
// );
|
||||
// } else {
|
||||
// Navigation.goBack();
|
||||
// }
|
||||
|
||||
// tabBarRef.current?.unlock();
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ const Auth = ({ navigation, route }) => {
|
||||
initialAuthMode.current = route?.params.mode || AuthMode.login;
|
||||
useNavigationFocus(navigation, {
|
||||
onFocus: () => {
|
||||
tabBarRef?.current.lock();
|
||||
//tabBarRef?.current.lock();
|
||||
initialAuthMode.current = route?.params.mode || AuthMode.login;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -20,10 +20,7 @@ export const RightMenus = () => {
|
||||
|
||||
return (
|
||||
<View style={styles.rightBtnContainer}>
|
||||
{!currentScreen.startsWith('Settings') &&
|
||||
currentScreen !== 'Auth' &&
|
||||
currentScreen !== 'Signup' &&
|
||||
currentScreen !== 'Login' ? (
|
||||
{!currentScreen.startsWith('Settings') ? (
|
||||
<IconButton
|
||||
onPress={async () => {
|
||||
SearchService.prepareSearch();
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import React from 'react';
|
||||
import Animated, { FadeInDown } from 'react-native-reanimated';
|
||||
import { eSendEvent } from '../../services/event-manager';
|
||||
import Navigation from '../../services/navigation';
|
||||
import SettingsService from '../../services/settings';
|
||||
import { useThemeStore } from '../../stores/use-theme-store';
|
||||
import { getElevation } from '../../utils';
|
||||
import umami from '../../utils/analytics';
|
||||
import { eOpenLoginDialog } from '../../utils/events';
|
||||
import { SIZE } from '../../utils/size';
|
||||
import { AuthMode } from '../auth';
|
||||
import { Button } from '../ui/button';
|
||||
@@ -44,14 +47,20 @@ export const WelcomeNotice = () => {
|
||||
height={45}
|
||||
width={250}
|
||||
onPress={async () => {
|
||||
Navigation.navigate(
|
||||
{
|
||||
name: 'Auth'
|
||||
},
|
||||
{
|
||||
mode: AuthMode.welcomeSignup
|
||||
}
|
||||
);
|
||||
eSendEvent(eOpenLoginDialog, AuthMode.welcomeSignup);
|
||||
SettingsService.set({
|
||||
introCompleted: true
|
||||
});
|
||||
setTimeout(() => {
|
||||
Navigation.replace(
|
||||
{
|
||||
name: 'Notes'
|
||||
},
|
||||
{
|
||||
canGoBack: false
|
||||
}
|
||||
);
|
||||
}, 1000);
|
||||
umami.pageView('/encryptionnotice', '/welcome/privacymode');
|
||||
}}
|
||||
style={{
|
||||
|
||||
@@ -16,7 +16,7 @@ import { useNoteStore } from '../../stores/use-notes-store';
|
||||
import { useSettingStore } from '../../stores/use-setting-store';
|
||||
import { useThemeStore } from '../../stores/use-theme-store';
|
||||
import { useUserStore } from '../../stores/use-user-store';
|
||||
import { db } from '../../utils/database';
|
||||
import { db, loadDatabase } from '../../utils/database';
|
||||
import { MMKV } from '../../utils/database/mmkv';
|
||||
import { eOpenAnnouncementDialog } from '../../utils/events';
|
||||
import { tabBarRef } from '../../utils/global-refs';
|
||||
@@ -68,7 +68,8 @@ const Launcher = React.memo(
|
||||
|
||||
const init = async () => {
|
||||
if (!dbInitCompleted.current) {
|
||||
await RNBootSplash.hide();
|
||||
if (!verifyUser) await RNBootSplash.hide({ fade: true });
|
||||
await loadDatabase();
|
||||
await db.init();
|
||||
dbInitCompleted.current = true;
|
||||
}
|
||||
@@ -125,18 +126,16 @@ const Launcher = React.memo(
|
||||
};
|
||||
|
||||
const checkAppUpdateAvailable = async () => {
|
||||
return;
|
||||
// try {
|
||||
// const version = await checkVersion();
|
||||
// if (!version.needsUpdate) return false;
|
||||
// presentSheet({
|
||||
// component: ref => <Update version={version} fwdRef={ref} />
|
||||
// });
|
||||
|
||||
// return true;
|
||||
// } catch (e) {
|
||||
// return false;
|
||||
// }
|
||||
try {
|
||||
const version = await checkVersion();
|
||||
if (!version.needsUpdate) return false;
|
||||
presentSheet({
|
||||
component: ref => <Update version={version} fwdRef={ref} />
|
||||
});
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const restoreEditorState = async () => {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { View } from 'react-native';
|
||||
import * as ProgressBar from 'react-native-progress';
|
||||
import { presentSheet } from '../../../services/event-manager';
|
||||
import { useThemeStore } from '../../../stores/use-theme-store';
|
||||
import useSyncProgress from '../../../utils/hooks/use-sync-progress';
|
||||
import { SIZE } from '../../../utils/size';
|
||||
import Seperator from '../../ui/seperator';
|
||||
import { ProgressBarComponent } from '../../ui/svg/lazy';
|
||||
import Heading from '../../ui/typography/heading';
|
||||
import Paragraph from '../../ui/typography/paragraph';
|
||||
|
||||
@@ -41,16 +41,18 @@ export const Progress = () => {
|
||||
width: 200
|
||||
}}
|
||||
>
|
||||
<ProgressBar.Bar
|
||||
height={5}
|
||||
width={null}
|
||||
animated={true}
|
||||
useNativeDriver
|
||||
progress={currentProgress || 0.1}
|
||||
unfilledColor={colors.nav}
|
||||
color={colors.accent}
|
||||
borderWidth={0}
|
||||
/>
|
||||
<React.Suspense fallback={<View />}>
|
||||
<ProgressBarComponent
|
||||
height={5}
|
||||
width={null}
|
||||
animated={true}
|
||||
useNativeDriver
|
||||
progress={currentProgress || 0.1}
|
||||
unfilledColor={colors.nav}
|
||||
color={colors.accent}
|
||||
borderWidth={0}
|
||||
/>
|
||||
</React.Suspense>
|
||||
</View>
|
||||
|
||||
{progress ? (
|
||||
|
||||
@@ -2,7 +2,6 @@ import Clipboard from '@react-native-clipboard/clipboard';
|
||||
import React, { createRef } from 'react';
|
||||
import { Platform, View } from 'react-native';
|
||||
import FileViewer from 'react-native-file-viewer';
|
||||
import QRCode from 'react-native-qrcode-svg';
|
||||
import * as ScopedStorage from 'react-native-scoped-storage';
|
||||
import Share from 'react-native-share';
|
||||
//import { LOGO_BASE64 } from '../../../assets/images/assets';
|
||||
@@ -19,6 +18,7 @@ import DialogHeader from '../../dialog/dialog-header';
|
||||
import { Button } from '../../ui/button';
|
||||
import Seperator from '../../ui/seperator';
|
||||
import SheetWrapper from '../../ui/sheet';
|
||||
import { QRCode } from '../../ui/svg/lazy';
|
||||
import Paragraph from '../../ui/typography/paragraph';
|
||||
|
||||
let RNFetchBlob;
|
||||
@@ -241,13 +241,15 @@ class RecoveryKeySheet extends React.Component {
|
||||
}}
|
||||
>
|
||||
{this.state.key ? (
|
||||
<QRCode
|
||||
getRef={this.svg}
|
||||
size={500}
|
||||
value={this.state.key}
|
||||
//logo={{ uri: LOGO_BASE64 }}
|
||||
logoBorderRadius={10}
|
||||
/>
|
||||
<React.Suspense>
|
||||
<QRCode
|
||||
getRef={this.svg}
|
||||
size={500}
|
||||
value={this.state.key}
|
||||
//logo={{ uri: LOGO_BASE64 }}
|
||||
logoBorderRadius={10}
|
||||
/>
|
||||
</React.Suspense>
|
||||
) : null}
|
||||
</View>
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -13,9 +13,9 @@ import Heading from '../ui/typography/heading';
|
||||
import Paragraph from '../ui/typography/paragraph';
|
||||
import { TimeSince } from '../ui/time-since';
|
||||
import useSyncProgress from '../../utils/hooks/use-sync-progress';
|
||||
import * as Progress from 'react-native-progress';
|
||||
import Navigation from '../../services/navigation';
|
||||
import { tabBarRef } from '../../utils/global-refs';
|
||||
import { ProgressCircleComponent } from '../ui/svg/lazy';
|
||||
|
||||
export const UserStatus = () => {
|
||||
const colors = useThemeStore(state => state.colors);
|
||||
@@ -48,15 +48,7 @@ export const UserStatus = () => {
|
||||
await Sync.run();
|
||||
} else {
|
||||
tabBarRef.current?.closeDrawer();
|
||||
Navigation.navigate(
|
||||
{
|
||||
name: 'Login'
|
||||
},
|
||||
{
|
||||
mode: 0,
|
||||
canGoBack: true
|
||||
}
|
||||
);
|
||||
eSendEvent(eOpenLoginDialog);
|
||||
}
|
||||
}}
|
||||
type="gray"
|
||||
@@ -118,18 +110,20 @@ export const UserStatus = () => {
|
||||
{user ? (
|
||||
syncing ? (
|
||||
<>
|
||||
<Progress.Circle
|
||||
size={SIZE.xl}
|
||||
progress={progress ? progress.current / progress.total : 0.1}
|
||||
textStyle={{
|
||||
fontSize: 8
|
||||
}}
|
||||
animated={true}
|
||||
color={colors.accent}
|
||||
unfilledColor={colors.nav}
|
||||
borderWidth={0}
|
||||
thickness={2}
|
||||
/>
|
||||
<React.Suspense fallback={<View />}>
|
||||
<ProgressCircleComponent
|
||||
size={SIZE.xl}
|
||||
progress={progress ? progress.current / progress.total : 0.1}
|
||||
textStyle={{
|
||||
fontSize: 8
|
||||
}}
|
||||
animated={true}
|
||||
color={colors.accent}
|
||||
unfilledColor={colors.nav}
|
||||
borderWidth={0}
|
||||
thickness={2}
|
||||
/>
|
||||
</React.Suspense>
|
||||
</>
|
||||
) : (
|
||||
<Icon color={colors.accent} name="sync" size={SIZE.lg} />
|
||||
|
||||
@@ -21,7 +21,6 @@ import { getElevation } from '../../../utils';
|
||||
import { SIZE } from '../../../utils/size';
|
||||
import { IconButton } from '../icon-button';
|
||||
import Paragraph from '../typography/paragraph';
|
||||
import phone from 'phone';
|
||||
|
||||
interface InputProps extends TextInputProps {
|
||||
fwdRef?: RefObject<any>;
|
||||
@@ -91,7 +90,7 @@ const Input = ({
|
||||
|
||||
const color = error ? colors.red : focus ? customColor || colors.accent : colors.nav;
|
||||
|
||||
const validate = (value: string) => {
|
||||
const validate = async (value: string) => {
|
||||
if (!validationType) return;
|
||||
if (!value || value?.length === 0) {
|
||||
setError(false);
|
||||
@@ -117,6 +116,8 @@ const Input = ({
|
||||
isError = customValidator && value === customValidator();
|
||||
break;
|
||||
case 'phonenumber':
|
||||
// eslint-disable-next-line no-case-declarations
|
||||
const phone = await (await import('phone')).default;
|
||||
// eslint-disable-next-line no-case-declarations
|
||||
let result = phone(value, {
|
||||
strictDetection: true,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { View } from 'react-native';
|
||||
import { SvgXml } from 'react-native-svg';
|
||||
import { SvgXml } from './lazy';
|
||||
|
||||
export const SvgView = ({
|
||||
width = 250,
|
||||
@@ -19,7 +19,9 @@ export const SvgView = ({
|
||||
width: height || 250
|
||||
}}
|
||||
>
|
||||
<SvgXml xml={src} width="100%" height="100%" />
|
||||
<React.Suspense fallback={<View />}>
|
||||
<SvgXml xml={src} width="100%" height="100%" />
|
||||
</React.Suspense>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
29
apps/mobile/src/components/ui/svg/lazy.js
Normal file
29
apps/mobile/src/components/ui/svg/lazy.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import React from 'react';
|
||||
|
||||
export const QRCode = React.lazy(async () => {
|
||||
const module = await (await import('./module-svg')).default;
|
||||
return {
|
||||
default: module.QRCode
|
||||
};
|
||||
});
|
||||
|
||||
export const SvgXml = React.lazy(async () => {
|
||||
const module = await (await import('./module-svg')).default;
|
||||
return {
|
||||
default: module.SvgXml
|
||||
};
|
||||
});
|
||||
|
||||
export const ProgressBarComponent = React.lazy(async () => {
|
||||
const module = await (await import('./module-svg')).default;
|
||||
return {
|
||||
default: module.Progress.Bar
|
||||
};
|
||||
});
|
||||
|
||||
export const ProgressCircleComponent = React.lazy(async () => {
|
||||
const module = await (await import('./module-svg')).default;
|
||||
return {
|
||||
default: module.Progress.Circle
|
||||
};
|
||||
});
|
||||
11
apps/mobile/src/components/ui/svg/module_svg.js
Normal file
11
apps/mobile/src/components/ui/svg/module_svg.js
Normal file
@@ -0,0 +1,11 @@
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
import { Bar, Circle } from 'react-native-progress';
|
||||
import QRCode from 'react-native-qrcode-svg';
|
||||
import { SvgXml } from 'react-native-svg';
|
||||
|
||||
const Progress = {
|
||||
Bar,
|
||||
Circle
|
||||
};
|
||||
|
||||
export default { Progress, QRCode, SvgXml };
|
||||
@@ -1,17 +1,18 @@
|
||||
import React from 'react';
|
||||
import { View } from 'react-native';
|
||||
import DelayLayout from '../components/delay-layout';
|
||||
import DialogProvider from '../components/dialog-provider';
|
||||
import { Header } from '../components/header';
|
||||
import Intro from '../components/intro';
|
||||
import { Toast } from '../components/toast';
|
||||
import SettingsService from '../services/settings';
|
||||
import { useNoteStore } from '../stores/use-notes-store';
|
||||
import { useSettingStore } from '../stores/use-setting-store';
|
||||
import { TabsHolder } from './tabs-holder';
|
||||
|
||||
const DialogProvider = React.lazy(() => import('../components/dialogprovider'));
|
||||
|
||||
export const ApplicationHolder = React.memo(
|
||||
() => {
|
||||
const loading = useNoteStore(state => state.loading);
|
||||
const introCompleted = SettingsService.get().introCompleted;
|
||||
const introCompleted = useSettingStore(state => state.settings.introCompleted);
|
||||
return loading && introCompleted ? (
|
||||
<>
|
||||
<Header />
|
||||
@@ -21,7 +22,9 @@ export const ApplicationHolder = React.memo(
|
||||
<>
|
||||
<TabsHolder />
|
||||
<Toast />
|
||||
<DialogProvider />
|
||||
<React.Suspense fallback={<View />}>
|
||||
<DialogProvider />
|
||||
</React.Suspense>
|
||||
</>
|
||||
);
|
||||
},
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import { NavigationContainer } from '@react-navigation/native';
|
||||
import { createNativeStackNavigator } from '@react-navigation/native-stack';
|
||||
import * as React from 'react';
|
||||
import Auth from '../components/auth';
|
||||
import { Login } from '../components/auth/login';
|
||||
import { Signup } from '../components/auth/signup';
|
||||
import Container from '../components/container';
|
||||
import Intro from '../components/intro';
|
||||
import Favorites from '../screens/favorites';
|
||||
@@ -41,7 +38,6 @@ const IntroStack = createNativeStackNavigator();
|
||||
|
||||
const IntroStackNavigator = () => {
|
||||
const colors = useThemeStore(state => state.colors);
|
||||
const introCompleted = SettingsService.get().introCompleted;
|
||||
return (
|
||||
<IntroStack.Navigator
|
||||
screenOptions={{
|
||||
@@ -56,13 +52,6 @@ const IntroStackNavigator = () => {
|
||||
>
|
||||
<NativeStack.Screen name="Intro" component={Intro} />
|
||||
<NativeStack.Screen name="AppLock" component={AppLock} />
|
||||
<NativeStack.Screen
|
||||
name="Auth"
|
||||
initialParams={{
|
||||
mode: 0
|
||||
}}
|
||||
component={Auth}
|
||||
/>
|
||||
</IntroStack.Navigator>
|
||||
);
|
||||
};
|
||||
@@ -92,20 +81,6 @@ const Tabs = React.memo(
|
||||
}
|
||||
}}
|
||||
>
|
||||
<NativeStack.Screen
|
||||
name="Signup"
|
||||
initialParams={{
|
||||
mode: 1
|
||||
}}
|
||||
component={Auth}
|
||||
/>
|
||||
<NativeStack.Screen
|
||||
name="Login"
|
||||
initialParams={{
|
||||
mode: 0
|
||||
}}
|
||||
component={Auth}
|
||||
/>
|
||||
<NativeStack.Screen name="Welcome" component={IntroStackNavigator} />
|
||||
<NativeStack.Screen name="Notes" component={Home} />
|
||||
<NativeStack.Screen name="Notebooks" component={Notebooks} />
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { View } from 'react-native';
|
||||
import * as Progress from 'react-native-progress';
|
||||
import { useThemeStore } from '../../stores/use-theme-store';
|
||||
import { useAttachmentStore } from '../../stores/use-attachment-store';
|
||||
import { SIZE } from '../../utils/size';
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
import { ProgressBarComponent } from '../../components/ui/svg/lazy';
|
||||
|
||||
export const ProgressBar = () => {
|
||||
const colors = useThemeStore(state => state.colors);
|
||||
@@ -50,14 +50,16 @@ export const ProgressBar = () => {
|
||||
}}
|
||||
onLayout={event => setWidth(event.nativeEvent.layout.width)}
|
||||
>
|
||||
<Progress.Bar
|
||||
size={SIZE.xxl}
|
||||
progress={prog}
|
||||
color={colors.accent}
|
||||
borderWidth={0}
|
||||
height={1}
|
||||
width={width || 400}
|
||||
/>
|
||||
<React.Suspense fallback={<View />}>
|
||||
<ProgressBarComponent
|
||||
size={SIZE.xxl}
|
||||
progress={prog}
|
||||
color={colors.accent}
|
||||
borderWidth={0}
|
||||
height={1}
|
||||
width={width || 400}
|
||||
/>
|
||||
</React.Suspense>
|
||||
</View>
|
||||
) : null;
|
||||
};
|
||||
|
||||
@@ -72,8 +72,8 @@ export const useEditor = (editorId = '', readonly?: boolean) => {
|
||||
useEffect(() => {
|
||||
console.log('sessionId:', sessionId);
|
||||
async () => {
|
||||
await commands.setSessionId(sessionId);
|
||||
if (sessionId) {
|
||||
await commands.setSessionId(sessionIdRef.current);
|
||||
if (sessionIdRef.current) {
|
||||
if (!state.current?.ready) return;
|
||||
await onReady();
|
||||
}
|
||||
@@ -88,7 +88,7 @@ export const useEditor = (editorId = '', readonly?: boolean) => {
|
||||
};
|
||||
|
||||
const onReady = useCallback(async () => {
|
||||
if (!(await isEditorLoaded(editorRef, sessionId))) {
|
||||
if (!(await isEditorLoaded(editorRef, sessionIdRef.current))) {
|
||||
console.log('reload editor');
|
||||
overlay(true);
|
||||
setLoading(true);
|
||||
|
||||
@@ -47,21 +47,18 @@ export const Notebooks = ({ navigation, route }: NavigationProps<'Notebooks'>) =
|
||||
});
|
||||
SearchService.prepareSearch = prepareSearch;
|
||||
RightMenus.floatingButtonAction = onPressFloatingButton;
|
||||
return !prev?.current;
|
||||
},
|
||||
onBlur: () => false,
|
||||
delay: SettingsService.get().homepage === route.name ? 1 : -1
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (navigation.isFocused()) {
|
||||
if (notebooks.length === 0) {
|
||||
Walkthrough.present('notebooks');
|
||||
} else {
|
||||
Walkthrough.update('notebooks');
|
||||
}
|
||||
}
|
||||
}, [notebooks]);
|
||||
|
||||
return !prev?.current;
|
||||
},
|
||||
onBlur: () => false,
|
||||
delay: SettingsService.get().homepage === route.name ? 1 : -1
|
||||
});
|
||||
|
||||
return (
|
||||
<DelayLayout>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { NativeStackScreenProps } from '@react-navigation/native-stack';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { FlatList, View } from 'react-native';
|
||||
import { Bar } from 'react-native-progress';
|
||||
import Animated, { FadeInDown, FadeOutDown } from 'react-native-reanimated';
|
||||
import DelayLayout from '../../components/delay-layout';
|
||||
import BaseDialog from '../../components/dialog/base-dialog';
|
||||
import { ProgressBarComponent } from '../../components/ui/svg/lazy';
|
||||
import Heading from '../../components/ui/typography/heading';
|
||||
import Paragraph from '../../components/ui/typography/paragraph';
|
||||
import { eSubscribeEvent, eUnSubscribeEvent } from '../../services/event-manager';
|
||||
@@ -71,17 +71,19 @@ const Home = ({ navigation, route }: NativeStackScreenProps<RouteParams, 'Settin
|
||||
marginTop: 15
|
||||
}}
|
||||
>
|
||||
<Bar
|
||||
height={5}
|
||||
width={100}
|
||||
animated={true}
|
||||
useNativeDriver
|
||||
indeterminate
|
||||
indeterminateAnimationDuration={2000}
|
||||
unfilledColor={colors.nav}
|
||||
color={colors.accent}
|
||||
borderWidth={0}
|
||||
/>
|
||||
<React.Suspense fallback={<View />}>
|
||||
<ProgressBarComponent
|
||||
height={5}
|
||||
width={100}
|
||||
animated={true}
|
||||
useNativeDriver
|
||||
indeterminate
|
||||
indeterminateAnimationDuration={2000}
|
||||
unfilledColor={colors.nav}
|
||||
color={colors.accent}
|
||||
borderWidth={0}
|
||||
/>
|
||||
</React.Suspense>
|
||||
</View>
|
||||
</View>
|
||||
</BaseDialog>
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { createNativeStackNavigator } from '@react-navigation/native-stack';
|
||||
import { createNativeStackNavigator, NativeStackScreenProps } from '@react-navigation/native-stack';
|
||||
import React from 'react';
|
||||
import DelayLayout from '../../components/delay-layout';
|
||||
import { Header } from '../../components/header';
|
||||
import useNavigationStore from '../../stores/use-navigation-store';
|
||||
import { useThemeStore } from '../../stores/use-theme-store';
|
||||
import Group from './group';
|
||||
import Home from './home';
|
||||
import { RouteParams } from './types';
|
||||
|
||||
const SettingsStack = createNativeStackNavigator();
|
||||
const screenListeners = {
|
||||
@@ -15,6 +16,34 @@ const screenListeners = {
|
||||
}
|
||||
};
|
||||
|
||||
const Home = React.lazy(() => import(/* webpackChunkName: "settings-home" */ './home'));
|
||||
const Group = React.lazy(() => import(/* webpackChunkName: "settings-group" */ './group'));
|
||||
|
||||
const Fallback = () => {
|
||||
return (
|
||||
<>
|
||||
<Header />
|
||||
<DelayLayout wait={true} type="settings" />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const HomeScreen = (props: NativeStackScreenProps<RouteParams, 'SettingsHome'>) => {
|
||||
return (
|
||||
<React.Suspense fallback={<Fallback />}>
|
||||
<Home {...props} />
|
||||
</React.Suspense>
|
||||
);
|
||||
};
|
||||
|
||||
const GroupScreen = (props: NativeStackScreenProps<RouteParams, 'SettingsGroup'>) => {
|
||||
return (
|
||||
<React.Suspense fallback={<Fallback />}>
|
||||
<Group {...props} />
|
||||
</React.Suspense>
|
||||
);
|
||||
};
|
||||
|
||||
export const Settings = () => {
|
||||
const colors = useThemeStore(state => state.colors);
|
||||
return (
|
||||
@@ -29,8 +58,8 @@ export const Settings = () => {
|
||||
}
|
||||
}}
|
||||
>
|
||||
<SettingsStack.Screen name="SettingsHome" component={Home} />
|
||||
<SettingsStack.Screen name="SettingsGroup" component={Group} />
|
||||
<SettingsStack.Screen name="SettingsHome" component={HomeScreen} />
|
||||
<SettingsStack.Screen name="SettingsGroup" component={GroupScreen} />
|
||||
</SettingsStack.Navigator>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,34 +1,46 @@
|
||||
import Database from 'notes-core/api/index';
|
||||
import { Platform } from 'react-native';
|
||||
import filesystem from '../filesystem';
|
||||
import EventSource from '../sse/even-source-ios';
|
||||
import AndroidEventSource from '../sse/event-source';
|
||||
import Storage from './storage';
|
||||
|
||||
export const db = new Database(
|
||||
Storage,
|
||||
Platform.OS === 'ios' ? EventSource : AndroidEventSource,
|
||||
filesystem
|
||||
);
|
||||
db.host(
|
||||
__DEV__
|
||||
? {
|
||||
API_HOST: 'https://api.notesnook.com',
|
||||
AUTH_HOST: 'https://auth.streetwriters.co',
|
||||
SSE_HOST: 'https://events.streetwriters.co',
|
||||
SUBSCRIPTIONS_HOST: 'https://subscriptions.streetwriters.co',
|
||||
ISSUES_HOST: 'https://issues.streetwriters.co'
|
||||
// API_HOST: 'http://192.168.10.29:5264',
|
||||
// AUTH_HOST: 'http://192.168.10.29:8264',
|
||||
// SSE_HOST: 'http://192.168.10.29:7264',
|
||||
// SUBSCRIPTIONS_HOST: 'http://192.168.10.29:9264',
|
||||
// ISSUES_HOST: 'http://192.168.10.29:2624'
|
||||
}
|
||||
: {
|
||||
API_HOST: 'https://api.notesnook.com',
|
||||
AUTH_HOST: 'https://auth.streetwriters.co',
|
||||
SSE_HOST: 'https://events.streetwriters.co',
|
||||
SUBSCRIPTIONS_HOST: 'https://subscriptions.streetwriters.co',
|
||||
ISSUES_HOST: 'https://issues.streetwriters.co'
|
||||
}
|
||||
);
|
||||
/**
|
||||
* @type {import("notes-core/api/index").default}
|
||||
*/
|
||||
export var db;
|
||||
|
||||
let DB = null;
|
||||
export async function loadDatabase() {
|
||||
if (!DB) {
|
||||
let module = await import(/* webpackChunkName: "notes-core" */ 'notes-core/api/index');
|
||||
DB = module.default;
|
||||
}
|
||||
db = new DB(Storage, Platform.OS === 'ios' ? EventSource : AndroidEventSource, filesystem);
|
||||
//@ts-ignore
|
||||
if (DOMParser) {
|
||||
//@ts-ignore
|
||||
await DOMParser.prepare();
|
||||
}
|
||||
db.host(
|
||||
__DEV__
|
||||
? {
|
||||
API_HOST: 'https://api.notesnook.com',
|
||||
AUTH_HOST: 'https://auth.streetwriters.co',
|
||||
SSE_HOST: 'https://events.streetwriters.co',
|
||||
SUBSCRIPTIONS_HOST: 'https://subscriptions.streetwriters.co',
|
||||
ISSUES_HOST: 'https://issues.streetwriters.co'
|
||||
// API_HOST: 'http://192.168.10.29:5264',
|
||||
// AUTH_HOST: 'http://192.168.10.29:8264',
|
||||
// SSE_HOST: 'http://192.168.10.29:7264',
|
||||
// SUBSCRIPTIONS_HOST: 'http://192.168.10.29:9264',
|
||||
// ISSUES_HOST: 'http://192.168.10.29:2624'
|
||||
}
|
||||
: {
|
||||
API_HOST: 'https://api.notesnook.com',
|
||||
AUTH_HOST: 'https://auth.streetwriters.co',
|
||||
SSE_HOST: 'https://events.streetwriters.co',
|
||||
SUBSCRIPTIONS_HOST: 'https://subscriptions.streetwriters.co',
|
||||
ISSUES_HOST: 'https://issues.streetwriters.co'
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -233,15 +233,7 @@ export const useActions = ({ close = () => {}, item }) => {
|
||||
message: 'Login to publish note',
|
||||
context: 'local',
|
||||
func: () => {
|
||||
Navigation.navigate(
|
||||
{
|
||||
name: 'Login'
|
||||
},
|
||||
{
|
||||
mode: AuthMode.login,
|
||||
canGoBack: true
|
||||
}
|
||||
);
|
||||
eSendEvent(eOpenLoginDialog);
|
||||
},
|
||||
actionText: 'Login'
|
||||
});
|
||||
|
||||
@@ -126,7 +126,7 @@ export async function toTXT(note, notitle) {
|
||||
} else {
|
||||
text = await db.notes.note(note.id).content();
|
||||
}
|
||||
htmlToText = htmlToText || require('html-to-text');
|
||||
htmlToText = htmlToText || (await import('html-to-text'));
|
||||
text = htmlToText.convert(text, {
|
||||
selectors: [{ selector: 'img', format: 'skip' }]
|
||||
});
|
||||
|
||||
271
apps/mobile/webpack.config.cjs
Normal file
271
apps/mobile/webpack.config.cjs
Normal file
@@ -0,0 +1,271 @@
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const path = require('path');
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
const Repack = require('@callstack/repack');
|
||||
|
||||
/**
|
||||
* More documentation, installation, usage, motivation and differences with Metro is available at:
|
||||
* https://github.com/callstack/repack/blob/main/README.md
|
||||
*
|
||||
* The API documentation for the functions and plugins used in this file is available at:
|
||||
* https://re-pack.netlify.app/
|
||||
*/
|
||||
|
||||
/**
|
||||
* Webpack configuration.
|
||||
* You can also export a static object or a function returning a Promise.
|
||||
*
|
||||
* @param env Environment options passed from either Webpack CLI or React Native CLI
|
||||
* when running with `react-native start/bundle`.
|
||||
*/
|
||||
module.exports = env => {
|
||||
const {
|
||||
mode = 'development',
|
||||
context = __dirname,
|
||||
entry = './index.js',
|
||||
platform,
|
||||
minimize = mode === 'production',
|
||||
devServer = undefined,
|
||||
bundleFilename = undefined,
|
||||
sourceMapFilename = undefined,
|
||||
assetsPath = undefined,
|
||||
reactNativePath = require.resolve('react-native')
|
||||
} = env;
|
||||
|
||||
if (!platform) {
|
||||
throw new Error('Missing platform');
|
||||
}
|
||||
|
||||
/**
|
||||
* Depending on your Babel configuration you might want to keep it.
|
||||
* If you don't use `env` in your Babel config, you can remove it.
|
||||
*
|
||||
* Keep in mind that if you remove it you should set `BABEL_ENV` or `NODE_ENV`
|
||||
* to `development` or `production`. Otherwise your production code might be compiled with
|
||||
* in development mode by Babel.
|
||||
*/
|
||||
process.env.BABEL_ENV = mode;
|
||||
|
||||
return {
|
||||
mode,
|
||||
/**
|
||||
* This should be always `false`, since the Source Map configuration is done
|
||||
* by `SourceMapDevToolPlugin`.
|
||||
*/
|
||||
devtool: false,
|
||||
context,
|
||||
/**
|
||||
* `getInitializationEntries` will return necessary entries with setup and initialization code.
|
||||
* If you don't want to use Hot Module Replacement, set `hmr` option to `false`. By default,
|
||||
* HMR will be enabled in development mode.
|
||||
*/
|
||||
entry: [
|
||||
...Repack.getInitializationEntries(reactNativePath, {
|
||||
hmr: devServer && devServer.hmr
|
||||
}),
|
||||
entry
|
||||
],
|
||||
resolve: {
|
||||
/**
|
||||
* `getResolveOptions` returns additional resolution configuration for React Native.
|
||||
* If it's removed, you won't be able to use `<file>.<platform>.<ext>` (eg: `file.ios.js`)
|
||||
* convention and some 3rd-party libraries that specify `react-native` field
|
||||
* in their `package.json` might not work correctly.
|
||||
*/
|
||||
...Repack.getResolveOptions(platform)
|
||||
|
||||
/**
|
||||
* Uncomment this to ensure all `react-native*` imports will resolve to the same React Native
|
||||
* dependency. You might need it when using workspaces/monorepos or unconventional project
|
||||
* structure. For simple/typical project you won't need it.
|
||||
*/
|
||||
// alias: {
|
||||
// 'react-native': reactNativePath,
|
||||
// },
|
||||
},
|
||||
/**
|
||||
* Configures output.
|
||||
* It's recommended to leave it as it is unless you know what you're doing.
|
||||
* By default Webpack will emit files into the directory specified under `path`. In order for the
|
||||
* React Native app use them when bundling the `.ipa`/`.apk`, they need to be copied over with
|
||||
* `Repack.OutputPlugin`, which is configured by default inside `Repack.RepackPlugin`.
|
||||
*/
|
||||
output: {
|
||||
clean: true,
|
||||
path: path.join(__dirname, 'build/generated', platform),
|
||||
filename: 'index.bundle',
|
||||
chunkFilename: '[name].chunk.bundle',
|
||||
publicPath: Repack.getPublicPath({ platform, devServer })
|
||||
},
|
||||
/**
|
||||
* Configures optimization of the built bundle.
|
||||
*/
|
||||
optimization: {
|
||||
/** Enables minification based on values passed from React Native CLI or from fallback. */
|
||||
minimize,
|
||||
/** Configure minimizer to process the bundle. */
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
test: /\.(js)?bundle(\?.*)?$/i,
|
||||
/**
|
||||
* Prevents emitting text file with comments, licenses etc.
|
||||
* If you want to gather in-file licenses, feel free to remove this line or configure it
|
||||
* differently.
|
||||
*/
|
||||
extractComments: false,
|
||||
terserOptions: {
|
||||
format: {
|
||||
comments: false
|
||||
}
|
||||
}
|
||||
})
|
||||
],
|
||||
chunkIds: 'named'
|
||||
},
|
||||
module: {
|
||||
/**
|
||||
* This rule will process all React Native related dependencies with Babel.
|
||||
* If you have a 3rd-party dependency that you need to transpile, you can add it to the
|
||||
* `include` list.
|
||||
*
|
||||
* You can also enable persistent caching with `cacheDirectory` - please refer to:
|
||||
* https://github.com/babel/babel-loader#options
|
||||
*/
|
||||
rules: [
|
||||
{
|
||||
test: /\.[jt]sx?$/,
|
||||
include: [
|
||||
/node_modules(.*[/\\])+react/,
|
||||
/node_modules(.*[/\\])+@react-native/,
|
||||
/node_modules(.*[/\\])+@react-navigation/,
|
||||
/node_modules(.*[/\\])+@react-native-community/,
|
||||
/node_modules(.*[/\\])+@expo/,
|
||||
/node_modules(.*[/\\])+pretty-format/,
|
||||
/node_modules(.*[/\\])+metro/,
|
||||
/node_modules(.*[/\\])+abort-controller/,
|
||||
/node_modules(.*[/\\])+@callstack[/\\]repack/,
|
||||
/node_modules(.*[/\\])+pretty-format/,
|
||||
/node_modules(.*[/\\])+@react-native-masked-view\/masked-view/,
|
||||
/node_modules(.*[/\\])+toggle-switch-react-native/,
|
||||
/node_modules(.*[/\\])+rn-fetch-blob/,
|
||||
/node_modules(.*[/\\])+notes-core/,
|
||||
/node_modules(.*[/\\])+@microsoft/,
|
||||
/node_modules(.*[/\\])+@msgpack/,
|
||||
/node_modules(.*[/\\])+liqe/
|
||||
],
|
||||
use: {
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
configFile: false,
|
||||
cacheDirectory: path.join(__dirname, 'node_modules/.webpack-cache'),
|
||||
babelrc: false,
|
||||
presets: ['module:metro-react-native-babel-preset'],
|
||||
plugins: [
|
||||
'react-native-reanimated/plugin',
|
||||
'@babel/plugin-transform-named-capturing-groups-regex'
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Here you can adjust loader that will process your files.
|
||||
*
|
||||
* You can also enable persistent caching with `cacheDirectory` - please refer to:
|
||||
* https://github.com/babel/babel-loader#options
|
||||
*/
|
||||
{
|
||||
test: /\.[jt]sx?$/,
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
/** Add React Refresh transform only when HMR is enabled. */
|
||||
configFile: false,
|
||||
cacheDirectory: path.join(__dirname, 'node_modules/.webpack-cache'),
|
||||
babelrc: false,
|
||||
presets: [
|
||||
['module:metro-react-native-babel-preset', { disableImportExportTransform: true }]
|
||||
],
|
||||
plugins:
|
||||
devServer && devServer.hmr
|
||||
? ['module:react-refresh/babel', 'react-native-reanimated/plugin']
|
||||
: [
|
||||
'react-native-reanimated/plugin',
|
||||
`@babel/plugin-transform-named-capturing-groups-regex`
|
||||
//'transform-remove-console'
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* This loader handles all static assets (images, video, audio and others), so that you can
|
||||
* use (reference) them inside your application.
|
||||
*
|
||||
* If you wan to handle specific asset type manually, filter out the extension
|
||||
* from `ASSET_EXTENSIONS`, for example:
|
||||
* ```
|
||||
* Repack.ASSET_EXTENSIONS.filter((ext) => ext !== 'svg')
|
||||
* ```
|
||||
*/
|
||||
{
|
||||
test: Repack.getAssetExtensionsRegExp(
|
||||
Repack.ASSET_EXTENSIONS.filter(ext => ext !== 'svg')
|
||||
),
|
||||
use: {
|
||||
loader: '@callstack/repack/assets-loader',
|
||||
options: {
|
||||
platform,
|
||||
devServerEnabled: Boolean(devServer),
|
||||
/**
|
||||
* Defines which assets are scalable - which assets can have
|
||||
* scale suffixes: `@1x`, `@2x` and so on.
|
||||
* By default all images are scalable.
|
||||
*/
|
||||
scalableAssetExtensions: Repack.SCALABLE_ASSETS
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.svg$/,
|
||||
use: [
|
||||
{
|
||||
loader: '@svgr/webpack',
|
||||
options: {
|
||||
native: true,
|
||||
dimensions: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
/**
|
||||
* Configure other required and additional plugins to make the bundle
|
||||
* work in React Native and provide good development experience with
|
||||
* sensible defaults.
|
||||
*
|
||||
* `Repack.RepackPlugin` provides some degree of customization, but if you
|
||||
* need more control, you can replace `Repack.RepackPlugin` with plugins
|
||||
* from `Repack.plugins`.
|
||||
*/
|
||||
new Repack.RepackPlugin({
|
||||
context,
|
||||
mode,
|
||||
platform,
|
||||
devServer,
|
||||
output: {
|
||||
bundleFilename,
|
||||
sourceMapFilename,
|
||||
assetsPath
|
||||
},
|
||||
extraChunks: [
|
||||
{
|
||||
type: 'local',
|
||||
include: /.*/
|
||||
}
|
||||
]
|
||||
})
|
||||
]
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user