提交 9fb36030 编写于 作者: fxy060608's avatar fxy060608

feat(app): add recovery

上级 b866985e
import { nextTick } from 'vue'
import {
ACTION_TYPE_ADD_EVENT,
ACTION_TYPE_CREATE,
......@@ -25,6 +26,7 @@ import {
setActionMinify,
} from '../../../src/constants'
import { decodeActions } from '../../../src/view/framework/dom/decodeActions'
describe('dom', () => {
const pageId = 1
const root = createPageNode(pageId, {
......@@ -198,6 +200,26 @@ describe('dom', () => {
expect(flag & EventModifierFlags.prevent).toBeTruthy()
expect(flag & EventModifierFlags.self).toBeFalsy()
})
test('restore', (done) => {
root.childNodes = []
root.clear()
const viewElem = createElement('view', { pageNode: root })
viewElem.setAttribute('id', 'view')
root.appendChild(viewElem)
viewElem.setAttribute('hidden', true)
const textNode = createTextNode('hello', { pageNode: root })
root.appendChild(textNode)
const clickFn1 = withModifiers(() => {}, [
'stop',
'prevent',
]) as unknown as UniEventListener
textNode.addEventListener('click', clickFn1, { capture: true })
nextTick(() => {
root.restore()
nextTick(done)
})
})
})
function expectActions(root: UniPageNode) {
......
......@@ -1858,9 +1858,6 @@ var serviceContext = (function (vue) {
return rootProxy.$page.id;
}
}
function getPageById(id) {
return getCurrentPages().find((page) => page.$page.id === id);
}
function getCurrentPage() {
const pages = getCurrentPages();
const len = pages.length;
......@@ -9667,11 +9664,85 @@ var serviceContext = (function (vue) {
});
}
let vueApp;
function getVueApp() {
return vueApp;
}
function initVueApp(appVm) {
const appContext = appVm.$.appContext;
vueApp = extend(appContext.app, {
mountPage(pageComponent, pageProps, pageContainer) {
const vnode = vue.createVNode(pageComponent, pageProps);
// store app context on the root VNode.
// this will be set on the root instance on initial mount.
vnode.appContext = appContext;
vnode.__page_container__ = pageContainer;
vue.render(vnode, pageContainer);
const publicThis = vnode.component.proxy;
publicThis.__page_container__ = pageContainer;
return publicThis;
},
unmountPage: (pageInstance) => {
const { __page_container__ } = pageInstance;
if (__page_container__) {
__page_container__.isUnmounted = true;
vue.render(null, __page_container__);
}
},
});
}
const pages = [];
function addCurrentPage(page) {
pages.push(page);
}
function getPageById(id) {
return pages.find((page) => page.$page.id === id);
}
function getAllPages() {
return pages;
}
function getCurrentPages$1() {
const curPages = [];
pages.forEach((page) => {
if (page.__isTabBar) {
if (page.$.__isActive) {
curPages.push(page);
}
}
else {
curPages.push(page);
}
});
return curPages;
}
function removeCurrentPage() {
const page = getCurrentPage();
if (!page) {
return;
}
removePage(page);
}
function removePage(curPage) {
const index = pages.findIndex((page) => page === curPage);
if (index === -1) {
return;
}
if (!curPage.$page.meta.isNVue) {
getVueApp().unmountPage(curPage);
}
pages.splice(index, 1);
if ((process.env.NODE_ENV !== 'production')) {
console.log(formatLog('removePage', curPage.$page));
}
}
function onNodeEvent(nodeId, evt, pageNode) {
pageNode.fireEvent(nodeId, evt);
}
function onVdSync(actions, pageId) {
// 从所有pages中获取
const page = getPageById(parseInt(pageId));
if (!page) {
if ((process.env.NODE_ENV !== 'production')) {
......@@ -9751,76 +9822,6 @@ var serviceContext = (function (vue) {
const VIEW_WEBVIEW_PATH = '_www/__uniappview.html';
const WEBVIEW_ID_PREFIX = 'webviewId';
let vueApp;
function getVueApp() {
return vueApp;
}
function initVueApp(appVm) {
const appContext = appVm.$.appContext;
vueApp = extend(appContext.app, {
mountPage(pageComponent, pageProps, pageContainer) {
const vnode = vue.createVNode(pageComponent, pageProps);
// store app context on the root VNode.
// this will be set on the root instance on initial mount.
vnode.appContext = appContext;
vnode.__page_container__ = pageContainer;
vue.render(vnode, pageContainer);
const publicThis = vnode.component.proxy;
publicThis.__page_container__ = pageContainer;
return publicThis;
},
unmountPage: (pageInstance) => {
const { __page_container__ } = pageInstance;
if (__page_container__) {
__page_container__.isUnmounted = true;
vue.render(null, __page_container__);
}
},
});
}
const pages = [];
function addCurrentPage(page) {
pages.push(page);
}
function getAllPages() {
return pages;
}
function getCurrentPages$1() {
const curPages = [];
pages.forEach((page) => {
if (page.__isTabBar) {
if (page.$.__isActive) {
curPages.push(page);
}
}
else {
curPages.push(page);
}
});
return curPages;
}
function removeCurrentPage() {
const page = getCurrentPage();
if (!page) {
return;
}
removePage(page);
}
function removePage(curPage) {
const index = pages.findIndex((page) => page === curPage);
if (index === -1) {
return;
}
if (!curPage.$page.meta.isNVue) {
getVueApp().unmountPage(curPage);
}
pages.splice(index, 1);
if ((process.env.NODE_ENV !== 'production')) {
console.log(formatLog('removePage', curPage.$page));
}
}
function initNVue(webviewStyle, routeMeta, path) {
if (path && routeMeta.isNVue) {
webviewStyle.uniNView = {
......@@ -10115,6 +10116,35 @@ var serviceContext = (function (vue) {
});
}
function onWebviewRecovery(webview) {
if (webview.nvue) {
return;
}
const webviewId = webview.id;
const { subscribe, unsubscribe } = UniServiceJSBridge;
const onWebviewRecoveryReady = (_, pageId) => {
if (webviewId !== pageId) {
return;
}
unsubscribe(ON_WEBVIEW_READY, onWebviewRecoveryReady);
if ((process.env.NODE_ENV !== 'production')) {
console.log(formatLog(`Recovery`, webviewId, 'ready'));
}
const page = getPageById(parseInt(pageId));
if (page) {
const pageNode = page.__page_container__;
pageNode.restore();
}
};
// @ts-expect-error
webview.addEventListener('recovery', () => {
if ((process.env.NODE_ENV !== 'production')) {
console.log(formatLog('Recovery', webview.id));
}
subscribe(ON_WEBVIEW_READY, onWebviewRecoveryReady);
});
}
function onWebviewResize(webview) {
const { emit } = UniServiceJSBridge;
const onResize = function ({ width, height, }) {
......@@ -10152,9 +10182,8 @@ var serviceContext = (function (vue) {
});
onWebviewClose(webview);
onWebviewResize(webview);
// TODO
if (plus.os.name === 'iOS') {
// !(webview as any).nvue && onWebviewRecovery(webview, routeOptions)
onWebviewRecovery(webview);
onWebviewPopGesture(webview);
}
}
......@@ -10563,11 +10592,19 @@ var serviceContext = (function (vue) {
vue.queuePostFlushCb(this._update);
}
restore() {
this.clear();
this.push(this.createAction);
if (this.scrollAction) {
this.push(this.scrollAction);
}
// TODO restore children
const restoreNode = (node) => {
this.onCreate(node, node.nodeName);
this.onInsertBefore(node.parentNode, node, null);
node.childNodes.forEach((childNode) => {
restoreNode(childNode);
});
};
this.childNodes.forEach((childNode) => restoreNode(childNode));
this.push(this.createdAction);
}
setup() {
......@@ -10578,7 +10615,6 @@ var serviceContext = (function (vue) {
if ((process.env.NODE_ENV !== 'production')) {
console.log(formatLog('PageNode', 'update', updateActions.length, _createActionMap.size));
}
_createActionMap.clear();
// 首次
if (!this._created) {
this._created = true;
......@@ -10589,9 +10625,13 @@ var serviceContext = (function (vue) {
updateActions.unshift([ACTION_TYPE_DICT, dicts]);
}
this.send(updateActions);
dicts.length = 0;
updateActions.length = 0;
}
this.clear();
}
clear() {
this.dicts.length = 0;
this.updateActions.length = 0;
this._createActionMap.clear();
}
send(action) {
UniServiceJSBridge.publishHandler(VD_SYNC, action, this.pageId);
......
import { getPageById } from '@dcloudio/uni-core'
import { getPageById } from '../../page/getCurrentPages'
export function onWebviewInserted(_: unknown, pageId: string) {
const page = getPageById(parseInt(pageId))
......
......@@ -30,8 +30,6 @@ import {
ACTION_TYPE_ADD_WXS_EVENT,
} from '@dcloudio/uni-shared'
import { getPageById } from '@dcloudio/uni-core'
import {
ACTION_MINIFY,
ACTION_TYPE_DICT,
......@@ -40,6 +38,7 @@ import {
Value,
VD_SYNC,
} from '../../../constants'
import { getPageById } from '../page/getCurrentPages'
export default class UniPageNode extends UniNode implements IUniPageNode {
pageId: number
......@@ -225,11 +224,19 @@ export default class UniPageNode extends UniNode implements IUniPageNode {
queuePostFlushCb(this._update)
}
restore() {
this.clear()
this.push(this.createAction)
if (this.scrollAction) {
this.push(this.scrollAction)
}
// TODO restore children
const restoreNode = (node: UniNode) => {
this.onCreate(node, node.nodeName)
this.onInsertBefore(node.parentNode!, node, null)
node.childNodes.forEach((childNode) => {
restoreNode(childNode)
})
}
this.childNodes.forEach((childNode) => restoreNode(childNode))
this.push(this.createdAction)
}
setup() {
......@@ -247,7 +254,6 @@ export default class UniPageNode extends UniNode implements IUniPageNode {
)
)
}
_createActionMap.clear()
// 首次
if (!this._created) {
this._created = true
......@@ -258,9 +264,13 @@ export default class UniPageNode extends UniNode implements IUniPageNode {
updateActions.unshift([ACTION_TYPE_DICT, dicts])
}
this.send(updateActions)
dicts.length = 0
updateActions.length = 0
}
this.clear()
}
clear() {
this.dicts.length = 0
this.updateActions.length = 0
this._createActionMap.clear()
}
send(action: (PageAction | DictAction)[]) {
UniServiceJSBridge.publishHandler(VD_SYNC, action, this.pageId)
......
import { getPageById } from '@dcloudio/uni-core'
import { ACTION_TYPE_EVENT, formatLog } from '@dcloudio/uni-shared'
import { getPageById } from '../page/getCurrentPages'
import { EventAction, onNodeEvent } from './onNodeEvent'
import UniPageNode from './Page'
export function onVdSync(actions: EventAction[], pageId: string) {
// 从所有pages中获取
const page = getPageById(parseInt(pageId))
if (!page) {
if (__DEV__) {
......
......@@ -9,6 +9,10 @@ export function addCurrentPage(page: ComponentPublicInstance) {
pages.push(page)
}
export function getPageById(id: number) {
return pages.find((page) => page.$page.id === id)
}
export function getAllPages() {
return pages
}
......
......@@ -9,6 +9,7 @@ import {
import { setPullDownRefreshWebview } from '../../../../utils'
import { onWebviewClose } from './close'
import { onWebviewPopGesture } from './popGesture'
import { onWebviewRecovery } from './recovery'
import { onWebviewResize } from './resize'
const WEBVIEW_LISTENERS = {
......@@ -35,9 +36,8 @@ export function initWebviewEvent(webview: PlusWebviewWebviewObject) {
onWebviewClose(webview)
onWebviewResize(webview)
// TODO
if (plus.os.name === 'iOS') {
// !(webview as any).nvue && onWebviewRecovery(webview, routeOptions)
onWebviewRecovery(webview)
onWebviewPopGesture(webview)
}
}
import { formatLog } from '@dcloudio/uni-shared'
import { ON_WEBVIEW_READY } from '../../../../../constants'
import UniPageNode from '../../../dom/Page'
import { getPageById } from '../../../page/getCurrentPages'
export function onWebviewRecovery(webview: PlusWebviewWebviewObject) {
if ((webview as any).nvue) {
return
}
const webviewId = webview.id
const { subscribe, unsubscribe } = UniServiceJSBridge
const onWebviewRecoveryReady = (_: unknown, pageId: string) => {
if (webviewId !== pageId) {
return
}
unsubscribe(ON_WEBVIEW_READY, onWebviewRecoveryReady)
if (__DEV__) {
console.log(formatLog(`Recovery`, webviewId, 'ready'))
}
const page = getPageById(parseInt(pageId))
if (page) {
const pageNode = (page as any).__page_container__ as UniPageNode
pageNode.restore()
}
}
// @ts-expect-error
webview.addEventListener('recovery', () => {
if (__DEV__) {
console.log(formatLog('Recovery', webview.id))
}
subscribe(ON_WEBVIEW_READY, onWebviewRecoveryReady)
})
}
......@@ -21,7 +21,7 @@ export function getPageIdByVm(vm: ComponentPublicInstance) {
}
}
export function getPageById(id: number) {
function getPageById(id: number) {
return getCurrentPages().find((page) => page.$page.id === id)
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册