diff --git a/packages/uni-app-plus/dist/uni-app-service.es.js b/packages/uni-app-plus/dist/uni-app-service.es.js index cb0ab3e8b013956eb9934eeff1fa23539585e040..462ba9b03bd948d158f38de5c49dc28ecb779260 100644 --- a/packages/uni-app-plus/dist/uni-app-service.es.js +++ b/packages/uni-app-plus/dist/uni-app-service.es.js @@ -4417,8 +4417,11 @@ var serviceContext = (function (vue) { type: Number, }, }, createAnimationProtocol(ANIMATION_OUT)); + const RedirectToProtocol = BaseRouteProtocol; const NavigateToOptions = /*#__PURE__*/ createRouteOptions(API_NAVIGATE_TO); + const RedirectToOptions = + /*#__PURE__*/ createRouteOptions(API_REDIRECT_TO); const NavigateBackOptions = { formatArgs: { delta(value, params) { @@ -8986,6 +8989,67 @@ var serviceContext = (function (vue) { return new InteractiveAd(options); }, CreateInteractiveAdProtocol, CreateInteractiveAdOptions)); + const pages = []; + function addCurrentPage(page) { + pages.push(page); + } + function getCurrentPages$1() { + const curPages = []; + pages.forEach((page) => { + if (page.__isTabBar) { + if (page.$.__isActive) { + curPages.push(page); + } + } + else { + curPages.push(page); + } + }); + return curPages; + } + function removePage(curPage) { + const index = pages.findIndex((page) => page === curPage); + if (index === -1) { + return; + } + if (!curPage.$page.meta.isNVue) { + curPage.$.appContext.app.unmount(); + } + pages.splice(index, 1); + if ((process.env.NODE_ENV !== 'production')) { + console.log(formatLog('removePage', curPage.$page)); + } + } + + let lastStatusBarStyle; + let oldSetStatusBarStyle = plus.navigator.setStatusBarStyle; + function newSetStatusBarStyle(style) { + lastStatusBarStyle = style; + oldSetStatusBarStyle(style); + } + plus.navigator.setStatusBarStyle = newSetStatusBarStyle; + function setStatusBarStyle(statusBarStyle) { + if (!statusBarStyle) { + const pages = getCurrentPages(); + if (!pages.length) { + return; + } + statusBarStyle = pages[pages.length - 1].$page + .statusBarStyle; + if (!statusBarStyle || statusBarStyle === lastStatusBarStyle) { + return; + } + } + if (statusBarStyle === lastStatusBarStyle) { + return; + } + if ((process.env.NODE_ENV !== 'production')) { + console.log(formatLog('setStatusBarStyle', statusBarStyle)); + } + lastStatusBarStyle = statusBarStyle; + plus.navigator.setStatusBarStyle(statusBarStyle); + } + let pendingNavigator = false; function setPendingNavigator(path, callback, msg) { pendingNavigator = { @@ -8997,7 +9061,7 @@ var serviceContext = (function (vue) { console.log(formatLog('setPendingNavigator', path, msg)); } } - function navigate(path, callback, isAppLaunch) { + function navigate(path, callback, isAppLaunch = false) { if (!isAppLaunch && pendingNavigator) { return console.error(`Waiting to navigate to: ${pendingNavigator.path}, do not operate continuously: ${path}.`); } @@ -9119,6 +9183,91 @@ var serviceContext = (function (vue) { }); } + const navigateBack = defineAsyncApi(API_NAVIGATE_BACK, (args, { resolve, reject }) => { + const page = getCurrentPage(); + if (!page) { + return reject(`getCurrentPages is empty`); + } + if (invokeHook(page, 'onBackPress', { + from: args.from, + })) { + return resolve(); + } + uni.hideToast(); + uni.hideLoading(); + if (page.$page.meta.isQuit) { + quit(); + } + else if (page.$page.id === 1 && __uniConfig.realEntryPagePath) { + // condition + __uniConfig.entryPagePath = __uniConfig.realEntryPagePath; + delete __uniConfig.realEntryPagePath; + uni.reLaunch({ + url: '/' + __uniConfig.entryPagePath, + }); + } + else { + const { delta, animationType, animationDuration } = args; + back(delta, animationType, animationDuration); + } + return resolve(); + }, NavigateBackProtocol, NavigateBackOptions); + let firstBackTime = 0; + function quit() { + initI18nAppMsgsOnce(); + if (!firstBackTime) { + firstBackTime = Date.now(); + plus.nativeUI.toast(useI18n().t('uni.app.quit')); + setTimeout(() => { + firstBackTime = 0; + }, 2000); + } + else if (Date.now() - firstBackTime < 2000) { + plus.runtime.quit(); + } + } + function back(delta, animationType, animationDuration) { + const pages = getCurrentPages(); + const len = pages.length; + const currentPage = pages[len - 1]; + if (delta > 1) { + // 中间页隐藏 + pages + .slice(len - delta, len - 1) + .reverse() + .forEach((deltaPage) => { + closeWebview(plus.webview.getWebviewById(deltaPage.$page.id + ''), 'none', 0); + }); + } + const backPage = function (webview) { + if (animationType) { + closeWebview(webview, animationType, animationDuration || ANI_DURATION); + } + else { + if (currentPage.$page.openType === 'redirectTo') { + // 如果是 redirectTo 跳转的,需要指定 back 动画 + closeWebview(webview, ANI_CLOSE, ANI_DURATION); + } + else { + closeWebview(webview, 'auto'); + } + } + pages + .slice(len - delta, len) + .forEach((page) => removePage(page)); + setStatusBarStyle(); + // 前一个页面触发 onShow + invokeHook('onShow'); + }; + const webview = plus.webview.getWebviewById(currentPage.$page.id + ''); + if (!currentPage.__uniapp_webview) { + return backPage(webview); + } + backWebview(webview, () => { + backPage(webview); + }); + } + class UniPageNode extends UniNode { constructor(pageId, options, setup = false) { super(NODE_TYPE_PAGE, '#page', null); @@ -9333,38 +9482,6 @@ var serviceContext = (function (vue) { return new UniPageNode(pageId, pageOptions, setup); } - const pages = []; - function addCurrentPage(page) { - pages.push(page); - } - function getCurrentPages$1() { - const curPages = []; - pages.forEach((page) => { - if (page.__isTabBar) { - if (page.$.__isActive) { - curPages.push(page); - } - } - else { - curPages.push(page); - } - }); - return curPages; - } - function removePage(curPage) { - const index = pages.findIndex((page) => page === curPage); - if (index === -1) { - return; - } - if (!curPage.$page.meta.isNVue) { - curPage.$.appContext.app.unmount(); - } - pages.splice(index, 1); - if ((process.env.NODE_ENV !== 'production')) { - console.log(formatLog('removePage', curPage.$page)); - } - } - function setupPage(component) { const oldSetup = component.setup; component.inheritAttrs = false; // 禁止继承 __pageId 等属性,避免告警 @@ -9554,117 +9671,56 @@ var serviceContext = (function (vue) { ]; } - let lastStatusBarStyle; - let oldSetStatusBarStyle = plus.navigator.setStatusBarStyle; - function newSetStatusBarStyle(style) { - lastStatusBarStyle = style; - oldSetStatusBarStyle(style); - } - plus.navigator.setStatusBarStyle = newSetStatusBarStyle; - function setStatusBarStyle(statusBarStyle) { - if (!statusBarStyle) { - const pages = getCurrentPages(); - if (!pages.length) { - return; - } - statusBarStyle = pages[pages.length - 1].$page - .statusBarStyle; - if (!statusBarStyle || statusBarStyle === lastStatusBarStyle) { - return; - } - } - if (statusBarStyle === lastStatusBarStyle) { - return; - } - if ((process.env.NODE_ENV !== 'production')) { - console.log(formatLog('setStatusBarStyle', statusBarStyle)); - } - lastStatusBarStyle = statusBarStyle; - plus.navigator.setStatusBarStyle(statusBarStyle); - } - - const navigateBack = defineAsyncApi(API_NAVIGATE_BACK, (args, { resolve, reject }) => { - const page = getCurrentPage(); - if (!page) { - return reject(`getCurrentPages is empty`); - } - if (invokeHook(page, 'onBackPress', { - from: args.from, - })) { - return resolve(); - } - uni.hideToast(); - uni.hideLoading(); - if (page.$page.meta.isQuit) { - quit(); - } - else if (page.$page.id === 1 && __uniConfig.realEntryPagePath) { - // condition - __uniConfig.entryPagePath = __uniConfig.realEntryPagePath; - delete __uniConfig.realEntryPagePath; - uni.reLaunch({ - url: '/' + __uniConfig.entryPagePath, - }); - } - else { - const { delta, animationType, animationDuration } = args; - back(delta, animationType, animationDuration); - } - return resolve(); - }, NavigateBackProtocol, NavigateBackOptions); - let firstBackTime = 0; - function quit() { - initI18nAppMsgsOnce(); - if (!firstBackTime) { - firstBackTime = Date.now(); - plus.nativeUI.toast(useI18n().t('uni.app.quit')); - setTimeout(() => { - firstBackTime = 0; - }, 2000); - } - else if (Date.now() - firstBackTime < 2000) { - plus.runtime.quit(); - } - } - function back(delta, animationType, animationDuration) { - const pages = getCurrentPages(); - const len = pages.length; - const currentPage = pages[len - 1]; - if (delta > 1) { - // 中间页隐藏 - pages - .slice(len - delta, len - 1) - .reverse() - .forEach((deltaPage) => { - closeWebview(plus.webview.getWebviewById(deltaPage.$page.id + ''), 'none', 0); - }); - } - const backPage = function (webview) { - if (animationType) { - closeWebview(webview, animationType, animationDuration || ANI_DURATION); - } - else { - if (currentPage.$page.openType === 'redirectTo') { - // 如果是 redirectTo 跳转的,需要制定 back 动画 - closeWebview(webview, ANI_CLOSE, ANI_DURATION); - } - else { - closeWebview(webview, 'auto'); + const redirectTo = defineAsyncApi(API_REDIRECT_TO, ({ url }, { resolve, reject }) => { + const { path, query } = parseUrl(url); + navigate(path, () => { + _redirectTo({ + url, + path, + query, + }) + .then(resolve) + .catch(reject); + }); + }, RedirectToProtocol, RedirectToOptions); + function _redirectTo({ url, path, query, }) { + // TODO exists + // if (exists === 'back') { + // const existsPageIndex = findExistsPageIndex(url) + // if (existsPageIndex !== -1) { + // const delta = len - existsPageIndex + // if (delta > 0) { + // navigateBack({ + // delta, + // }) + // invoke(callbackId, { + // errMsg: 'redirectTo:ok', + // }) + // return + // } + // } + // } + const lastPage = getCurrentPage(); + lastPage && removePage(lastPage); + return new Promise((resolve) => { + showWebview(registerPage({ + url, + path, + query, + openType: 'redirectTo', + }), 'none', 0, () => { + if (lastPage) { + const webview = lastPage + .$getAppWebview(); + // TODO preload + // if (webview.__preload__) { + // removePreloadWebview(webview) + // } + webview.close('none'); } - } - pages - .slice(len - delta, len) - .forEach((page) => removePage(page)); + resolve(undefined); + }); setStatusBarStyle(); - // 前一个页面触发 onShow - invokeHook('onShow'); - }; - const webview = plus.webview.getWebviewById(currentPage.$page.id + ''); - if (!currentPage.__uniapp_webview) { - return backPage(webview); - } - backWebview(webview, () => { - backPage(webview); }); } @@ -9795,8 +9851,9 @@ var serviceContext = (function (vue) { createFullScreenVideoAd: createFullScreenVideoAd, createInterstitialAd: createInterstitialAd, createInteractiveAd: createInteractiveAd, + navigateBack: navigateBack, navigateTo: navigateTo, - navigateBack: navigateBack + redirectTo: redirectTo }); let invokeViewMethodId = 0; diff --git a/packages/uni-app-plus/src/service/api/index.ts b/packages/uni-app-plus/src/service/api/index.ts index c1dcd2e4c36b93c213df9d2d014f4b4d1eaf2227..9e33d803dedb1efd61f35c293e4572dba730b054 100644 --- a/packages/uni-app-plus/src/service/api/index.ts +++ b/packages/uni-app-plus/src/service/api/index.ts @@ -52,8 +52,9 @@ export * from './ad/fullScreenVideoAd' export * from './ad/interstitialAd' export * from './ad/interactiveAd' -export * from './route/navigateTo' export * from './route/navigateBack' +export * from './route/navigateTo' +export * from './route/redirectTo' export { upx2px, diff --git a/packages/uni-app-plus/src/service/api/route/navigateBack.ts b/packages/uni-app-plus/src/service/api/route/navigateBack.ts index 10429558820afeaf5a938151cf168cbc5310d141..9e610d221486acfbb6ce51194fb7d56bba858697 100644 --- a/packages/uni-app-plus/src/service/api/route/navigateBack.ts +++ b/packages/uni-app-plus/src/service/api/route/navigateBack.ts @@ -94,7 +94,7 @@ function back( closeWebview(webview, animationType, animationDuration || ANI_DURATION) } else { if (currentPage.$page.openType === 'redirectTo') { - // 如果是 redirectTo 跳转的,需要制定 back 动画 + // 如果是 redirectTo 跳转的,需要指定 back 动画 closeWebview(webview, ANI_CLOSE, ANI_DURATION) } else { closeWebview(webview, 'auto') diff --git a/packages/uni-app-plus/src/service/api/route/redirectTo.ts b/packages/uni-app-plus/src/service/api/route/redirectTo.ts new file mode 100644 index 0000000000000000000000000000000000000000..f57f5eeb76ef1c40ba593c0e2f2d17566208ba9f --- /dev/null +++ b/packages/uni-app-plus/src/service/api/route/redirectTo.ts @@ -0,0 +1,91 @@ +import { + API_REDIRECT_TO, + API_TYPE_REDIRECT_TO, + defineAsyncApi, + RedirectToOptions, + RedirectToProtocol, +} from '@dcloudio/uni-api' +import { parseUrl } from '@dcloudio/uni-shared' +import { getCurrentPage } from '@dcloudio/uni-core' +import { removePage } from '../../framework/page/getCurrentPages' +import { registerPage } from '../../framework/page' +import { navigate } from './utils' +import { showWebview } from './webview' +import { setStatusBarStyle } from '../../statusBar' +import { ComponentPublicInstance } from 'vue' + +export const redirectTo = defineAsyncApi( + API_REDIRECT_TO, + ({ url }, { resolve, reject }) => { + const { path, query } = parseUrl(url) + navigate(path, () => { + _redirectTo({ + url, + path, + query, + }) + .then(resolve) + .catch(reject) + }) + }, + RedirectToProtocol, + RedirectToOptions +) + +interface RedirectToOptions { + url: string + path: string + query: Record +} + +function _redirectTo({ + url, + path, + query, +}: RedirectToOptions): Promise { + // TODO exists + // if (exists === 'back') { + // const existsPageIndex = findExistsPageIndex(url) + // if (existsPageIndex !== -1) { + // const delta = len - existsPageIndex + // if (delta > 0) { + // navigateBack({ + // delta, + // }) + // invoke(callbackId, { + // errMsg: 'redirectTo:ok', + // }) + // return + // } + // } + // } + + const lastPage = getCurrentPage() + lastPage && removePage(lastPage) + + return new Promise((resolve) => { + showWebview( + registerPage({ + url, + path, + query, + openType: 'redirectTo', + }), + 'none', + 0, + () => { + if (lastPage) { + const webview = (lastPage as ComponentPublicInstance) + .$getAppWebview!() + // TODO preload + // if (webview.__preload__) { + // removePreloadWebview(webview) + // } + webview.close('none') + } + resolve(undefined) + } + ) + setStatusBarStyle() + }) +} diff --git a/packages/uni-app-plus/src/service/api/route/utils.ts b/packages/uni-app-plus/src/service/api/route/utils.ts index 526f9d39ab201ba7c6bcaa71f7b65c37ded40f7b..24699f8c30347505b995d7d1b8de8ca646ceaeda 100644 --- a/packages/uni-app-plus/src/service/api/route/utils.ts +++ b/packages/uni-app-plus/src/service/api/route/utils.ts @@ -28,7 +28,7 @@ function setPendingNavigator(path: string, callback: Function, msg: string) { export function navigate( path: string, callback: Function, - isAppLaunch: boolean + isAppLaunch: boolean = false ) { if (!isAppLaunch && pendingNavigator) { return console.error( diff --git a/packages/uni-app-plus/src/service/framework/page/getCurrentPages.ts b/packages/uni-app-plus/src/service/framework/page/getCurrentPages.ts index f91327459e24a3877f57946252c2e6e0fb11b53d..4a2af818fd0f2559ef4e5f372f4ce78b0a93352f 100644 --- a/packages/uni-app-plus/src/service/framework/page/getCurrentPages.ts +++ b/packages/uni-app-plus/src/service/framework/page/getCurrentPages.ts @@ -23,16 +23,22 @@ export function getCurrentPages() { } export function removeCurrentPage() { - removePage(getCurrentPage() as ComponentPublicInstance) + const page = getCurrentPage() as ComponentPublicInstance + if (!page) { + return + } + removePage(page) } -export function removePage(curPage: ComponentPublicInstance) { +export function removePage( + curPage: ComponentPublicInstance | Page.PageInstance +) { const index = pages.findIndex((page) => page === curPage) if (index === -1) { return } if (!curPage.$page.meta.isNVue) { - curPage.$.appContext.app.unmount() + ;(curPage as ComponentPublicInstance).$.appContext.app.unmount() } pages.splice(index, 1) if (__DEV__) {