diff --git a/packages/svelte-hmr/lib/make-hot.js b/packages/svelte-hmr/lib/make-hot.js index b9a68fe..c4c0e70 100644 --- a/packages/svelte-hmr/lib/make-hot.js +++ b/packages/svelte-hmr/lib/make-hot.js @@ -76,7 +76,9 @@ const renderApplyHmr = ({ emitCss, imports = [ `import * as ${globalName} from ${JSON.stringify(hotApiImport)}`, - `import { adapter as ${importAdapterName} } from ${JSON.stringify(adapterImport)}`, + `import { adapter as ${importAdapterName} } from ${JSON.stringify( + adapterImport + )}`, ], }) => // this silly formatting keeps all original characters in their position, diff --git a/packages/svelte-hmr/runtime/svelte-native/proxy-adapter-native.js b/packages/svelte-hmr/runtime/svelte-native/proxy-adapter-native.js index f927072..dc4a0c3 100644 --- a/packages/svelte-hmr/runtime/svelte-native/proxy-adapter-native.js +++ b/packages/svelte-hmr/runtime/svelte-native/proxy-adapter-native.js @@ -47,65 +47,11 @@ const getNavTransition = ({ transition }) => { return transition ? { animated: true, transition } : { animated: false } } -// copied from TNS FrameBase.replacePage -// -// it is not public but there is a comment in there indicating it is for -// HMR (probably their own core HMR though) -// -// NOTE this "worked" in TNS 5, but not anymore in TNS 6: updated version bellow -// -// eslint-disable-next-line no-unused-vars -const replacePage_tns5 = (frame, newPageElement, hotOptions) => { - const currentBackstackEntry = frame._currentEntry - frame.navigationType = 2 - frame.performNavigation({ - isBackNavigation: false, - entry: { - resolvedPage: newPageElement.nativeView, - // - // entry: currentBackstackEntry.entry, - entry: Object.assign( - currentBackstackEntry.entry, - getNavTransition(hotOptions) - ), - navDepth: currentBackstackEntry.navDepth, - fragmentTag: currentBackstackEntry.fragmentTag, - frameId: currentBackstackEntry.frameId, - }, - }) -} - -// Updated for TNS v6 -// -// https://github.com/NativeScript/NativeScript/blob/6.1.1/tns-core-modules/ui/frame/frame-common.ts#L656 -const replacePage = (frame, newPageElement) => { - const currentBackstackEntry = frame._currentEntry - const newPage = newPageElement.nativeView - const newBackstackEntry = { - entry: currentBackstackEntry.entry, - resolvedPage: newPage, - navDepth: currentBackstackEntry.navDepth, - fragmentTag: currentBackstackEntry.fragmentTag, - frameId: currentBackstackEntry.frameId, - } - const navigationContext = { - entry: newBackstackEntry, - isBackNavigation: false, - navigationType: 2 /* NavigationType replace */, - } - frame._navigationQueue.push(navigationContext) - frame._processNextNavigationEntry() -} - export const adapter = class ProxyAdapterNative extends ProxyAdapterDom { constructor(instance) { super(instance) this.nativePageElement = null - this.originalNativeView = null - this.navigatedFromHandler = null - - this.relayNativeNavigatedFrom = this.relayNativeNavigatedFrom.bind(this) } dispose() { @@ -120,31 +66,6 @@ export const adapter = class ProxyAdapterNative extends ProxyAdapterDom { } } - // svelte-native uses navigateFrom event + e.isBackNavigation to know - // when to $destroy the component -- but we don't want our proxy instance - // destroyed when we renavigate to the same page for navigation purposes! - interceptPageNavigation(pageElement) { - const originalNativeView = pageElement.nativeView - const { on } = originalNativeView - const ownOn = originalNativeView.hasOwnProperty('on') - // tricks svelte-native into giving us its handler - originalNativeView.on = function(type, handler) { - if (type === 'navigatedFrom') { - this.navigatedFromHandler = handler - if (ownOn) { - originalNativeView.on = on - } else { - delete originalNativeView.on - } - } else { - //some other handler wireup, we will just pass it on. - if (on) { - on(type, handler) - } - } - } - } - afterMount(target, anchor) { // nativePageElement needs to be updated each time (only for page // components, native component that are not pages follow normal flow) @@ -168,7 +89,6 @@ export const adapter = class ProxyAdapterNative extends ProxyAdapterDom { target.firstChild.tagName == 'page' if (isNativePage) { const nativePageElement = target.firstChild - this.interceptPageNavigation(nativePageElement) this.nativePageElement = nativePageElement } else { // try to protect against components changing from page to no-page @@ -216,6 +136,15 @@ export const adapter = class ProxyAdapterNative extends ProxyAdapterDom { throw new Error('Failed to create updated page') } const isFirstPage = !frame.canGoBack() + const nativeView = newPageElement.nativeView + const navigationEntry = Object.assign( + {}, + { + create: () => nativeView, + clearHistory: true, + }, + getNavTransition(hotOptions) + ) if (isFirstPage) { // NOTE not so sure of bellow with the new NS6 method for replace @@ -233,19 +162,9 @@ export const adapter = class ProxyAdapterNative extends ProxyAdapterDom { // // Fortunately, we can overwrite history in this case. // - const nativeView = newPageElement.nativeView - frame.navigate( - Object.assign( - {}, - { - create: () => nativeView, - clearHistory: true, - }, - getNavTransition(hotOptions) - ) - ) + frame.navigate(navigationEntry) } else { - replacePage(frame, newPageElement, hotOptions) + frame.replacePage(navigationEntry) } } else { const backEntry = frame.backStack.find( @@ -295,42 +214,31 @@ export const adapter = class ProxyAdapterNative extends ProxyAdapterDom { const { instance: { refreshComponent }, } = this - const { nativePageElement, relayNativeNavigatedFrom } = this - const oldNativeView = nativePageElement.nativeView + const { nativePageElement: oldNativePageElement } = this + const oldNativeView = oldNativePageElement.nativeView // rerender const target = document.createElement('fragment') + // not using conservative for now, since there's nothing in place here to // leverage it (yet?) -- and it might be easier to miss breakages in native // only code paths refreshComponent(target, null) + // this.nativePageElement is updated in afterMount, triggered by proxy / hooks const newPageElement = this.nativePageElement - // update event proxy - oldNativeView.off('navigatedFrom', relayNativeNavigatedFrom) - nativePageElement.nativeView.on('navigatedFrom', relayNativeNavigatedFrom) - return newPageElement - } - relayNativeNavigatedFrom({ isBackNavigation }) { - const { originalNativeView, navigatedFromHandler } = this - if (!isBackNavigation) { - return - } - if (originalNativeView) { - const { off } = originalNativeView - const ownOff = originalNativeView.hasOwnProperty('off') - originalNativeView.off = function() { - this.navigatedFromHandler = null - if (ownOff) { - originalNativeView.off = off - } else { - delete originalNativeView.off - } - } - } - if (navigatedFromHandler) { - return navigatedFromHandler.apply(this, arguments) + // svelte-native uses navigateFrom event + e.isBackNavigation to know when to $destroy the component. + // To keep that behaviour after refresh, we move event handler from old native view to the new one using + // __navigateFromHandler property that svelte-native provides us with. + const navigateFromHandler = oldNativeView.__navigateFromHandler + if (navigateFromHandler) { + oldNativeView.off('navigatedFrom', navigateFromHandler) + newPageElement.nativeView.on('navigatedFrom', navigateFromHandler) + newPageElement.nativeView.__navigateFromHandler = navigateFromHandler + delete oldNativeView.__navigateFromHandler } + + return newPageElement } renderError(err /* , target, anchor */) {