gengxin
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
function finiteNumber(value, fallback = 0) {
|
||||
const parsed = Number(value)
|
||||
return Number.isFinite(parsed) ? parsed : fallback
|
||||
}
|
||||
|
||||
function clamp(value, minimum, maximum) {
|
||||
return Math.min(maximum, Math.max(minimum, value))
|
||||
}
|
||||
|
||||
/**
|
||||
* 首页使用自定义导航栏,横屏时既要避开左右刘海与底部 Home
|
||||
* Indicator,也要为微信右上角胶囊留下真实空间。CSS 的 env()
|
||||
* 在部分微信横屏机型上只会返回系统安全区,不包含胶囊,因此这里
|
||||
* 以运行时尺寸为准,CSS env() 只作为脚本尚未执行时的兜底。
|
||||
*/
|
||||
function getHomeLayoutMetrics(windowInfo = {}, menuRect = {}) {
|
||||
const windowWidth = Math.max(320, finiteNumber(windowInfo.windowWidth, 844))
|
||||
const windowHeight = Math.max(240, finiteNumber(windowInfo.windowHeight, 390))
|
||||
const safeArea = windowInfo.safeArea || {}
|
||||
|
||||
const safeLeft = clamp(
|
||||
finiteNumber(safeArea.left, 0),
|
||||
0,
|
||||
windowWidth / 3,
|
||||
)
|
||||
const safeRightEdge = clamp(
|
||||
finiteNumber(safeArea.right, windowWidth),
|
||||
windowWidth * 2 / 3,
|
||||
windowWidth,
|
||||
)
|
||||
const safeRight = clamp(
|
||||
windowWidth - safeRightEdge,
|
||||
0,
|
||||
windowWidth / 3,
|
||||
)
|
||||
const safeTop = Math.max(
|
||||
0,
|
||||
finiteNumber(windowInfo.statusBarHeight, 0),
|
||||
finiteNumber(safeArea.top, 0),
|
||||
)
|
||||
const safeBottomEdge = clamp(
|
||||
finiteNumber(safeArea.bottom, windowHeight),
|
||||
windowHeight * 2 / 3,
|
||||
windowHeight,
|
||||
)
|
||||
const safeBottom = clamp(
|
||||
windowHeight - safeBottomEdge,
|
||||
0,
|
||||
windowHeight / 3,
|
||||
)
|
||||
|
||||
const menuLeft = finiteNumber(menuRect.left, windowWidth)
|
||||
const menuBottom = finiteNumber(menuRect.bottom, 0)
|
||||
const hasMenuRect = (
|
||||
menuLeft > windowWidth / 2
|
||||
&& menuLeft < windowWidth
|
||||
&& menuBottom > 0
|
||||
)
|
||||
const compactHeight = windowHeight <= 620
|
||||
const horizontalPageGap = compactHeight ? 10 : 14
|
||||
const capsuleGap = compactHeight ? 8 : 10
|
||||
|
||||
const leftInset = Math.ceil(safeLeft + horizontalPageGap)
|
||||
const rightInset = Math.ceil(Math.max(
|
||||
safeRight + horizontalPageGap,
|
||||
hasMenuRect
|
||||
? windowWidth - menuLeft + capsuleGap
|
||||
: safeRight + horizontalPageGap,
|
||||
))
|
||||
const topInset = Math.ceil(safeTop + (compactHeight ? 8 : 12))
|
||||
const bottomInset = Math.ceil(safeBottom + (compactHeight ? 7 : 12))
|
||||
|
||||
return {
|
||||
windowWidth,
|
||||
windowHeight,
|
||||
compactHeight,
|
||||
safeLeft,
|
||||
safeRight,
|
||||
safeTop,
|
||||
safeBottom,
|
||||
leftInset,
|
||||
rightInset,
|
||||
topInset,
|
||||
bottomInset,
|
||||
hasMenuRect,
|
||||
}
|
||||
}
|
||||
|
||||
function getHomeLayoutStyle(metrics = {}) {
|
||||
return [
|
||||
`height:${Math.max(240, finiteNumber(metrics.windowHeight, 390))}px`,
|
||||
`--home-top-inset:${Math.max(0, finiteNumber(metrics.topInset, 8))}px`,
|
||||
`--home-right-inset:${Math.max(0, finiteNumber(metrics.rightInset, 10))}px`,
|
||||
`--home-bottom-inset:${Math.max(0, finiteNumber(metrics.bottomInset, 7))}px`,
|
||||
`--home-left-inset:${Math.max(0, finiteNumber(metrics.leftInset, 10))}px`,
|
||||
].join(';')
|
||||
}
|
||||
|
||||
function hasReadingProgress(progress = {}) {
|
||||
const completedChapters = Array.isArray(progress.completedChapters)
|
||||
? progress.completedChapters
|
||||
: []
|
||||
const completedHotspots = progress.completedHotspots
|
||||
&& typeof progress.completedHotspots === 'object'
|
||||
? progress.completedHotspots
|
||||
: {}
|
||||
const hasCompletedHotspot = Object.values(completedHotspots).some(
|
||||
(ids) => Array.isArray(ids) && ids.length > 0,
|
||||
)
|
||||
|
||||
return (
|
||||
completedChapters.length > 0
|
||||
|| finiteNumber(progress.lastChapter, 1) > 1
|
||||
|| hasCompletedHotspot
|
||||
)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getHomeLayoutMetrics,
|
||||
getHomeLayoutStyle,
|
||||
hasReadingProgress,
|
||||
}
|
||||
Reference in New Issue
Block a user