Compare commits
3
Commits
video-restart
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b0d60d0a5b | ||
|
|
71e759e477 | ||
|
|
24dd05db5d |
No files matched your search
@@ -23,6 +23,7 @@ services:
|
|||||||
MS_CLIENT_SECRET: ${MS_CLIENT_SECRET:-}
|
MS_CLIENT_SECRET: ${MS_CLIENT_SECRET:-}
|
||||||
LYRICS_API_URL: http://127.0.0.1:9999 # the bundled lyrics service (Lyrica, below, shares this container's network); remove this line and the service to skip it
|
LYRICS_API_URL: http://127.0.0.1:9999 # the bundled lyrics service (Lyrica, below, shares this container's network); remove this line and the service to skip it
|
||||||
TRANSCRIBE_API_URL: http://127.0.0.1:8000 # the bundled speech-to-text service (whisper, below): makes a transcript for a podcast or audiobook on request. Remove this line and the service to skip it
|
TRANSCRIBE_API_URL: http://127.0.0.1:8000 # the bundled speech-to-text service (whisper, below): makes a transcript for a podcast or audiobook on request. Remove this line and the service to skip it
|
||||||
|
TRANSCRIBE_MODEL: ${TRANSCRIBE_MODEL:-Systran/faster-whisper-base} # smaller and about 3x faster than -small on a CPU-only host; set Systran/faster-whisper-small for better accuracy
|
||||||
SIGNAL_API_URL: http://127.0.0.1:8085 # the bundled Signal bridge (below, shares this container's network); remove this line and the service to skip Signal
|
SIGNAL_API_URL: http://127.0.0.1:8085 # the bundled Signal bridge (below, shares this container's network); remove this line and the service to skip Signal
|
||||||
OPENAUDIBLE_URL: ${OPENAUDIBLE_URL:-} # audiobooks straight from OpenAudible (e.g. http://172.16.16.106:8000); the username and password in Settings -> Audiobooks sign-in are OpenAudible's. Leave empty to go through the audiobook player instead
|
OPENAUDIBLE_URL: ${OPENAUDIBLE_URL:-} # audiobooks straight from OpenAudible (e.g. http://172.16.16.106:8000); the username and password in Settings -> Audiobooks sign-in are OpenAudible's. Leave empty to go through the audiobook player instead
|
||||||
PODCAST_URL: ${PODCAST_URL:-https://podcast.necloud.us/}
|
PODCAST_URL: ${PODCAST_URL:-https://podcast.necloud.us/}
|
||||||
|
|||||||
+3
-2
@@ -345,10 +345,11 @@ async function chAnnounceCard(el) {
|
|||||||
function chFit() {
|
function chFit() {
|
||||||
const m = chMounted() && ch.root.querySelector('.sgm'); if (!m || m.offsetParent === null) return;
|
const m = chMounted() && ch.root.querySelector('.sgm'); if (!m || m.offsetParent === null) return;
|
||||||
if (window.innerWidth >= 1024) { m.style.height = ''; return; }
|
if (window.innerWidth >= 1024) { m.style.height = ''; return; }
|
||||||
let bottom = window.visualViewport ? window.visualViewport.height : window.innerHeight;
|
let bottom = window.visualViewport ? window.visualViewport.offsetTop + window.visualViewport.height : window.innerHeight; // (page coordinates: the visible area can be panned down while the keyboard is up)
|
||||||
const top0 = m.getBoundingClientRect().top; // (look up from the screen's edge for the first spot that is page content, not the bottom bar or mini player)
|
const top0 = m.getBoundingClientRect().top; // (look up from the screen's edge for the first spot that is page content, not the bottom bar or mini player)
|
||||||
for (let y = Math.floor(bottom) - 2; y > top0 + 130; y -= 4) { const hit = document.elementsFromPoint(innerWidth / 2, y).find(e => !e.closest('.sgm')); const covers = hit && !hit.closest('#view'); if (!covers) { bottom = y + 4; break; } }
|
for (let y = Math.floor(bottom) - 2; y > top0 + 130; y -= 4) { const hit = document.elementsFromPoint(innerWidth / 2, y).find(e => !e.closest('.sgm')); const covers = hit && !hit.closest('#view'); if (!covers) { bottom = y + 4; break; } }
|
||||||
const top = m.getBoundingClientRect().top; m.style.height = Math.max(260, Math.floor(bottom - top - 10)) + 'px';
|
const top = m.getBoundingClientRect().top; m.style.height = Math.max(document.body.classList.contains('kb') ? 150 : 260, Math.floor(bottom - top - 10)) + 'px';
|
||||||
}
|
}
|
||||||
|
window.addEventListener('kbfit', () => { chFit(); if (!chMounted() || !chq('.sgm')) return; const v = document.getElementById('view'); if (v) v.scrollTop = 0; const l = chq('#chmsgs'); if (l && document.activeElement && document.activeElement.id === 'chtext') l.scrollTop = l.scrollHeight; }); // (the keyboard came or went: refit, and keep the newest message in sight)
|
||||||
window.addEventListener('resize', chFit); if (window.visualViewport) window.visualViewport.addEventListener('resize', chFit);
|
window.addEventListener('resize', chFit); if (window.visualViewport) window.visualViewport.addEventListener('resize', chFit);
|
||||||
setInterval(chFit, 700);
|
setInterval(chFit, 700);
|
||||||
@@ -68,3 +68,22 @@
|
|||||||
else if (!e.shiftKey && (document.activeElement === last || !s.contains(document.activeElement))) { e.preventDefault(); first.focus(); }
|
else if (!e.shiftKey && (document.activeElement === last || !s.contains(document.activeElement))) { e.preventDefault(); first.focus(); }
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
// ---- iPhone keyboard: iOS shrinks only the visual viewport when the keyboard opens and pans the whole page to reveal the field, so the app used to slide up with it.
|
||||||
|
// Pin the shell to what is really visible while typing and tuck the bottom bar away; chat and mail size themselves again on 'kbfit'.
|
||||||
|
(function () {
|
||||||
|
const vv = window.visualViewport; if (!vv || !matchMedia('(pointer: coarse)').matches) return;
|
||||||
|
const root = document.documentElement; let raf = 0;
|
||||||
|
const typing = () => { const a = document.activeElement; return !!a && (a.tagName === 'TEXTAREA' || a.isContentEditable || (a.tagName === 'INPUT' && !/^(checkbox|radio|button|submit|reset|range|file|color|image)$/.test(a.type))); };
|
||||||
|
function apply() {
|
||||||
|
raf = 0;
|
||||||
|
const kb = typing() && window.innerHeight - vv.height > 120 && window.innerWidth < 768;
|
||||||
|
document.body.classList.toggle('kb', kb);
|
||||||
|
if (kb) { root.style.setProperty('--vvh', vv.height + 'px'); root.style.setProperty('--vvt', vv.offsetTop + 'px'); if (window.scrollY) window.scrollTo(0, 0); }
|
||||||
|
else { root.style.removeProperty('--vvh'); root.style.removeProperty('--vvt'); }
|
||||||
|
window.dispatchEvent(new Event('kbfit'));
|
||||||
|
}
|
||||||
|
const soon = () => { if (!raf) raf = requestAnimationFrame(apply); };
|
||||||
|
vv.addEventListener('resize', soon); vv.addEventListener('scroll', soon);
|
||||||
|
document.addEventListener('focusin', soon); document.addEventListener('focusout', () => setTimeout(soon, 80));
|
||||||
|
})();
|
||||||
@@ -264,6 +264,14 @@ body { -webkit-touch-callout: none; }
|
|||||||
button, a, .row { -webkit-user-select: none; user-select: none; }
|
button, a, .row { -webkit-user-select: none; user-select: none; }
|
||||||
input, textarea, [contenteditable], .sheet p, .card p, #view .sub { -webkit-user-select: text; user-select: text; }
|
input, textarea, [contenteditable], .sheet p, .card p, #view .sub { -webkit-user-select: text; user-select: text; }
|
||||||
|
|
||||||
|
/* iPhone keyboard (shell.js adds body.kb while a field is focused and the keyboard is up): the shell is exactly the visible area, with no bottom bar in the way */
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
body.kb { overflow: hidden; }
|
||||||
|
body.kb #shell { height: var(--vvh, 100dvh); transform: translateY(var(--vvt, 0px)); }
|
||||||
|
body.kb #nav, body.kb #player, body.kb #upd, body.kb #toast { display: none; }
|
||||||
|
body.kb .sgm { min-height: 0; }
|
||||||
|
}
|
||||||
|
|
||||||
/* "A new version is available" notice */
|
/* "A new version is available" notice */
|
||||||
#upd { position: fixed; left: 50%; transform: translateX(-50%); bottom: calc(var(--nav-h) + var(--sab) + 70px); z-index: 30; display: flex; align-items: center; gap: 12px;
|
#upd { position: fixed; left: 50%; transform: translateX(-50%); bottom: calc(var(--nav-h) + var(--sab) + 70px); z-index: 30; display: flex; align-items: center; gap: 12px;
|
||||||
background: var(--text); color: var(--bg); padding: 8px 8px 8px 16px; border-radius: 14px; box-shadow: 0 6px 24px rgba(0,0,0,.35); max-width: 92vw; }
|
background: var(--text); color: var(--bg); padding: 8px 8px 8px 16px; border-radius: 14px; box-shadow: 0 6px 24px rgba(0,0,0,.35); max-width: 92vw; }
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
// App-shell cache only; Seafile/API traffic always goes to the network.
|
// App-shell cache only; Seafile/API traffic always goes to the network.
|
||||||
const CACHE = 'hub-v88';
|
const CACHE = 'hub-v89';
|
||||||
const SHARE = 'hub-share'; // files shared into the app from other apps, held until the person picks a folder
|
const SHARE = 'hub-share'; // files shared into the app from other apps, held until the person picks a folder
|
||||||
const SHELL = ['/icon.svg', '/manifest.webmanifest', '/icons/icon-192.png', '/icons/apple-touch-icon.png'];
|
const SHELL = ['/icon.svg', '/manifest.webmanifest', '/icons/icon-192.png', '/icons/apple-touch-icon.png'];
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user