[FEATURE] Add flipnote.js web playback

Adds in-browser Flipnote playback with audio, seeking, mute and looping using flipnote.js. Introduces a separate media route for playback so loading a Flipnote does not increment download counts, while retaining the existing first-frame preview as a fallback.
This commit is contained in:
Rekushi authored and GitHub committed 2026-09-15 23:22:31 +01:00
1 parent b6d610d15f
commit 4817f99974
3 files changed
+213 -3

No files matched your search

+5
View File
@@ -81,3 +81,8 @@ input,textarea,select{width:100%;border:1px solid var(--line);border-radius:3px;
@media(max-width:1050px){.flipnote-grid{grid-template-columns:repeat(4,minmax(0,1fr))}.watch-layout{grid-template-columns:minmax(0,1fr) 270px}.docs-layout{grid-template-columns:205px minmax(0,1fr)}}
@media(max-width:820px){.credit-list{grid-template-columns:1fr}.docs-layout{grid-template-columns:1fr}.docs-nav{position:static}.docs-nav nav{grid-template-columns:repeat(3,minmax(0,1fr))}.watch-head{align-items:flex-start}.related-grid{grid-template-columns:repeat(3,minmax(0,1fr))}.header-inner{height:auto;min-height:68px;flex-wrap:wrap;gap:0 12px;padding-top:6px;padding-bottom:6px}.brand{width:164px;height:54px}.brand img{width:164px}.main-nav{order:3;width:100%;height:36px}.nav-link{padding:0 10px}.header-actions{margin-left:auto}.flipnote-grid{grid-template-columns:repeat(3,minmax(0,1fr))}.watch-layout{grid-template-columns:1fr}.detail-panel{position:static}.comment{grid-template-columns:120px 1fr}.admin-ban-form{grid-template-columns:1fr}.page-shell{padding-top:20px}}
@media(max-width:580px){.docs-nav nav{grid-template-columns:repeat(2,minmax(0,1fr))}.watch-head{flex-direction:column;align-items:stretch}.preview-stage{min-height:220px}.preview-footer{align-items:flex-start;flex-direction:column}.related-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.header-inner{padding-left:12px;padding-right:12px}.brand{width:150px}.brand img{width:150px}.nav-action{padding:0 8px;font-size:12px}.nav-action:not(.ghost){display:none}.page-shell{padding:16px 12px 50px}.page-head,.page-head.split,.home-intro-card,.site-footer{align-items:flex-start;flex-direction:column}.page-head h1{font-size:25px}.tabs{width:100%;justify-content:space-between}.flipnote-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:9px}.comment{grid-template-columns:1fr;gap:4px}.comment-form{align-items:stretch;flex-direction:column}.site-footer{padding-left:12px;padding-right:12px}.site-footer>div{flex-wrap:wrap}}
/* flipnote.js web player */
.flipnote-stage{position:relative;overflow:hidden;min-height:0;aspect-ratio:4/3}.flipnote-player-canvas{display:none;width:100%;height:100%;align-items:center;justify-content:center;background:#080708;cursor:pointer}.flipnote-stage.is-ready .flipnote-player-canvas{display:flex}.flipnote-player-canvas canvas{display:block;width:100%!important;height:100%!important;max-width:100%;object-fit:contain;background:#080708;image-rendering:auto}.flipnote-player-fallback{display:block;width:100%;height:100%;object-fit:contain;background:#080708}.flipnote-stage.is-ready .flipnote-player-fallback,.flipnote-player-fallback[hidden]{display:none}.flipnote-player-status{position:absolute;left:12px;bottom:12px;padding:5px 8px;border:1px solid rgba(255,255,255,.12);border-radius:3px;background:rgba(8,7,8,.84);color:#d7cfcd;font-size:11px;font-weight:700}.flipnote-big-play{position:absolute;left:50%;top:50%;width:64px;height:64px;transform:translate(-50%,-50%);border:1px solid rgba(255,255,255,.28);border-radius:50%;background:rgba(8,7,8,.78);color:#fff;font:700 25px/1 system-ui,sans-serif;cursor:pointer;padding:0 0 1px 4px;box-shadow:0 3px 18px rgba(0,0,0,.35)}.flipnote-big-play:hover{background:rgba(177,59,41,.9)}.flipnote-big-play[hidden]{display:none}.flipnote-stage.has-player-error .flipnote-player-status{border-color:#70423b;background:rgba(33,21,19,.94)}
.flipnote-controls{display:grid;grid-template-columns:auto minmax(110px,1fr) auto auto auto;gap:8px;align-items:center;padding:8px 10px;border-top:1px solid var(--line);background:#111012}.flipnote-control-button{min-width:58px;height:30px;padding:0 9px;border:1px solid var(--line);border-radius:3px;background:var(--surface-raised);color:#ddd5d3;font:700 11px/1 system-ui,sans-serif;cursor:pointer}.flipnote-control-button:hover:not(:disabled),.flipnote-control-button.is-active{border-color:#7e463e;background:#2a1916;color:#fff}.flipnote-control-button:disabled{opacity:.45;cursor:default}.flipnote-progress{width:100%;min-width:70px;accent-color:var(--accent);cursor:pointer}.flipnote-progress:disabled{cursor:default;opacity:.45}.flipnote-time{min-width:82px;color:var(--muted);font:700 10px/1.2 ui-monospace,SFMono-Regular,Consolas,monospace;text-align:center;white-space:nowrap}
@media(max-width:580px){.flipnote-controls{grid-template-columns:auto minmax(90px,1fr) auto}.flipnote-time{grid-column:2;text-align:left}.flipnote-control-button[data-action="mute"]{grid-column:3}.flipnote-control-button[data-action="loop"]{grid-column:3}.flipnote-big-play{width:56px;height:56px;font-size:22px}}