file-show: cover
Massimo Melina committed
Feb 3, 2024 at 19:49 UTC
24e68b5bb5f6e29fd3646c77385e6c6264d02e1e
2 files changed
+16
-2
frontend/src/index.scss
+12
-1
@@ -648,11 +648,22 @@ button .icon + .label {
648
flex-direction: column-reverse !important; // bar at the bottom, easier on the thumb
649
}
650
}
651
- .showing-container { width: 100%; height: 100%; display: flex; justify-content: center; align-items: center;}
651
+ .showing-container { width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; position: relative; }
652
.showing {
653
max-width: calc(100% - min(4vw, var(--nav-size)) * 2); // avoid overlapping of controls and nav buttons
654
max-height: 100%;
655
}
656
+ .cover {
657
+ position: absolute;
658
+ width: 100%; height: 100%;
659
+ background-repeat: no-repeat;
660
+ background-size: contain;
661
+ background-position: center;
662
+ z-index: -1; // otherwise firefox
663
+ opacity: .3;
664
+ transition: opacity 1s;
665
+ &.none { opacity: 0; }
666
+ }
667
audio.showing { min-width: 60%; }
668
audio.showing, // even on mobile, we need the whole thing to control it decently, and nav-s don't seem to be a problem
669
img.showing { max-width: 100% } // we are ok with overlapping for simple images
frontend/src/show.ts
+4
-1
@@ -26,6 +26,7 @@ export function fileShow(entry: DirEntry) {
26
const [mode, setMode] = useState(ZoomMode.contain)
27
const [shuffle, setShuffle] = useState<undefined|DirList>()
28
const [repeat, setRepeat] = useState(false)
29
+ const [cover, setCover] = useState('')
30
useEffect(() => {
31
if (shuffle)
32
goTo(shuffle[0])
@@ -73,7 +74,7 @@ export function fileShow(entry: DirEntry) {
74
75
const { auto_play_seconds } = useSnapState()
76
const [autoPlaying, setAutoPlaying] = useState(false)
76
- const showElement = containerRef.current?.querySelector('*')
77
+ const showElement = containerRef.current?.querySelector('.showing')
78
useEffect(() => {
79
if (!autoPlaying || !showElement) return
80
if (showElement instanceof HTMLMediaElement) {
@@ -139,6 +140,7 @@ export function fileShow(entry: DirEntry) {
140
h('div', {}, cur.name),
141
t`Loading failed`
142
) : h('div', { className: 'showing-container', ref: containerRef },
143
+ h('div', { className: 'cover ' + (cover ? '' : 'none'), style: { backgroundImage: `url(${cover})` } }),
144
h(getShowType(cur) || Fragment, {
145
src: cur.uri,
146
className: 'showing',
@@ -151,6 +153,7 @@ export function fileShow(entry: DirEntry) {
153
const folder = cur.n.slice(0, -cur.name)
154
const covers = state.list.filter(x => folder === x.n.slice(0, -x.name) // same folder
155
&& x.name.match(/(?:folder|cover|albumart.*)\.jpe?g$/i))
156
+ setCover(_.maxBy(covers, 's')?.n || '')
157
navigator.mediaSession.metadata = new MediaMetadata({
158
title: cur.name,
159
album: decodeURIComponent(basename(dirname(cur.uri))),