Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05455a86da | ||
|
|
4c78ce8a27
|
||
|
|
d9fa2f5768 | ||
|
|
dfabfc18d6 |
@@ -100,6 +100,11 @@ Things worth knowing before editing:
|
|||||||
`<video>` with no data has a natural size of 300x150, and WebKit sizes it from that —
|
`<video>` with no data has a natural size of 300x150, and WebKit sizes it from that —
|
||||||
so one with no poster of its own gets an empty SVG of the right shape as a stand-in,
|
so one with no poster of its own gets an empty SVG of the right shape as a stand-in,
|
||||||
without which a portrait video sits in a squat landscape box until you press play.
|
without which a portrait video sits in a squat landscape box until you press play.
|
||||||
|
- **A page with a video claims the `playback` audio session** (`public/app.js`). iOS
|
||||||
|
hands inline video the ambient session, which the Ring/Silent switch mutes, so
|
||||||
|
without this the video plays and says nothing until it goes fullscreen — and the
|
||||||
|
report that arrives is "this one platform has no sound". The session only activates
|
||||||
|
once something plays, so declaring it costs nothing on a page nobody presses play on.
|
||||||
- **Never a bare error page.** A failed resolve renders a card carrying the platform, the
|
- **Never a bare error page.** A failed resolve renders a card carrying the platform, the
|
||||||
original URL and the copy button. A broken adapter must still leave the link one tap
|
original URL and the copy button. A broken adapter must still leave the link one tap
|
||||||
away.
|
away.
|
||||||
|
|||||||
@@ -171,6 +171,10 @@ The one exception is Bluesky video, which is an HLS playlist — proxying it wou
|
|||||||
rewriting the manifest and every segment, so it is linked directly. Safari plays HLS
|
rewriting the manifest and every segment, so it is linked directly. Safari plays HLS
|
||||||
natively; other browsers show a note.
|
natively; other browsers show a note.
|
||||||
|
|
||||||
|
A page carrying a video asks iOS for the playback audio session. Without it a video
|
||||||
|
playing inline is treated as ambience and the Ring/Silent switch mutes it, so the post
|
||||||
|
plays perfectly and says nothing unless you go fullscreen.
|
||||||
|
|
||||||
Resolved posts are cached in memory for an hour, so a reload or a back button doesn't
|
Resolved posts are cached in memory for an hour, so a reload or a back button doesn't
|
||||||
drive the browser again.
|
drive the browser again.
|
||||||
|
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "antisocial",
|
"name": "antisocial",
|
||||||
"version": "1.2.3",
|
"version": "1.2.4",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "antisocial",
|
"name": "antisocial",
|
||||||
"version": "1.2.3",
|
"version": "1.2.4",
|
||||||
"license": "UNLICENSED",
|
"license": "UNLICENSED",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fastify/static": "10.1.3",
|
"@fastify/static": "10.1.3",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "antisocial",
|
"name": "antisocial",
|
||||||
"version": "1.2.3",
|
"version": "1.2.4",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "Reads social posts back to you without the app.",
|
"description": "Reads social posts back to you without the app.",
|
||||||
"license": "UNLICENSED",
|
"license": "UNLICENSED",
|
||||||
|
|||||||
@@ -155,6 +155,19 @@ function setupMedia(media) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// On iOS a video playing inline gets the "ambient" audio session, which the
|
||||||
|
// Ring/Silent switch mutes -- so the post plays perfectly and says nothing,
|
||||||
|
// and the only way to hear it is to go fullscreen. Claiming "playback" says
|
||||||
|
// what is true here: the sound is the point, not decoration. The session is
|
||||||
|
// not activated until something actually plays, so declaring it up front
|
||||||
|
// interrupts nothing; it is declared only on a page that has a video so an
|
||||||
|
// ordinary text post never claims it at all.
|
||||||
|
function setupAudioSession() {
|
||||||
|
if (!('audioSession' in navigator)) return;
|
||||||
|
if (!document.querySelector('video')) return;
|
||||||
|
navigator.audioSession.type = 'playback';
|
||||||
|
}
|
||||||
|
|
||||||
// Every comment is a <details open>, so folding one already works with this
|
// Every comment is a <details open>, so folding one already works with this
|
||||||
// file missing. All this adds is doing the whole page at once, which is why
|
// file missing. All this adds is doing the whole page at once, which is why
|
||||||
// the button ships hidden and is only revealed here.
|
// the button ships hidden and is only revealed here.
|
||||||
@@ -189,6 +202,7 @@ setupCopy();
|
|||||||
applyBrowser(storedBrowser());
|
applyBrowser(storedBrowser());
|
||||||
setupBrowserPicker();
|
setupBrowserPicker();
|
||||||
for (const media of document.querySelectorAll('.media')) setupMedia(media);
|
for (const media of document.querySelectorAll('.media')) setupMedia(media);
|
||||||
|
setupAudioSession();
|
||||||
setupComments();
|
setupComments();
|
||||||
|
|
||||||
// --- Verification puzzles -------------------------------------------------
|
// --- Verification puzzles -------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user