Skip to content

Commit

Permalink
feat: $navigateTo and $navigateBack
Browse files Browse the repository at this point in the history
  • Loading branch information
rigor789 committed Jun 16, 2020
1 parent 3a386b1 commit 57f1556
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 13 deletions.
13 changes: 13 additions & 0 deletions apps/demo/app/Test.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,17 @@
<Label text="Hello"/>
<Label text="World" @tap="doSomething"/>
<Label :text="msg"/>

<ContentView>
<Frame>
<TestPage/>
</Frame>
</ContentView>
</template>

<script>
import TestPage from './TestPage'
export default {
data() {
return {
Expand All @@ -15,7 +23,12 @@
doSomething() {
console.log('tapped world!')
this.msg += '.'
this.$navigateTo(TestPage)
}
},
components: {
TestPage
}
}
</script>
16 changes: 16 additions & 0 deletions apps/demo/app/TestPage.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<template>
<Page>
<Label text="Test Page" @tap="$navigateBack()"/>
</Page>
</template>

<script>
export default {
mounted() {
console.log('test page mounted')
},
unmounted() {
console.log('test page unmounted')
}
}
</script>
58 changes: 45 additions & 13 deletions packages/runtime/src/plugins/navigation.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { App, Component, h, isRef, nextTick, Ref } from '@vue/runtime-core'
import { App, Component, isRef, nextTick, Ref } from '@vue/runtime-core'
import { Frame, NavigationEntry, Page } from '@nativescript/core'
import { nodeOps, NSVElement, render } from '@nativescript-vue/runtime'
import { createApp, NSVElement } from '@nativescript-vue/runtime'
import { NavigatedData } from '@nativescript/core/ui/page'

declare module '@vue/runtime-core' {
interface ComponentCustomProperties {
Expand All @@ -12,11 +13,15 @@ declare module '@vue/runtime-core' {
* @param target
* @param options
*/
$navigateTo: (target: Component, options: any) => Promise<any>
$navigateTo: (
target: Component,
options?: NavigationOptions
) => Promise<any>
$navigateBack: (options?: NavigationOptions) => void
}
}

export interface NavigateToOptions extends NavigationEntry {
export interface NavigationOptions extends NavigationEntry {
props?: Record<string, any>
frame?: string | Ref | NSVElement | Frame
}
Expand All @@ -26,9 +31,10 @@ export interface NavigateToOptions extends NavigationEntry {
*/
export function install(app: App) {
app.config.globalProperties.$navigateTo = $navigateTo
app.config.globalProperties.$navigateBack = $navigateBack
}

function resolveFrame(frame: NavigateToOptions['frame']): Frame {
function resolveFrame(frame: NavigationOptions['frame']): Frame {
if (!frame) {
return Frame.topmost()
}
Expand All @@ -53,7 +59,7 @@ function resolveFrame(frame: NavigateToOptions['frame']): Frame {
}

async function waitForFrame(
frame: NavigateToOptions['frame'],
frame: NavigationOptions['frame'],
retries: number = 5
) {
let _frame = resolveFrame(frame)
Expand All @@ -66,7 +72,7 @@ async function waitForFrame(

export async function $navigateTo(
target: Component,
options: NavigateToOptions
options?: NavigationOptions
): Promise<Page> {
options = Object.assign({}, options)
console.log('$navigateTo')
Expand All @@ -78,19 +84,45 @@ export async function $navigateTo(
throw new Error('Failed to resolve frame. Make sure your frame exists.')
}

const root = nodeOps.createRoot()
render(h(target, options.props), root)
const navigationApp = createApp(target, options.props)
const targetPage = (navigationApp.mount().$el.nativeView as unknown) as Page

const handler = (args: NavigatedData) => {
if (args.isBackNavigation) {
targetPage.off('navigatedFrom', handler as any)
navigationApp.unmount()
}
}
targetPage.on('navigatedFrom', handler)

const dispose = targetPage.disposeNativeView
targetPage.disposeNativeView = () => {
navigationApp.unmount()
dispose.call(targetPage)
}

frame.navigate({
...options,
create() {
return (root.el!.nativeView as unknown) as Page
},
create: () => targetPage,
})
return (root.el!.nativeView as unknown) as Page
return targetPage
} catch (e) {
console.log('[$navigateTo] Failed to navigate:\n\n')
console.log(e)
throw e
}
}

export async function $navigateBack(options: NavigationOptions) {
const frame = await waitForFrame(options?.frame)

if (!frame) {
throw new Error('Failed to resolve frame. Make sure your frame exists.')
}

if (!frame.canGoBack()) {
return
}

frame.goBack()
}

0 comments on commit 57f1556

Please sign in to comment.