openvibers/openvibe.network Commits
Right now: a live stream with no thumbnail falls back to the streamer's avatar (an empty URL became openvibe.live's home page, drawn as a blank box) (#304)
Changes
@@@ -31,7 +31,9 @@ let enabled = process.env.HOME_ACTIVITY !== 'off' && process.env.NODE_ENV !== 'tlet readers = {};const clip = (s, n) => { const t = String(s == null ? '' : s).replace(/\s+/g, ' ').trim(); return t.length > n ? `${t.slice(0, n - 1).trimEnd()}…` : t; };--const abs = (base, u) => { try { const x = new URL(String(u || ''), base); return /^https:$/.test(x.protocol) ? x.href : null; } catch { return null; } };++// An empty value is no URL (new URL('', base) is the base itself: a stream with no thumbnail drew openvibe.live's home++// page as its picture, a blank box, instead of falling back to the streamer's avatar).++const abs = (base, u) => { if (u == null || String(u).trim() === '') return null; try { const x = new URL(String(u), base); return /^https:$/.test(x.protocol) ? x.href : null; } catch { return null; } };const onHost = (u, host) => { try { const x = new URL(String(u || '')); return x.protocol === 'https:' && x.hostname === host ? x.href : null; } catch { return null; } };// The front door is the network's most public page, so it is stricter than the services it quotes: an item whose words@@@ -20,6 +20,9 @@ assert.deepStrictEqual(live.map((s) => s.name), ['bob', 'Alice'], 'live and SFWassert.strictEqual(live[1].thumb, 'https://openvibe.live/api/thumbnails/a.jpg', 'a relative thumbnail becomes the public https URL');assert.strictEqual(live[0].thumb, null, 'a non-https thumbnail is dropped');assert.strictEqual(live[1].url, 'https://openvibe.live/@alice');++// No thumbnail is no picture (it was openvibe.live's home page, drawn as a blank box): the card falls back to the avatar.++const bare = activity.liveStreams({ streams: [{ is_live: 1, username: 'cara', title: 't', thumbnail_url: null, avatar_url: 'https://openvibe.media/o/med_1' }, { is_live: 1, username: 'dee', title: 't', thumbnail_url: '', avatar_url: '' }] });++assert.deepStrictEqual(bare.map((s) => [s.thumb, s.avatar]), [[null, 'https://openvibe.media/o/med_1'], [null, null]]);const pastes = activity.publicPastes({ pastes: [{ slug: 'one', title: 'Public one', visibility: 'public', type: 'code', language: 'js' },
@@ -31,7 +31,9 @@ let enabled = process.env.HOME_ACTIVITY !== 'off' && process.env.NODE_ENV !== 't
@@ -31,7 +31,9 @@ let enabled = process.env.HOME_ACTIVITY !== 'off' && process.env.NODE_ENV !== 't
let readers = {};
let readers = {};
const clip = (s, n) => { const t = String(s == null ? '' : s).replace(/\s+/g, ' ').trim(); return t.length > n ? `${t.slice(0, n - 1).trimEnd()}…` : t; };
const clip = (s, n) => { const t = String(s == null ? '' : s).replace(/\s+/g, ' ').trim(); return t.length > n ? `${t.slice(0, n - 1).trimEnd()}…` : t; };
-const abs = (base, u) => { try { const x = new URL(String(u || ''), base); return /^https:$/.test(x.protocol) ? x.href : null; } catch { return null; } };
+// An empty value is no URL (new URL('', base) is the base itself: a stream with no thumbnail drew openvibe.live's home
+// page as its picture, a blank box, instead of falling back to the streamer's avatar).
+const abs = (base, u) => { if (u == null || String(u).trim() === '') return null; try { const x = new URL(String(u), base); return /^https:$/.test(x.protocol) ? x.href : null; } catch { return null; } };
const onHost = (u, host) => { try { const x = new URL(String(u || '')); return x.protocol === 'https:' && x.hostname === host ? x.href : null; } catch { return null; } };
const onHost = (u, host) => { try { const x = new URL(String(u || '')); return x.protocol === 'https:' && x.hostname === host ? x.href : null; } catch { return null; } };
// The front door is the network's most public page, so it is stricter than the services it quotes: an item whose words
// The front door is the network's most public page, so it is stricter than the services it quotes: an item whose words
@@ -20,6 +20,9 @@ assert.deepStrictEqual(live.map((s) => s.name), ['bob', 'Alice'], 'live and SFW
@@ -20,6 +20,9 @@ assert.deepStrictEqual(live.map((s) => s.name), ['bob', 'Alice'], 'live and SFW
assert.strictEqual(live[1].thumb, 'https://openvibe.live/api/thumbnails/a.jpg', 'a relative thumbnail becomes the public https URL');
assert.strictEqual(live[1].thumb, 'https://openvibe.live/api/thumbnails/a.jpg', 'a relative thumbnail becomes the public https URL');
assert.strictEqual(live[0].thumb, null, 'a non-https thumbnail is dropped');
assert.strictEqual(live[0].thumb, null, 'a non-https thumbnail is dropped');
assert.strictEqual(live[1].url, 'https://openvibe.live/@alice');
assert.strictEqual(live[1].url, 'https://openvibe.live/@alice');
+// No thumbnail is no picture (it was openvibe.live's home page, drawn as a blank box): the card falls back to the avatar.
+const bare = activity.liveStreams({ streams: [{ is_live: 1, username: 'cara', title: 't', thumbnail_url: null, avatar_url: 'https://openvibe.media/o/med_1' }, { is_live: 1, username: 'dee', title: 't', thumbnail_url: '', avatar_url: '' }] });
+assert.deepStrictEqual(bare.map((s) => [s.thumb, s.avatar]), [[null, 'https://openvibe.media/o/med_1'], [null, null]]);
const pastes = activity.publicPastes({ pastes: [
const pastes = activity.publicPastes({ pastes: [
{ slug: 'one', title: 'Public one', visibility: 'public', type: 'code', language: 'js' },
{ slug: 'one', title: 'Public one', visibility: 'public', type: 'code', language: 'js' },