136 lines
3.7 KiB
JavaScript
136 lines
3.7 KiB
JavaScript
const COMIC_READER_LAYOUT_CONTRACT = Object.freeze({
|
|
contractId: 'story-first-three-frame-v1',
|
|
columns: Object.freeze({
|
|
art: 3,
|
|
content: 2,
|
|
}),
|
|
frames: Object.freeze({
|
|
front: Object.freeze({
|
|
imageMode: 'aspectFit',
|
|
initialControls: 'none',
|
|
revealGesture: 'single-tap',
|
|
revealedControls: 'topbar-only',
|
|
}),
|
|
back: Object.freeze({
|
|
art: 2,
|
|
content: 3,
|
|
imageMode: 'aspectFit',
|
|
}),
|
|
interaction: Object.freeze({
|
|
art: 2,
|
|
content: 3,
|
|
imageMode: 'aspectFit',
|
|
choiceCount: 2,
|
|
choiceDirection: 'vertical',
|
|
}),
|
|
}),
|
|
minimumControlPx: 48,
|
|
compactHeightMaxPx: 620,
|
|
fontModes: Object.freeze({
|
|
standard: 'large',
|
|
xlarge: 'xlarge',
|
|
}),
|
|
audioSlot: Object.freeze({
|
|
placement: 'unified-topbar',
|
|
minimumHeightPx: 48,
|
|
textModeLabel: '直接看文字',
|
|
readyLabel: '听一听',
|
|
playingLabel: '暂停',
|
|
replayLabel: '重听',
|
|
usesPageAudioCueIds: true,
|
|
}),
|
|
artOverlayPolicy: Object.freeze({
|
|
event: 'transparent-actor-hotspot-only',
|
|
emotion: 'transparent-actor-hotspot-only',
|
|
}),
|
|
})
|
|
|
|
const COMIC_PAGE_TEMPLATE_BY_TYPE = Object.freeze({
|
|
cover: 'chapter-ensemble',
|
|
ensemble: 'chapter-ensemble',
|
|
event: 'actor-event',
|
|
emotion: 'emotion-interaction',
|
|
memory: 'memory-cliffhanger',
|
|
})
|
|
|
|
const COMIC_PRESENTATION_BY_CHAPTER = Object.freeze({
|
|
'S01-C01': 'front-back-comic-v1',
|
|
'S01-C02': 'front-back-comic-v1',
|
|
'S01-C03': 'front-back-comic-v1',
|
|
'S01-C04': 'front-back-comic-v1',
|
|
'S01-C05': 'front-back-comic-v1',
|
|
'S01-C06': 'front-back-comic-v1',
|
|
'S01-C07': 'front-back-comic-v1',
|
|
'S01-C08': 'front-back-comic-v1',
|
|
'S01-C09': 'front-back-comic-v1',
|
|
'S01-C10': 'front-back-comic-v1',
|
|
'S01-C11': 'front-back-comic-v1',
|
|
'S01-C12': 'front-back-comic-v1',
|
|
'S01-C13': 'front-back-comic-v1',
|
|
'S01-C14': 'front-back-comic-v1',
|
|
'S01-C15': 'front-back-comic-v1',
|
|
})
|
|
|
|
function getComicPresentationMode(chapterId) {
|
|
return COMIC_PRESENTATION_BY_CHAPTER[String(chapterId || '')]
|
|
|| 'legacy-60-40-v1'
|
|
}
|
|
|
|
const COMIC_PAGE_LAYOUT_EXCEPTIONS = Object.freeze({
|
|
'S01-C09-P03': Object.freeze({
|
|
layoutVariant: 'standard-landscape-60-40',
|
|
behavior: 'key-safe-actor-hotspot',
|
|
actorHotspot: Object.freeze({ x: 16, y: 3, w: 56, h: 82 }),
|
|
reason: '人物仍可整片点击,但透明热区须止于画面下方钥匙带之前。',
|
|
}),
|
|
})
|
|
|
|
// These pages keep the full reviewed frame and add one read-only crop from
|
|
// the same asset as a second comic panel. This is an art-reading aid, not a
|
|
// new interaction or a page-layout exception.
|
|
const COMIC_FIXED_DETAIL_INSET_PAGE_IDS = Object.freeze([
|
|
'S01-C04-P04',
|
|
'S01-C09-P01',
|
|
'S01-C09-P05',
|
|
'S01-C09-P06',
|
|
'S01-C10-P07',
|
|
'S01-C13-P04',
|
|
'S01-C15-P05',
|
|
'S01-C15-P08',
|
|
])
|
|
|
|
function allowsFixedDetailInset(pageId) {
|
|
return COMIC_FIXED_DETAIL_INSET_PAGE_IDS.indexOf(
|
|
String(pageId || ''),
|
|
) >= 0
|
|
}
|
|
|
|
function getComicPageLayoutException(pageId) {
|
|
return COMIC_PAGE_LAYOUT_EXCEPTIONS[String(pageId || '')] || null
|
|
}
|
|
|
|
function resolveComicPageLayout(pageId, type) {
|
|
const templateKey = COMIC_PAGE_TEMPLATE_BY_TYPE[type] || 'chapter-ensemble'
|
|
const exception = getComicPageLayoutException(pageId)
|
|
return {
|
|
templateKey,
|
|
layoutVariant: exception
|
|
? exception.layoutVariant
|
|
: 'standard-landscape-60-40',
|
|
layoutExceptionId: exception ? String(pageId) : '',
|
|
layoutExceptionBehavior: exception ? exception.behavior : '',
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
COMIC_READER_LAYOUT_CONTRACT,
|
|
COMIC_PRESENTATION_BY_CHAPTER,
|
|
COMIC_PAGE_TEMPLATE_BY_TYPE,
|
|
COMIC_PAGE_LAYOUT_EXCEPTIONS,
|
|
COMIC_FIXED_DETAIL_INSET_PAGE_IDS,
|
|
allowsFixedDetailInset,
|
|
getComicPresentationMode,
|
|
getComicPageLayoutException,
|
|
resolveComicPageLayout,
|
|
}
|