Skip to content

Quick and dirty fix for the #388 HMR issue #444

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions platform/nativescript/plugins/navigator-plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { isObject, isDef, isPrimitive } from 'shared/util'
import { getFrame } from '../util/frame'
import { getFrameById } from 'tns-core-modules/ui/frame'

function getFrameInstance(frame) {
export function getFrameInstance(frame) {
// get the frame that we need to navigate
// this can be a frame id (String)
// a Vue ref to a frame
Expand All @@ -19,7 +19,7 @@ function getFrameInstance(frame) {
return getFrame(frame.id)
}

function _findParentNavigationEntry(vm) {
export function findParentNavigationEntry(vm) {
if (!vm) {
return false
}
Expand All @@ -35,7 +35,7 @@ function _findParentNavigationEntry(vm) {
export default {
install(Vue) {
Vue.prototype.$navigateBack = function(options, backstackEntry = null) {
const navEntry = _findParentNavigationEntry(this)
const navEntry = findParentNavigationEntry(this)
const defaultOptions = {
frame: navEntry ? navEntry.$options.frame : 'default'
}
Expand Down
4 changes: 2 additions & 2 deletions platform/nativescript/renderer/ViewNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ export default class ViewNode {
this._meta = null

/* istanbul ignore next
* make vue happy :)
*/
* make vue happy :)
*/
this.hasAttribute = this.removeAttribute = () => false
}

Expand Down
102 changes: 97 additions & 5 deletions platform/nativescript/runtime/components/frame.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { setFrame, getFrame, deleteFrame } from '../../util/frame'
import { extend } from 'shared/util'
import { isAndroid } from 'tns-core-modules/platform'
import { isHMRChecking, resetHMRChecking } from '../../util/hmr'
import { isAndroid, isIOS } from 'tns-core-modules/platform'
import { ios as iosUtils } from 'tns-core-modules/utils/utils'
import { _setAndroidFragmentTransitions } from 'tns-core-modules/ui/frame/fragment.transitions'

let idCounter = 1

Expand Down Expand Up @@ -88,13 +90,103 @@ export default {
},

notifyPageMounted(pageVm) {
let options = {
create: () => pageVm.$el.nativeView
}

this.$nextTick(() => {
this.navigate({
create: () => pageVm.$el.nativeView
})
if (isHMRChecking()) {
this.replace(options)
} else {
this.navigate(options)
}
})
},

replace(entry) {
const frame = this._getFrame()
const page = entry.create()
entry.create = () => page

const backstackEntry = {
entry: entry,
resolvedPage: page,
navDepth: undefined,
fragmentTag: undefined
}
// TODO: this should be in a specific NS Frame method
if (isIOS) {
let viewController = backstackEntry.resolvedPage.ios
if (!viewController) {
throw new Error(
'Required page does not have a viewController created.'
)
}
viewController['_transition'] = { name: 'non-animated' }
viewController['_delegate'] = null
frame._ios.controller.delegate = null
viewController['_entry'] = backstackEntry

if (iosUtils.MajorVersion > 10) {
// Reset back button title before pushing view controller to prevent
// displaying default 'back' title (when NavigationButton custom title is set).
let barButtonItem = UIBarButtonItem.alloc().initWithTitleStyleTargetAction(
'',
UIBarButtonItemStyle.Plain,
null,
null
)
viewController.navigationItem.backBarButtonItem = barButtonItem
}

let newControllers = NSMutableArray.alloc().initWithArray(
frame._ios.controller.viewControllers
)
if (newControllers.count === 0) {
throw new Error('Wrong controllers count.')
}

// the code below fixes a phantom animation that appears on the Back button in this case
viewController.navigationItem.hidesBackButton =
frame.backStack.length === 0

// swap the top entry with the new one
const skippedNavController = newControllers.lastObject
skippedNavController.isBackstackSkipped = true
newControllers.removeLastObject()
newControllers.addObject(viewController)

// replace the controllers instead of pushing directly
frame._ios.controller.setViewControllersAnimated(newControllers, false)
} else {
const frameId = frame._android.frameId
frame._isBack = false
backstackEntry.frameId = frameId

const manager = frame._getFragmentManager()
const currentEntry = frame._currentEntry

const newFragmentTag = `fragment${frameId}[-1]`
const newFragment = frame.createFragment(backstackEntry, newFragmentTag)
const animated = false
const navigationTransition = null

const transaction = manager.beginTransaction()
_setAndroidFragmentTransitions(
animated,
navigationTransition,
currentEntry,
backstackEntry,
transaction,
frameId
)
transaction.remove(currentEntry.fragment)
transaction.replace(frame.containerViewId, newFragment, newFragmentTag)
transaction.commitAllowingStateLoss()
}
resetHMRChecking()
},

navigate(entry, back = false) {
const frame = this._getFrame()

Expand Down
18 changes: 17 additions & 1 deletion platform/nativescript/runtime/components/page.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
import {
findParentNavigationEntry,
getFrameInstance
} from '../../plugins/navigator-plugin'
import { isHMRChecking } from '../../util/hmr'

export const PAGE_REF = '__vuePageRef__'

export default {
Expand All @@ -14,7 +20,17 @@ export default {
mounted() {
this.$el.nativeView[PAGE_REF] = this

const frame = this._findParentFrame()
let frame = null

if (isHMRChecking()) {
const navEntry = findParentNavigationEntry(this)
const options = {
frame: navEntry ? navEntry.$options.frame : 'default'
}
frame = getFrameInstance(options.frame)
} else {
frame = this._findParentFrame()
}

if (frame) {
frame.notifyPageMounted(this)
Expand Down
4 changes: 3 additions & 1 deletion platform/nativescript/runtime/modules/transition.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ export function enter(vnode, toggleDisplay) {

const beforeEnterHook = isAppear ? beforeAppear || beforeEnter : beforeEnter
const enterHook = isAppear
? typeof appear === 'function' ? appear : enter
? typeof appear === 'function'
? appear
: enter
: enter
const afterEnterHook = isAppear ? afterAppear || afterEnter : afterEnter
const enterCancelledHook = isAppear
Expand Down
17 changes: 17 additions & 0 deletions platform/nativescript/util/hmr.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
let hmrChecking = false

export const isHMRChecking = () => {
return hmrChecking
}

export const resetHMRChecking = () => {
hmrChecking = false
}

if (module.hot) {
module.hot.addStatusHandler(status => {
if (status === 'check') {
hmrChecking = true
}
})
}