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:
parent
200f03c1f8
commit
df937f3e40
1 changed files with 13 additions and 8 deletions
|
|
@ -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)}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue