mirror of
https://github.com/Shik3i/KoalaSync.git
synced 2026-07-26 12:08:15 +00:00
Normalize shared tab titles
This commit is contained in:
+16
-1
@@ -60,6 +60,22 @@
|
||||
- **Legal/moderation:** Unclear what moderation requirements would apply if users can exchange chat messages. Could be relevant depending on jurisdiction.
|
||||
- **Status:** Under evaluation, may come later.
|
||||
|
||||
### Cross-frame video detection and control
|
||||
|
||||
- **Priority:** P3
|
||||
- **Category:** Compatibility / Embedded Players
|
||||
- **Background:** KoalaSync currently injects on demand into the selected tab's top frame. This works for normal top-frame players, including current Emby/Jellyfin usage, but does not cover cases where the real `<video>` lives inside a cross-origin iframe or an `about:blank`/`srcdoc` player frame.
|
||||
- **Possible approach:** Add an opt-in frame bridge where child frames announce detected videos to the top frame, and the top frame routes remote play/pause/seek commands to the active child video.
|
||||
- **Status:** Future compatibility work, not needed for current Emby behavior.
|
||||
|
||||
### Local extension E2E smoke tests
|
||||
|
||||
- **Priority:** P2
|
||||
- **Category:** Testing / Release Confidence
|
||||
- **Background:** The release verification covers unit tests, server integration, syntax, lint, audits, and builds, but it does not currently run a real browser extension flow. A small local E2E smoke suite would catch regressions in content-script injection, tab navigation reinjection, remote seek handling, and iframe player support.
|
||||
- **Possible approach:** Add a separate local-only Playwright smoke command that loads the unpacked extension, opens two controlled video pages, and verifies play/pause/seek through the actual extension path. Keep it outside `npm run verify` until it is stable enough for CI.
|
||||
- **Status:** Backlog, recommended before larger content-script or frame-bridge changes.
|
||||
|
||||
---
|
||||
|
||||
## ❌ Rejected
|
||||
@@ -70,4 +86,3 @@
|
||||
|---|---|
|
||||
| *(none yet)* | |
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@ import { EVENTS, OFFICIAL_LANDING_PAGE_URL, SUPPORT_URL, getReviewUrl } from './
|
||||
import { BLACKLIST_DOMAINS } from './shared/blacklist.js';
|
||||
import { getAvatarForName, generateUsername, USERNAME_ADJECTIVES, USERNAME_NOUNS } from './shared/names.js';
|
||||
import { loadLocale, translateDOM, getMessage, getSystemLanguage } from './i18n.js';
|
||||
import { TITLE_PRIVACY_MODES, normalizeSendTabTitle } from './title-privacy.js';
|
||||
import { TITLE_PRIVACY_MODES, normalizeSendTabTitle, normalizeTabTitle } from './title-privacy.js';
|
||||
|
||||
|
||||
const elements = {
|
||||
@@ -920,7 +920,7 @@ async function populateTabs(providedPeers = null, providedTargetTabId = null) {
|
||||
// Smart Matching Logic — exclude own tabTitle to prevent self-match (computed once)
|
||||
const cleanTitle = (rawTitle) => {
|
||||
if (!rawTitle) return '';
|
||||
return rawTitle
|
||||
return (normalizeTabTitle(rawTitle) || '')
|
||||
.replace(/(?:\s*[-\|•]\s*(?:YouTube|Twitch|Jellyfin|Emby|Netflix|Vimeo|Dailymotion).*)$/i, '')
|
||||
.replace(/^(?:Netflix|Twitch|YouTube|Emby|Jellyfin)\s*[-\|•]\s*/i, '')
|
||||
.trim();
|
||||
|
||||
@@ -17,9 +17,15 @@ export function normalizeSendTabTitle(sendTabTitle, legacyMode = TITLE_PRIVACY_M
|
||||
return normalizeTitlePrivacyMode(legacyMode) === TITLE_PRIVACY_MODES.FULL;
|
||||
}
|
||||
|
||||
export function normalizeTabTitle(title) {
|
||||
if (typeof title !== 'string') return null;
|
||||
const normalized = title.replace(/^\s*(?:\(\d{1,2}\)|\[\d{1,2}\])\s+/, '').trim();
|
||||
return normalized.length > 0 ? normalized : null;
|
||||
}
|
||||
|
||||
export function sanitizeTabTitle(title, sendTabTitle) {
|
||||
if (!sendTabTitle) return null;
|
||||
return typeof title === 'string' && title.length > 0 ? title : null;
|
||||
return normalizeTabTitle(title);
|
||||
}
|
||||
|
||||
export function sanitizeSharedTitle(title, mode) {
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
TITLE_PRIVACY_MODES,
|
||||
applyTitlePrivacyToPayload,
|
||||
normalizeSendTabTitle,
|
||||
normalizeTabTitle,
|
||||
normalizeTitlePrivacyMode,
|
||||
sanitizeSharedTitle,
|
||||
sanitizeTabTitle
|
||||
@@ -15,8 +16,13 @@ assert.equal(normalizeSendTabTitle(undefined, TITLE_PRIVACY_MODES.FULL), true);
|
||||
assert.equal(normalizeSendTabTitle(undefined, TITLE_PRIVACY_MODES.EPISODE), false);
|
||||
assert.equal(normalizeSendTabTitle(true, TITLE_PRIVACY_MODES.HIDDEN), true);
|
||||
assert.equal(normalizeSendTabTitle(false, TITLE_PRIVACY_MODES.FULL), false);
|
||||
assert.equal(normalizeTabTitle('(12) Testvideo - YouTube'), 'Testvideo - YouTube');
|
||||
assert.equal(normalizeTabTitle('[7] Testvideo - YouTube'), 'Testvideo - YouTube');
|
||||
assert.equal(normalizeTabTitle('(500) Days of Summer'), '(500) Days of Summer');
|
||||
assert.equal(normalizeTabTitle(' '), null);
|
||||
|
||||
assert.equal(sanitizeTabTitle('Private Tab', true), 'Private Tab');
|
||||
assert.equal(sanitizeTabTitle('(12) Private Tab', true), 'Private Tab');
|
||||
assert.equal(sanitizeTabTitle('Private Tab', false), null);
|
||||
assert.equal(sanitizeTabTitle('', true), null);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user