Skip to content

Commit

Permalink
fix: prevent reload by adding SCU
Browse files Browse the repository at this point in the history
fixes #75
  • Loading branch information
linonetwo committed Dec 1, 2024
1 parent 06f7bf7 commit b464d70
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 32 deletions.
14 changes: 9 additions & 5 deletions src/pages/WikiWebView/CustomWebview.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
import React, { MutableRefObject, PureComponent } from 'react';
import React, { Component, MutableRefObject } from 'react';
import { Text } from 'react-native-paper';
import { WebView, WebViewMessageEvent } from 'react-native-webview';
import type { WebViewErrorEvent, WebViewNavigationEvent } from 'react-native-webview/lib/RNCWebViewNativeComponent';
import { FAKE_USER_AGENT } from '../../constants/webview';

interface CustomWebViewProps {
backgroundColor: string;
injectedJavaScript: string;
onLoadEnd: (event: WebViewNavigationEvent | WebViewErrorEvent) => void;
onLoadStart: () => void;
onLoadEnd?: () => void;
onLoadStart?: () => void;
onMessageReference: MutableRefObject<(event: WebViewMessageEvent) => void>;
preferredLanguage: string | undefined | null;
reloadingKey: string | number;
triggerFullReload: () => void;
webViewReference: MutableRefObject<WebView | null>;
}

export class CustomWebView extends PureComponent<CustomWebViewProps> {
export class CustomWebView extends Component<CustomWebViewProps> {
shouldComponentUpdate(nextProps: CustomWebViewProps) {
return this.props.reloadingKey !== nextProps.reloadingKey;
}

render() {
const {
backgroundColor,
Expand Down
13 changes: 6 additions & 7 deletions src/pages/WikiWebView/WikiViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export function WikiViewer({ wikiWorkspace, webviewSideReceiver, quickLoad }: Wi
* Register service JSB to be `window.service.xxxService`, for plugin in webView to call.
*/
const [webViewReference, onMessageReference, registerWikiStorageServiceOnWebView, servicesOfWorkspace] = useRegisterService(wikiWorkspace);
useSetWebViewReferenceToService(servicesOfWorkspace.wikiHookService, webViewReference);
useSetWebViewReferenceToService(servicesOfWorkspace, webViewReference);
// TODO: goback not seem to working
// useHandleGoBack(webViewReference);
/**
Expand All @@ -83,12 +83,12 @@ export function WikiViewer({ wikiWorkspace, webviewSideReceiver, quickLoad }: Wi
triggerFullReload();
}
}, [triggerFullReload, webViewKeyToReloadAfterRecycleByOS]);
servicesOfWorkspace.wikiHookService.setLatestTriggerFullReloadCallback(triggerFullReload);
servicesOfWorkspace.current?.wikiHookService?.setLatestTriggerFullReloadCallback?.(triggerFullReload);
useEffect(() => {
console.log('resetWebviewReceiverReady on webViewKeyToReloadAfterRecycleByOS and init');
servicesOfWorkspace.wikiHookService.resetWebviewReceiverReady();
servicesOfWorkspace.current?.wikiHookService?.resetWebviewReceiverReady?.();
void backgroundSyncService.updateServerOnlineStatus();
}, [servicesOfWorkspace.wikiHookService, webViewKeyToReloadAfterRecycleByOS]);
}, [servicesOfWorkspace, webViewKeyToReloadAfterRecycleByOS]);
const { loadHtmlError, loading, streamChunksToWebViewPercentage } = useTiddlyWiki(
wikiWorkspace,
loaded,
Expand Down Expand Up @@ -127,18 +127,17 @@ export function WikiViewer({ wikiWorkspace, webviewSideReceiver, quickLoad }: Wi
* Quick load is very fast, progress bar will flash and disappear. So we don't show it.
*/
const showProgressBar = loading && !quickLoad;
// TODO: check if webViewKeyToReloadAfterRecycleByOS on component is working. Sometimes the source works, but preload is not applied
return (
<>
<TopProgressBar animatedValue={streamChunksToWebViewPercentage} color={MD3Colors.neutral50} />
<WebViewContainer showProgressBar={showProgressBar}>
<CustomWebView
webViewReference={webViewReference}
backgroundColor={theme.colors.background}
key={webViewKeyToReloadAfterRecycleByOS}
reloadingKey={webViewKeyToReloadAfterRecycleByOS}
preferredLanguage={preferredLanguage ?? detectedLanguage}
onLoadEnd={onLoadEnd}
onLoadStart={onLoadStart}
onLoadEnd={onLoadEnd}
onMessageReference={onMessageReference}
injectedJavaScript={preloadScript}
triggerFullReload={triggerFullReload}
Expand Down
14 changes: 7 additions & 7 deletions src/pages/WikiWebView/useStreamChunksToWebView/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import { OnStreamChunksToWebViewEventTypes } from './streamChunksPreloadScript';
* @url https://github.com/react-native-webview/react-native-webview/issues/3126
* @returns
*/
export function useStreamChunksToWebView(webViewReference: MutableRefObject<WebView | null>, servicesOfWorkspace: {
wikiHookService: WikiHookService;
wikiStorageService: WikiStorageService;
}) {
export function useStreamChunksToWebView(
webViewReference: MutableRefObject<WebView | null>,
servicesOfWorkspace: MutableRefObject<{ wikiHookService: WikiHookService; wikiStorageService: WikiStorageService } | undefined>,
) {
const [streamChunksToWebViewPercentage, setStreamChunksToWebViewPercentage] = useState(0);
const sendDataToWebView = useCallback((messageType: OnStreamChunksToWebViewEventTypes, data?: string) => {
console.log(`sendDataToWebView ${messageType}`);
Expand All @@ -41,12 +41,12 @@ export function useStreamChunksToWebView(webViewReference: MutableRefObject<WebV
*/
const injectHtmlAndTiddlersStore = useCallback(async ({ html, tiddlersStream, setLoadHtmlError }: IHtmlContent) => {
// start using `window.onStreamChunksToWebView` only when webviewLoaded, which means preload script is loaded.
if (webViewReference.current !== null) {
if (webViewReference.current !== null && servicesOfWorkspace.current !== undefined) {
try {
// Huawei HONOR device need to wait for a while before sending large data, otherwise first message (send HTML) will lost, cause white screen (no HTML loaded). Maybe its webview has bug.
// Instead of `if (brand === 'HONOR') await new Promise<void>(resolve => setTimeout(resolve, 1000));}`, we use heart beat to check if it is ready.
// This is also required when app bring from background after a while, the webview will be recycled, and need to wait for it to resume before sending large data, otherwise first few data will be lost.
await servicesOfWorkspace.wikiHookService.waitForWebviewReceiverReady(() => {
await servicesOfWorkspace.current.wikiHookService.waitForWebviewReceiverReady(() => {
sendDataToWebView(OnStreamChunksToWebViewEventTypes.CHECK_RECEIVER_READY);
});
/**
Expand Down Expand Up @@ -97,7 +97,7 @@ export function useStreamChunksToWebView(webViewReference: MutableRefObject<WebV
throw error;
}
}
}, [webViewReference, servicesOfWorkspace.wikiHookService, sendDataToWebView]);
}, [webViewReference, servicesOfWorkspace, sendDataToWebView]);

return { injectHtmlAndTiddlersStore, streamChunksToWebViewPercentage };
}
5 changes: 1 addition & 4 deletions src/pages/WikiWebView/useTiddlyWiki.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,7 @@ export function useTiddlyWiki(
webViewReference: MutableRefObject<WebView | null>,
keyToTriggerReload: number,
quickLoad: boolean,
servicesOfWorkspace: {
wikiHookService: WikiHookService;
wikiStorageService: WikiStorageService;
},
servicesOfWorkspace: MutableRefObject<{ wikiHookService: WikiHookService; wikiStorageService: WikiStorageService } | undefined>,
) {
const [loadHtmlError, setLoadHtmlError] = useState('');
const tiddlersStreamReference = useRef<SQLiteTiddlersReadStream | undefined>();
Expand Down
14 changes: 9 additions & 5 deletions src/services/WikiHookService/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useRegisterProxy } from 'react-native-postmessage-cat';
import { WebView } from 'react-native-webview';
import { IWikiWorkspace } from '../../store/workspace';
import { nativeService } from '../NativeService';
import { WikiStorageService } from '../WikiStorageService';
import { WikiHookService } from '.';
import { WikiHookServiceIPCDescriptor } from './descriptor';

Expand All @@ -12,14 +13,17 @@ export function useWikiHookService(workspace: IWikiWorkspace) {
return [webViewReference, onMessageReference, wikiHookService] as const;
}

export function useSetWebViewReferenceToService(wikiHookService: WikiHookService, webViewReference: MutableRefObject<WebView | null>) {
export function useSetWebViewReferenceToService(
servicesOfWorkspace: MutableRefObject<{ wikiHookService: WikiHookService; wikiStorageService: WikiStorageService } | undefined>,
webViewReference: MutableRefObject<WebView | null>,
) {
useEffect(() => {
if (wikiHookService !== undefined) {
wikiHookService.setLatestWebViewReference(webViewReference);
nativeService.setCurrentWikiHookServices(wikiHookService);
if (servicesOfWorkspace.current !== undefined) {
servicesOfWorkspace.current.wikiHookService.setLatestWebViewReference(webViewReference);
nativeService.setCurrentWikiHookServices(servicesOfWorkspace.current.wikiHookService);
return () => {
nativeService.clearCurrentWikiHookServices();
};
}
}, [webViewReference, wikiHookService]);
}, [webViewReference]);
}
15 changes: 11 additions & 4 deletions src/services/registerServiceOnWebView.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useEffect, useRef } from 'react';
import { useMergedReference } from 'react-native-postmessage-cat';
import { IWikiWorkspace } from '../store/workspace';
import { AppDataServiceIPCDescriptor } from './AppDataService/descriptor';
Expand Down Expand Up @@ -58,10 +59,16 @@ export function useRegisterService(workspace: IWikiWorkspace) {
/**
* Services that are limited to the workspace. Can not be accessed globally.
*/
const servicesOfWorkspace = {
wikiStorageService,
wikiHookService,
};
const servicesOfWorkspace = useRef<{
wikiHookService: typeof wikiHookService;
wikiStorageService: typeof wikiStorageService;
}>();
useEffect(() => {
servicesOfWorkspace.current = {
wikiStorageService,
wikiHookService,
};
}, [wikiStorageService, wikiHookService]);

return [mergedWebViewReference, mergedOnMessageReference, registerServiceOnWebView, servicesOfWorkspace] as const;
}

0 comments on commit b464d70

Please sign in to comment.