fix(soundboard): auto-prepend https:// for URL import

URLs pasted without protocol (e.g. instagram.com/reel/...) now work.
normalizeUrl() adds https:// if missing. Input type changed from
"url" to "text" to prevent browser validation blocking paste.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Daniel 2026-03-06 23:45:41 +01:00
parent 200f03c1f8
commit df937f3e40

View file

@ -414,29 +414,34 @@ export default function SoundboardTab({ data }: SoundboardTabProps) {
}, []);
const soundKey = useCallback((s: Sound) => s.relativePath ?? s.fileName, []);
const YTDLP_HOSTS = ['youtube.com', 'www.youtube.com', 'm.youtube.com', 'youtu.be', 'music.youtube.com', 'instagram.com', 'www.instagram.com'];
/** Auto-prepend https:// if missing */
const normalizeUrl = useCallback((value: string): string => {
const v = value.trim();
if (!v) return v;
if (/^https?:\/\//i.test(v)) return v;
return 'https://' + v;
}, []);
const isSupportedUrl = useCallback((value: string) => {
try {
const parsed = new URL(value.trim());
const parsed = new URL(normalizeUrl(value));
const host = parsed.hostname.toLowerCase();
// Direct MP3 link
if (parsed.pathname.toLowerCase().endsWith('.mp3')) return true;
// YouTube / Instagram
if (YTDLP_HOSTS.some(h => host === h || host.endsWith('.' + h))) return true;
return false;
} catch {
return false;
}
}, []);
}, [normalizeUrl]);
const getUrlType = useCallback((value: string): 'youtube' | 'instagram' | 'mp3' | null => {
try {
const parsed = new URL(value.trim());
const parsed = new URL(normalizeUrl(value));
const host = parsed.hostname.toLowerCase();
if (host.includes('youtube') || host === 'youtu.be') return 'youtube';
if (host.includes('instagram')) return 'instagram';
if (parsed.pathname.toLowerCase().endsWith('.mp3')) return 'mp3';
return null;
} catch { return null; }
}, []);
}, [normalizeUrl]);
const guildId = selected ? selected.split(':')[0] : '';
const channelId = selected ? selected.split(':')[1] : '';
@ -632,7 +637,7 @@ export default function SoundboardTab({ data }: SoundboardTabProps) {
}
async function handleUrlImport() {
const trimmed = importUrl.trim();
const trimmed = normalizeUrl(importUrl);
if (!trimmed) return notify('Bitte einen Link eingeben', 'error');
if (!isSupportedUrl(trimmed)) return notify('Nur YouTube, Instagram oder direkte MP3-Links', 'error');
setImportBusy(true);
@ -1017,7 +1022,7 @@ export default function SoundboardTab({ data }: SoundboardTabProps) {
</span>
<input
className="url-import-input"
type="url"
type="text"
placeholder="YouTube / Instagram / MP3-Link..."
value={importUrl}
onChange={e => setImportUrl(e.target.value)}