2021-04-15 11:35:58 +08:00
|
|
|
import { DoricSuperNode, DoricViewNode, DVModel } from "./DoricViewNode";
|
2019-12-28 14:25:03 +08:00
|
|
|
|
|
|
|
export class DoricRefreshableNode extends DoricSuperNode {
|
|
|
|
|
2021-04-15 11:35:58 +08:00
|
|
|
headerViewId = ""
|
|
|
|
headerNode?: DoricViewNode
|
2019-12-28 14:25:03 +08:00
|
|
|
|
2021-04-15 11:35:58 +08:00
|
|
|
contentViewId = ""
|
|
|
|
contentNode?: DoricViewNode
|
|
|
|
|
|
|
|
onRefreshCallback?: Function
|
|
|
|
|
|
|
|
headerContainer?: HTMLDivElement
|
|
|
|
|
|
|
|
contentContainer?: HTMLDivElement
|
2021-04-15 18:34:06 +08:00
|
|
|
refreshable = true
|
2019-12-28 14:25:03 +08:00
|
|
|
build() {
|
|
|
|
const ret = document.createElement('div')
|
2021-04-15 11:35:58 +08:00
|
|
|
ret.style.overflow = "hidden"
|
2021-04-14 17:46:58 +08:00
|
|
|
const header = document.createElement('div')
|
|
|
|
const content = document.createElement('div')
|
|
|
|
header.style.width = "100%"
|
2021-04-15 15:51:24 +08:00
|
|
|
header.style.height = "100%"
|
|
|
|
header.style.display = "flex"
|
|
|
|
header.style.alignItems = "flex-end"
|
|
|
|
header.style.justifyContent = "center"
|
2021-04-14 17:46:58 +08:00
|
|
|
content.style.width = "100%"
|
|
|
|
content.style.height = "100%"
|
|
|
|
ret.appendChild(header)
|
|
|
|
ret.appendChild(content)
|
2021-04-15 11:35:58 +08:00
|
|
|
let touchStart = 0
|
|
|
|
ret.ontouchstart = (ev) => {
|
2021-04-15 18:34:06 +08:00
|
|
|
if (!this.refreshable) {
|
|
|
|
return
|
|
|
|
}
|
2021-04-15 11:35:58 +08:00
|
|
|
touchStart = ev.touches[0].pageY
|
|
|
|
}
|
|
|
|
ret.ontouchmove = (ev) => {
|
2021-04-15 18:34:06 +08:00
|
|
|
if (!this.refreshable) {
|
|
|
|
return
|
|
|
|
}
|
2021-04-16 13:20:03 +08:00
|
|
|
const offset = (ev.touches[0].pageY - touchStart) * 0.68
|
|
|
|
ret.scrollTop = Math.max(0, header.offsetHeight - offset)
|
|
|
|
this.headerNode?.callJSResponse("setPullingDistance", offset)
|
2021-04-15 18:34:06 +08:00
|
|
|
}
|
|
|
|
const touchend = () => {
|
|
|
|
if (!this.refreshable) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if (header.offsetHeight - ret.scrollTop >= (this.headerNode?.getWidth() || 0)) {
|
|
|
|
this.setRefreshing(true)
|
|
|
|
this.onRefreshCallback?.()
|
|
|
|
} else {
|
|
|
|
// To idel
|
|
|
|
ret.scrollTo({
|
|
|
|
top: header.offsetHeight,
|
|
|
|
behavior: "smooth"
|
|
|
|
})
|
|
|
|
}
|
2021-04-15 11:35:58 +08:00
|
|
|
}
|
|
|
|
ret.ontouchcancel = () => {
|
2021-04-15 18:34:06 +08:00
|
|
|
touchend()
|
2021-04-15 11:35:58 +08:00
|
|
|
}
|
|
|
|
ret.ontouchend = () => {
|
2021-04-15 18:34:06 +08:00
|
|
|
touchend()
|
2021-04-15 11:35:58 +08:00
|
|
|
}
|
|
|
|
window.requestAnimationFrame(() => {
|
|
|
|
ret.scrollTop = header.offsetHeight
|
2021-04-14 17:46:58 +08:00
|
|
|
})
|
2021-04-15 11:35:58 +08:00
|
|
|
this.headerContainer = header
|
|
|
|
this.contentContainer = content
|
2019-12-28 14:25:03 +08:00
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
2021-04-15 11:35:58 +08:00
|
|
|
blendProps(v: HTMLElement, propName: string, prop: any) {
|
|
|
|
if (propName === 'content') {
|
|
|
|
this.contentViewId = prop
|
|
|
|
} else if (propName === 'header') {
|
|
|
|
this.headerViewId = prop
|
|
|
|
} else if (propName === 'onRefresh') {
|
|
|
|
this.onRefreshCallback = () => {
|
|
|
|
this.callJSResponse(prop)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
super.blendProps(v, propName, prop)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
blendSubNode(model: DVModel) {
|
|
|
|
this.getSubNodeById(model.id)?.blend(model.props)
|
|
|
|
}
|
|
|
|
|
|
|
|
getSubNodeById(viewId: string) {
|
|
|
|
if (viewId === this.headerViewId) {
|
|
|
|
return this.headerNode
|
|
|
|
} else if (viewId === this.contentViewId) {
|
|
|
|
return this.contentNode
|
|
|
|
}
|
|
|
|
return undefined
|
|
|
|
}
|
|
|
|
|
|
|
|
onBlending() {
|
|
|
|
super.onBlending()
|
|
|
|
{
|
|
|
|
const headerModel = this.getSubModel(this.headerViewId)
|
|
|
|
if (headerModel) {
|
|
|
|
if (this.headerNode) {
|
|
|
|
if (this.headerNode.viewId !== this.headerViewId) {
|
|
|
|
if (this.reusable && this.headerNode.viewType === headerModel.type) {
|
|
|
|
this.headerNode.viewId = headerModel.id
|
|
|
|
this.headerNode.blend(headerModel.props)
|
|
|
|
} else {
|
|
|
|
this.headerContainer?.removeChild(this.headerNode.view)
|
|
|
|
const headerNode = DoricViewNode.create(this.context, headerModel.type)
|
|
|
|
if (headerNode) {
|
|
|
|
headerNode.viewId = headerModel.id
|
|
|
|
headerNode.init(this)
|
|
|
|
headerNode.blend(headerModel.props)
|
|
|
|
this.headerContainer?.appendChild(headerNode.view)
|
|
|
|
this.headerNode = headerNode
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
const headerNode = DoricViewNode.create(this.context, headerModel.type)
|
|
|
|
if (headerNode) {
|
|
|
|
headerNode.viewId = headerModel.id
|
|
|
|
headerNode.init(this)
|
|
|
|
headerNode.blend(headerModel.props)
|
|
|
|
this.headerContainer?.appendChild(headerNode.view)
|
|
|
|
this.headerNode = headerNode
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
const contentModel = this.getSubModel(this.contentViewId)
|
|
|
|
if (contentModel) {
|
|
|
|
if (this.contentNode) {
|
|
|
|
if (this.contentNode.viewId !== this.contentViewId) {
|
|
|
|
if (this.reusable && this.contentNode.viewType === contentModel.type) {
|
|
|
|
this.contentNode.viewId = contentModel.id
|
|
|
|
this.contentNode.blend(contentModel.props)
|
|
|
|
} else {
|
|
|
|
this.contentContainer?.removeChild(this.contentNode.view)
|
|
|
|
const contentNode = DoricViewNode.create(this.context, contentModel.type)
|
|
|
|
if (contentNode) {
|
|
|
|
contentNode.viewId = contentModel.id
|
|
|
|
contentNode.init(this)
|
|
|
|
contentNode.blend(contentModel.props)
|
|
|
|
this.contentContainer?.appendChild(contentNode.view)
|
|
|
|
this.contentNode = contentNode
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
const contentNode = DoricViewNode.create(this.context, contentModel.type)
|
|
|
|
if (contentNode) {
|
|
|
|
contentNode.viewId = contentModel.id
|
|
|
|
contentNode.init(this)
|
|
|
|
contentNode.blend(contentModel.props)
|
|
|
|
this.contentContainer?.appendChild(contentNode.view)
|
|
|
|
this.contentNode = contentNode
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
onBlended() {
|
|
|
|
super.onBlended()
|
|
|
|
}
|
|
|
|
|
2021-04-15 15:51:24 +08:00
|
|
|
setRefreshing(v: boolean) {
|
|
|
|
if (!this.headerContainer || !this.headerNode) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if (v) {
|
|
|
|
this.view.scrollTo({
|
|
|
|
top: this.headerContainer.offsetHeight - this.headerNode.getHeight(),
|
|
|
|
behavior: "smooth"
|
|
|
|
})
|
2021-04-16 13:20:03 +08:00
|
|
|
this.headerNode.callJSResponse("startAnimation")
|
2021-04-15 15:51:24 +08:00
|
|
|
} else {
|
|
|
|
this.view.scrollTo({
|
|
|
|
top: this.headerContainer?.offsetHeight,
|
|
|
|
behavior: "smooth"
|
|
|
|
})
|
2021-04-16 13:20:03 +08:00
|
|
|
this.headerNode.callJSResponse("stopAnimation")
|
2021-04-15 15:51:24 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
setRefreshable(v: boolean) {
|
2021-04-15 18:34:06 +08:00
|
|
|
this.refreshable = v
|
|
|
|
if (!v) {
|
|
|
|
this.setRefreshing(false)
|
|
|
|
}
|
2021-04-15 15:51:24 +08:00
|
|
|
}
|
2019-12-28 14:25:03 +08:00
|
|
|
}
|