TASK: #115114 - 小组件基类添加生命周期

This commit is contained in:
luojiahao 2022-10-17 20:52:24 +08:00
parent e5b420c4d3
commit bb5032f2ed
3 changed files with 117 additions and 49 deletions

View File

@ -35,6 +35,15 @@ class BatteryWidget extends GaiaWidget {
this.charge = this._battery.charging
this._battery.addEventListener('levelchange', this)
this._battery.addEventListener('chargingchange', this)
this.lifeCycle = 'initialized'
}
run = async () => {
if (this.lifeCycle == 'initializing') {
await this.init()
}
this.percent = this._battery.level * 100
this.charge = this._battery.charging
}
handleEvent(event: Event): void {

View File

@ -40,14 +40,20 @@ class ClockWidget extends GaiaWidget {
})
}
init() {}
clock!: StarClock
connectedCallback() {
this.clock = this.shadowRoot!.querySelector('star-clock')!
}
run = () => {
if (!this.clock) this.clock = this.shadowRoot!.querySelector('star-clock')!
this.clock.date = new Date()
}
openActivity = (_: any): any => {
return Promise.resolve()
}
refresh() {
this.clock.date = new Date()
}

View File

@ -45,6 +45,15 @@ export default class GaiaWidget extends StarBaseElement {
createTime: number = new Date().getTime()
container!: HTMLElement
activityRequestTimer: number | undefined
lifeCycle!:
| 'initializing'
| 'initializition-failed'
| 'initialized'
| 'preparing'
| 'running'
| 'preparation-failed'
// TODO: 补充activity失败原因
status!: 'requesting' | 'idle' | 'activity-shut-down' | 'err'
constructor({
url,
size,
@ -70,35 +79,64 @@ export default class GaiaWidget extends StarBaseElement {
this.attachShadow({mode: 'open'})
this.shadowRoot!.innerHTML = this.template
this.lifeCycle = 'initializing'
this.init()
this.dispatchReady()
}
init() {
// 补全小组件入口地址
if (!/^http(s)?:\/\//.test(this.url)) {
if (/^\//.test(this.url)) {
this.url = this.origin + this.url
return new Promise((res, rej) => {
if (this.lifeCycle == 'initializing') {
// 补全小组件入口地址
if (!/^http(s)?:\/\//.test(this.url)) {
if (/^\//.test(this.url)) {
this.url = this.origin + this.url
} else {
this.url = this.origin + '/' + this.url
}
}
if (this.url.endsWith('html')) {
this.container = this.shadowRoot!.querySelector(
'#gaia-widget-container-' + this.createTime
)!
this.container.addEventListener('touchstart', this)
this.container.addEventListener('touchmove', this)
this.container.addEventListener('touchend', this)
this.container.addEventListener('click', this)
// 需要在构造函数中被调用在connectedCallback中调用会导致移动元素时刷新的问题
this.querySources(this.url)
.then(this.parseHTML)
.then(() => {
this.lifeCycle = 'initialized'
res(undefined)
})
.catch((err) => {
this.lifeCycle = 'initializition-failed'
console.error(err)
rej(err)
})
} else {
this.lifeCycle = 'initialized'
res(undefined)
}
} else {
this.url = this.origin + '/' + this.url
res(undefined)
}
}
this.container = this.shadowRoot!.querySelector(
'#gaia-widget-container-' + this.createTime
)!
this.container.addEventListener('touchstart', this)
this.container.addEventListener('touchmove', this)
this.container.addEventListener('touchend', this)
this.container.addEventListener('click', this)
})
}
dispatchReady = () => {
// 需要在构造函数中被调用在connectedCallback中调用会导致移动元素时刷新的问题
run = () => {
this.lifeCycle = 'preparing'
// 防止安装、更新应用时,首次 Activity 请求因注册方 Service Worker 未完成安装而丢失
let n = 0
this.activityRequestTimer = window.setInterval(() => {
if (n++ > 4) clearInterval(this.activityRequestTimer)
this.openActivity({data: {type: 'ready'}})
if (n++ > 4) {
clearInterval(this.activityRequestTimer)
this.lifeCycle = 'preparation-failed'
}
this.openActivity({data: {type: 'ready'}}).then(
() => (this.lifeCycle = 'running')
)
}, 100)
}
@ -164,23 +202,35 @@ export default class GaiaWidget extends StarBaseElement {
}
openActivity = ({data}: any) => {
data.widgetTitle = this.widgetTitle
data.manifestName = this.manifestWidgetName
data.viewName = this.viewName
// TODO: 添加任务队列
this.status = 'requesting'
return new Promise((res, rej) => {
data.widgetTitle = this.widgetTitle
data.manifestName = this.manifestWidgetName
data.viewName = this.viewName
// @ts-ignore
const activity = new WebActivity(
`${this.appName}_${this.manifestWidgetName}`,
{data, type: ['widget']}
)
// @ts-ignore
const activity = new WebActivity(
`${this.appName}_${this.manifestWidgetName}`,
{data, type: ['widget']}
)
activity
.start()
.then((result: any) => {
if (this.activityRequestTimer) clearInterval(this.activityRequestTimer)
this.handleActivity(result)
})
.catch((err: any) => console.log(err))
activity
.start()
.then((result: any) => {
if (this.activityRequestTimer) {
clearInterval(this.activityRequestTimer)
}
this.handleActivity(result)
this.status = 'idle'
res(result)
})
.catch((err: any) => {
console.log(err)
this.status = 'err'
rej(err)
})
})
}
wrapEvent = (event: any) => {
@ -206,7 +256,7 @@ export default class GaiaWidget extends StarBaseElement {
/**
*
*/
querySources(url: string) {
querySources(url: string): Promise<string> {
return new Promise((res, rej) => {
// @ts-ignore
const xhr = new XMLHttpRequest({mozSystem: true})
@ -240,21 +290,24 @@ export default class GaiaWidget extends StarBaseElement {
* @param {DOMString} html
* @returns
*/
parseHTML = (html: string) => {
html = this.handleSource(this.filterDom(html))
parseHTML = (html?: string) => {
return new Promise((res, rej) => {
if (!html) return rej()
html = this.handleSource(this.filterDom(html))
const parse = new DOMParser()
const htmlDocument = parse.parseFromString(html, 'text/html')
const {head, body} = htmlDocument
// @ts-ignore
this.widgetTitle = head?.querySelector('title').innerHTML
if (this.widgetTitle === void 0) {
throw new Error('There is not a widget name yet!')
}
const parse = new DOMParser()
const htmlDocument = parse.parseFromString(html, 'text/html')
const {head, body} = htmlDocument
// @ts-ignore
this.widgetTitle = head?.querySelector('title').innerHTML
if (this.widgetTitle === void 0) {
throw rej(new Error('There is not a widget name yet!'))
}
this.appendStyle(htmlDocument)
this.container.innerHTML = body.innerHTML
return Promise.resolve()
this.appendStyle(htmlDocument)
this.container.innerHTML = body.innerHTML
res(undefined)
})
}
/**