diff --git a/package.json b/package.json index cd4185b82..566621b7f 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "build:fdroid": "cross-env PUBLIC_URL=./ GENERATE_SOURCEMAP=false VITE_APP_DISTRIBUTION=fdroid vite build", "build:preload": "vite build --config electron/vite.preload.config.js", "build-vercel": "cross-env NODE_OPTIONS=\"--max_old_space_size=4096\" PUBLIC_URL=./ GENERATE_SOURCEMAP=true VITE_COMMIT_REF=$COMMIT_REF CI='' vite build", - "test": "vitest", + "test": "vitest --maxWorkers=4", "test:leaks": "vitest run --detectAsyncLeaks", "preview": "vite preview", "analyze-bundle": "cross-env PUBLIC_URL=./ GENERATE_SOURCEMAP=true vite build && npx source-map-explorer 'dist/assets/*.js'", diff --git a/public/translations/ar/default.json b/public/translations/ar/default.json index 2475c0923..b0d22087b 100644 --- a/public/translations/ar/default.json +++ b/public/translations/ar/default.json @@ -399,5 +399,6 @@ "ban": "حظر", "timestamp": "الطابع الزمني", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "فيديو YouTube" } diff --git a/public/translations/bn/default.json b/public/translations/bn/default.json index a8f9da3b0..2085b7c40 100644 --- a/public/translations/bn/default.json +++ b/public/translations/bn/default.json @@ -399,5 +399,6 @@ "ban": "নিষেধ করুন", "timestamp": "টাইমস্ট্যাম্প", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "YouTube ভিডিও" } diff --git a/public/translations/cs/default.json b/public/translations/cs/default.json index b62cd25f2..750ba1345 100644 --- a/public/translations/cs/default.json +++ b/public/translations/cs/default.json @@ -399,5 +399,6 @@ "ban": "zakázat", "timestamp": "časové razítko", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "video YouTube" } diff --git a/public/translations/da/default.json b/public/translations/da/default.json index 17045636b..27942ea82 100644 --- a/public/translations/da/default.json +++ b/public/translations/da/default.json @@ -399,5 +399,6 @@ "ban": "forbyd", "timestamp": "tidsstempel", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "YouTube-video" } diff --git a/public/translations/de/default.json b/public/translations/de/default.json index c9e0ec333..f4f36056a 100644 --- a/public/translations/de/default.json +++ b/public/translations/de/default.json @@ -399,5 +399,6 @@ "ban": "sperren", "timestamp": "Zeitstempel", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "YouTube-Video" } diff --git a/public/translations/el/default.json b/public/translations/el/default.json index 2ae041a29..3c54ca986 100644 --- a/public/translations/el/default.json +++ b/public/translations/el/default.json @@ -399,5 +399,6 @@ "ban": "απαγόρευση", "timestamp": "χρονοσήμανση", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "βίντεο YouTube" } diff --git a/public/translations/en/default.json b/public/translations/en/default.json index 37c97a0ca..4b8d99f3c 100644 --- a/public/translations/en/default.json +++ b/public/translations/en/default.json @@ -418,5 +418,6 @@ "ban": "ban", "timestamp": "timestamp", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "YouTube video" } diff --git a/public/translations/es/default.json b/public/translations/es/default.json index 39162f609..f5e43b78c 100644 --- a/public/translations/es/default.json +++ b/public/translations/es/default.json @@ -399,5 +399,6 @@ "ban": "prohibir", "timestamp": "marca de tiempo", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "video de YouTube" } diff --git a/public/translations/fa/default.json b/public/translations/fa/default.json index c9ad89dc8..075e2049a 100644 --- a/public/translations/fa/default.json +++ b/public/translations/fa/default.json @@ -399,5 +399,6 @@ "ban": "مسدود کردن", "timestamp": "مهر زمان", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "ویدیوی YouTube" } diff --git a/public/translations/fi/default.json b/public/translations/fi/default.json index d91352b54..419488edf 100644 --- a/public/translations/fi/default.json +++ b/public/translations/fi/default.json @@ -399,5 +399,6 @@ "ban": "kielto", "timestamp": "aikaleimaustiedosto", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "YouTube-video" } diff --git a/public/translations/fil/default.json b/public/translations/fil/default.json index 8b3d74e5c..66e459df4 100644 --- a/public/translations/fil/default.json +++ b/public/translations/fil/default.json @@ -399,5 +399,6 @@ "ban": "ipagbawal", "timestamp": "timestamp", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "video sa YouTube" } diff --git a/public/translations/fr/default.json b/public/translations/fr/default.json index 45aca0d6a..393646848 100644 --- a/public/translations/fr/default.json +++ b/public/translations/fr/default.json @@ -399,5 +399,6 @@ "ban": "interdire", "timestamp": "horodatage", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "vidéo YouTube" } diff --git a/public/translations/he/default.json b/public/translations/he/default.json index 046059c41..d823e75d8 100644 --- a/public/translations/he/default.json +++ b/public/translations/he/default.json @@ -399,5 +399,6 @@ "ban": "חסימה", "timestamp": "חותמת זמן", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "סרטון YouTube" } diff --git a/public/translations/hi/default.json b/public/translations/hi/default.json index b8a62a8ca..e0546c6b3 100644 --- a/public/translations/hi/default.json +++ b/public/translations/hi/default.json @@ -399,5 +399,6 @@ "ban": "प्रतिबंध", "timestamp": "टाइमस्टैंप", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "YouTube वीडियो" } diff --git a/public/translations/hu/default.json b/public/translations/hu/default.json index 18e701de1..30bf5d2cf 100644 --- a/public/translations/hu/default.json +++ b/public/translations/hu/default.json @@ -399,5 +399,6 @@ "ban": "tiltás", "timestamp": "időbélyeg", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "YouTube-videó" } diff --git a/public/translations/id/default.json b/public/translations/id/default.json index 68872425a..dedc1dbb4 100644 --- a/public/translations/id/default.json +++ b/public/translations/id/default.json @@ -399,5 +399,6 @@ "ban": "larangan", "timestamp": "stempel waktu", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "video YouTube" } diff --git a/public/translations/it/default.json b/public/translations/it/default.json index bc32a557c..2b9e99130 100644 --- a/public/translations/it/default.json +++ b/public/translations/it/default.json @@ -399,5 +399,6 @@ "ban": "vietare", "timestamp": "marca temporale", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "video YouTube" } diff --git a/public/translations/ja/default.json b/public/translations/ja/default.json index 4c5133687..c9108e4b9 100644 --- a/public/translations/ja/default.json +++ b/public/translations/ja/default.json @@ -399,5 +399,6 @@ "ban": "ブロック", "timestamp": "タイムスタンプ", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "YouTube動画" } diff --git a/public/translations/ko/default.json b/public/translations/ko/default.json index 38fa563d7..ba6556c53 100644 --- a/public/translations/ko/default.json +++ b/public/translations/ko/default.json @@ -399,5 +399,6 @@ "ban": "차단", "timestamp": "타임스탬프", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "YouTube 동영상" } diff --git a/public/translations/mr/default.json b/public/translations/mr/default.json index b49f090a1..b5cd4a153 100644 --- a/public/translations/mr/default.json +++ b/public/translations/mr/default.json @@ -399,5 +399,6 @@ "ban": "प्रतिबंध", "timestamp": "टाइमस्टॅम्प", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "YouTube व्हिडिओ" } diff --git a/public/translations/nl/default.json b/public/translations/nl/default.json index 7c27d424e..1177756ea 100644 --- a/public/translations/nl/default.json +++ b/public/translations/nl/default.json @@ -399,5 +399,6 @@ "ban": "verbannen", "timestamp": "tijdstempel", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "YouTube-video" } diff --git a/public/translations/no/default.json b/public/translations/no/default.json index ae92db179..e5f06010a 100644 --- a/public/translations/no/default.json +++ b/public/translations/no/default.json @@ -399,5 +399,6 @@ "ban": "forbud", "timestamp": "tidsstempel", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "YouTube-video" } diff --git a/public/translations/pl/default.json b/public/translations/pl/default.json index 16531a36f..09686d6a4 100644 --- a/public/translations/pl/default.json +++ b/public/translations/pl/default.json @@ -399,5 +399,6 @@ "ban": "zbanować", "timestamp": "znacznik czasu", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "wideo YouTube" } diff --git a/public/translations/pt/default.json b/public/translations/pt/default.json index 8f3125515..495362dd3 100644 --- a/public/translations/pt/default.json +++ b/public/translations/pt/default.json @@ -399,5 +399,6 @@ "ban": "banir", "timestamp": "marca de tempo", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "vídeo do YouTube" } diff --git a/public/translations/ro/default.json b/public/translations/ro/default.json index 7e89022ce..20a6c8b84 100644 --- a/public/translations/ro/default.json +++ b/public/translations/ro/default.json @@ -399,5 +399,6 @@ "ban": "interzice", "timestamp": "marcă de timp", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "video YouTube" } diff --git a/public/translations/ru/default.json b/public/translations/ru/default.json index 3d40efd8b..ee59405e5 100644 --- a/public/translations/ru/default.json +++ b/public/translations/ru/default.json @@ -399,5 +399,6 @@ "ban": "блокировка", "timestamp": "временная метка", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "видео YouTube" } diff --git a/public/translations/sq/default.json b/public/translations/sq/default.json index aeeefa4fb..d957627ae 100644 --- a/public/translations/sq/default.json +++ b/public/translations/sq/default.json @@ -399,5 +399,6 @@ "ban": "ndalim", "timestamp": "vulë kohe", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "video YouTube" } diff --git a/public/translations/sv/default.json b/public/translations/sv/default.json index 9ccc27ce3..16461023a 100644 --- a/public/translations/sv/default.json +++ b/public/translations/sv/default.json @@ -399,5 +399,6 @@ "ban": "förbjud", "timestamp": "tidsstämpel", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "YouTube-video" } diff --git a/public/translations/te/default.json b/public/translations/te/default.json index 2beb4767e..858193088 100644 --- a/public/translations/te/default.json +++ b/public/translations/te/default.json @@ -399,5 +399,6 @@ "ban": "నిషేధం", "timestamp": "టైమ్‌స్టాంప్", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "YouTube వీడియో" } diff --git a/public/translations/th/default.json b/public/translations/th/default.json index f7107f17a..40d6aec46 100644 --- a/public/translations/th/default.json +++ b/public/translations/th/default.json @@ -399,5 +399,6 @@ "ban": "แบน", "timestamp": "แสตมป์เวลา", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "วิดีโอ YouTube" } diff --git a/public/translations/tr/default.json b/public/translations/tr/default.json index 2d84909d6..40ec38cb0 100644 --- a/public/translations/tr/default.json +++ b/public/translations/tr/default.json @@ -399,5 +399,6 @@ "ban": "yasakla", "timestamp": "zaman damgası", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "YouTube videosu" } diff --git a/public/translations/uk/default.json b/public/translations/uk/default.json index 06e09b046..bfc8b604b 100644 --- a/public/translations/uk/default.json +++ b/public/translations/uk/default.json @@ -399,5 +399,6 @@ "ban": "заблокувати", "timestamp": "часова мітка", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "відео YouTube" } diff --git a/public/translations/ur/default.json b/public/translations/ur/default.json index 47eee3172..0effd6bc1 100644 --- a/public/translations/ur/default.json +++ b/public/translations/ur/default.json @@ -399,5 +399,6 @@ "ban": "روک", "timestamp": "ٹائم سٹیمپ", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "YouTube ویڈیو" } diff --git a/public/translations/vi/default.json b/public/translations/vi/default.json index b99c911a4..3a8dc69dc 100644 --- a/public/translations/vi/default.json +++ b/public/translations/vi/default.json @@ -399,5 +399,6 @@ "ban": "cấm", "timestamp": "dấu thời gian", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "video YouTube" } diff --git a/public/translations/zh/default.json b/public/translations/zh/default.json index 96c68340f..a76b591e4 100644 --- a/public/translations/zh/default.json +++ b/public/translations/zh/default.json @@ -399,5 +399,6 @@ "ban": "封禁", "timestamp": "时间戳", "tag": "tag", - "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled." + "post_form_flash_upload_prompt": "Recommended SWF host: Catbox. Upload a .swf, then paste the direct https://files.catbox.moe/...swf link in Link. Other hosts must provide a direct HTTPS .swf URL with CORS enabled.", + "youtube_video": "YouTube 视频" } diff --git a/src/components/__tests__/post-community-address-compat.test.tsx b/src/components/__tests__/post-community-address-compat.test.tsx index c74b1898a..377238e18 100644 --- a/src/components/__tests__/post-community-address-compat.test.tsx +++ b/src/components/__tests__/post-community-address-compat.test.tsx @@ -151,6 +151,8 @@ vi.mock('../../lib/utils/media-utils', () => ({ getDisplayMediaInfoType: (type?: string) => type ?? 'unknown', getHasThumbnail: () => true, getMediaDimensions: () => '100x100', + getPostMediaTypeLabel: (_commentMediaInfo: unknown, resolvedType?: string) => resolvedType ?? '', + getYouTubeEmbedPostMediaFileLink: () => undefined, })); vi.mock('../../lib/utils/post-utils', () => ({ @@ -171,6 +173,7 @@ vi.mock('../../lib/utils/pending-approval-moderation', () => ({ vi.mock('../../lib/utils/url-utils', () => ({ isValidURL: () => true, + parseHttpUrl: (value: string) => new URL(value), })); vi.mock('../../lib/utils/view-utils', () => ({ diff --git a/src/components/comment-content/__tests__/comment-content.test.tsx b/src/components/comment-content/__tests__/comment-content.test.tsx index a9c86b334..2e0832a6d 100644 --- a/src/components/comment-content/__tests__/comment-content.test.tsx +++ b/src/components/comment-content/__tests__/comment-content.test.tsx @@ -408,11 +408,11 @@ describe('CommentContent', () => { cid: 'post-2', content: 'ignored', postCid: 'post-2', - reason: 'spam', + reason: 'duplicate of >>96', removed: true, }); expect(container.textContent).toContain('this_post_was_removed'); - expect(container.textContent).toContain('Reason: "spam"'); + expect(queryMarkdownText()).toEqual(['Reason: duplicate of >>96']); await renderContent({ cid: 'post-3', @@ -422,7 +422,7 @@ describe('CommentContent', () => { reason: 'self-delete', }); expect(container.textContent).toContain('user_deleted_this_post'); - expect(container.textContent).toContain('Reason: "self-delete"'); + expect(queryMarkdownText()).toEqual(['Reason: self-delete']); }); it('renders pending approval, ban details, and loading or failed states', async () => { @@ -442,6 +442,7 @@ describe('CommentContent', () => { expect(container.textContent).toContain('pending_mod_approval'); expect(container.textContent).toContain('pending-reason:rules violation'); + expect(queryMarkdownText()).toEqual(['queued body', 'pending-reason:rules violation']); const tooltip = container.querySelector('[data-testid="tooltip"]'); expect(tooltip?.getAttribute('title')).toContain('ban:short:music-posting.eth:2024-01-01 12:00:00'); diff --git a/src/components/comment-content/comment-content.tsx b/src/components/comment-content/comment-content.tsx index c522dc5b5..c7853c76c 100644 --- a/src/components/comment-content/comment-content.tsx +++ b/src/components/comment-content/comment-content.tsx @@ -156,7 +156,14 @@ const CommentContent = ({ const failedError = getFailedCommentError(resolvedPost); const failedErrorMessage = formatErrorMessageForDisplay(failedError); const shouldShowUnpublishedStateDetails = !cid && (!hasFailedState || Boolean(failedError)); + const reasonMessage = reason ? `${capitalize(t('reason'))}: ${reason}` : undefined; const pendingApprovalReason = pendingApproval ? reason?.trim() : undefined; + const pendingApprovalReasonMessage = pendingApprovalReason + ? t('pending_mod_approval_reason', { + reason: pendingApprovalReason, + interpolation: { escapeValue: false }, + }) + : undefined; const loadingString = (
@@ -193,21 +200,21 @@ const CommentContent = ({ {purged ? ( {capitalize(t('this_post_was_purged'))} ) : removed ? ( - reason ? ( + reasonMessage ? ( <> ({t('this_post_was_removed')})

- {`${capitalize(t('reason'))}: "${reason}"`} + {renderContent(reasonMessage)} ) : ( {capitalize(t('this_post_was_removed'))}. ) ) : deleted ? ( - reason ? ( + reasonMessage ? ( <> {t('user_deleted_this_post')}{' '} - {`${capitalize(t('reason'))}: "${reason}"`} + {renderContent(reasonMessage)} ) : ( {t('user_deleted_this_post')} @@ -220,18 +227,13 @@ const CommentContent = ({

({t('pending_mod_approval')}) - {pendingApprovalReason && ( + {pendingApprovalReasonMessage ? ( <>

- - {t('pending_mod_approval_reason', { - reason: pendingApprovalReason, - interpolation: { escapeValue: false }, - })} - + {renderContent(pendingApprovalReasonMessage)} - )} + ) : null} )} {((!isInPostView && content?.length > 1000 && !showFullComment) || (isInPostView && content?.length > 2000 && !showFullComment)) && !isPrivilegedAuthor && ( diff --git a/src/components/comment-media/__tests__/comment-media.test.tsx b/src/components/comment-media/__tests__/comment-media.test.tsx index 6a5bc906c..fcd73faf5 100644 --- a/src/components/comment-media/__tests__/comment-media.test.tsx +++ b/src/components/comment-media/__tests__/comment-media.test.tsx @@ -295,6 +295,21 @@ describe('CommentMedia', () => { expect(setShowThumbnailMock).toHaveBeenCalledWith(false); }); + it('renders a youtube thumbnail before the embed is opened', async () => { + await renderMedia({ + commentMediaInfo: { + patternThumbnailUrl: 'https://img.youtube.com/vi/abc123/0.jpg', + type: 'iframe', + url: 'https://www.youtube.com/watch?v=abc123', + }, + setShowThumbnail: setShowThumbnailMock, + showThumbnail: true, + }); + + expect(container.querySelector('img[src="https://img.youtube.com/vi/abc123/0.jpg"]')).toBeTruthy(); + expect(container.querySelector('[data-testid="embed"]')).toBeNull(); + }); + it('renders the expanded embed view with a close button on mobile', async () => { testState.isMobile = true; diff --git a/src/components/embed/__tests__/embed.test.tsx b/src/components/embed/__tests__/embed.test.tsx index 7998bda11..7444cecdd 100644 --- a/src/components/embed/__tests__/embed.test.tsx +++ b/src/components/embed/__tests__/embed.test.tsx @@ -3,7 +3,7 @@ import { createElement } from 'react'; import { createRoot, type Root } from 'react-dom/client'; import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import Embed from '../embed'; -import { canEmbed } from '../embed-utils'; +import { canEmbed, getYouTubeVideoId } from '../embed-utils'; (globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true; const act = (React as { act?: (cb: () => void | Promise) => void | Promise }).act as (cb: () => void | Promise) => void | Promise; @@ -56,6 +56,18 @@ describe('Embed', () => { expect(container.innerHTML).toBe(''); }); + it('extracts youtube video ids for standard, short, and invidious urls', () => { + expect(getYouTubeVideoId(new URL('https://www.youtube.com/watch?v=abc123'))).toBe('abc123'); + expect(getYouTubeVideoId(new URL('https://m.youtube.com/watch?v=mobile123'))).toBe('mobile123'); + expect(getYouTubeVideoId(new URL('https://music.youtube.com/watch?v=music123'))).toBe('music123'); + expect(getYouTubeVideoId(new URL('https://youtu.be/short123'))).toBe('short123'); + expect(getYouTubeVideoId(new URL('https://www.youtube.com/shorts/short456'))).toBe('short456'); + expect(getYouTubeVideoId(new URL('https://yewtu.be/invidious789'))).toBe('invidious789'); + expect(getYouTubeVideoId(new URL('https://m.youtube.com/@channel'))).toBeNull(); + expect(getYouTubeVideoId(new URL('https://music.youtube.com/channel/UC123'))).toBeNull(); + expect(getYouTubeVideoId(new URL('https://www.youtube.com/playlist?list=PL123'))).toBeNull(); + }); + it('reports embeddable hosts through canEmbed and rejects unsupported reddit pages', () => { expect(canEmbed(new URL('https://www.youtube.com/watch?v=abc123'))).toBe(true); expect(canEmbed(new URL('https://yt.example/watch?v=abc123'))).toBe(true); diff --git a/src/components/embed/embed-utils.ts b/src/components/embed/embed-utils.ts index 07dd2d2a5..f9fdfc4e5 100644 --- a/src/components/embed/embed-utils.ts +++ b/src/components/embed/embed-utils.ts @@ -1,3 +1,5 @@ +const STANDARD_YOUTUBE_HOSTS = new Set(['youtube.com', 'www.youtube.com', 'm.youtube.com', 'music.youtube.com', 'youtu.be', 'www.youtu.be']); + export const youtubeHosts = new Set([ 'youtube.com', 'www.youtube.com', @@ -46,6 +48,35 @@ const canEmbedHosts = new Set([ ...spotifyHosts, ]); +export const getYouTubeVideoId = (parsedUrl: URL): string | null => { + if (parsedUrl.searchParams.has('list') && !parsedUrl.searchParams.get('v') && !parsedUrl.host.includes('youtu.be') && !parsedUrl.pathname.includes('/shorts/')) { + return null; + } + + const videoIdFromQuery = parsedUrl.searchParams.get('v'); + if (videoIdFromQuery) { + return videoIdFromQuery; + } + + if (parsedUrl.host.includes('youtu.be')) { + return parsedUrl.pathname.slice(1).split('/')[0] || null; + } + + if (parsedUrl.pathname.includes('/shorts/')) { + return parsedUrl.pathname.split('/shorts/')[1]?.split('/')[0] || null; + } + + const isInvidious = !STANDARD_YOUTUBE_HOSTS.has(parsedUrl.host) && (youtubeHosts.has(parsedUrl.host) || parsedUrl.host.startsWith('yt.')); + if (isInvidious) { + if (parsedUrl.pathname.startsWith('/watch')) { + return parsedUrl.searchParams.get('v'); + } + return parsedUrl.pathname.split('/').filter(Boolean).pop() || null; + } + + return null; +}; + export const canEmbed = (parsedUrl: URL): boolean => { if (xHosts.has(parsedUrl.host)) { return Boolean(getXTweetId(parsedUrl)); diff --git a/src/components/embed/embed.tsx b/src/components/embed/embed.tsx index 009646e50..4f7260d7e 100644 --- a/src/components/embed/embed.tsx +++ b/src/components/embed/embed.tsx @@ -10,6 +10,7 @@ import { streamableHosts, tiktokHosts, twitchHosts, + getYouTubeVideoId, xHosts, youtubeHosts, } from './embed-utils'; @@ -66,28 +67,11 @@ const remoteEmbedSandbox = `${srcDocSandbox} allow-forms allow-presentation allo const YoutubeEmbed = ({ parsedUrl }: EmbedComponentProps) => { let embedSrc = ''; - const isInvidious = parsedUrl.host !== 'youtube.com' && parsedUrl.host !== 'www.youtube.com' && parsedUrl.host !== 'youtu.be' && parsedUrl.host !== 'www.youtu.be'; - - if (parsedUrl.searchParams.has('list')) { + if (parsedUrl.searchParams.has('list') && !getYouTubeVideoId(parsedUrl)) { const playlistId = parsedUrl.searchParams.get('list'); embedSrc = `https://www.youtube.com/embed/videoseries?list=${playlistId}`; } else { - let videoId = parsedUrl.searchParams.get('v'); - - if (!videoId) { - if (parsedUrl.host.includes('youtu.be')) { - videoId = parsedUrl.pathname.substring(1); - } else if (parsedUrl.pathname.includes('/shorts/')) { - videoId = parsedUrl.pathname.split('/shorts/')[1]; - } else if (isInvidious) { - if (parsedUrl.pathname.startsWith('/watch')) { - videoId = parsedUrl.searchParams.get('v'); - } else { - videoId = parsedUrl.pathname.split('/').pop() || null; - } - } - } - + const videoId = getYouTubeVideoId(parsedUrl); if (videoId) { embedSrc = `https://www.youtube.com/embed/${videoId}`; } diff --git a/src/components/embed/index.ts b/src/components/embed/index.ts index 7ca087731..da9ba2a87 100644 --- a/src/components/embed/index.ts +++ b/src/components/embed/index.ts @@ -1,2 +1,2 @@ export { default } from './embed'; -export { canEmbed } from './embed-utils'; +export { canEmbed, getYouTubeVideoId } from './embed-utils'; diff --git a/src/components/markdown/__tests__/markdown.test.tsx b/src/components/markdown/__tests__/markdown.test.tsx index ae88860d8..00ee866a9 100644 --- a/src/components/markdown/__tests__/markdown.test.tsx +++ b/src/components/markdown/__tests__/markdown.test.tsx @@ -24,7 +24,9 @@ const testState = vi.hoisted(() => ({ cidToNumber: {} as Record, internalPathByHref: {} as Record, isMobile: false, - mediaInfoByHref: {} as Record, + mediaInfoByHref: {} as Record, + floatingMediaProps: null as { showThumbnail?: boolean } | null, + floatingOnOpenChange: null as ((open: boolean) => void) | null, numberToCid: {} as Record>, unavailableCids: new Set(), })); @@ -42,20 +44,32 @@ vi.mock('@floating-ui/react', () => ({ shift: () => ({}), size: () => ({}), useDismiss: () => ({}), - useFloating: () => ({ - context: {}, - floatingStyles: {}, - refs: { - setFloating: () => undefined, - setReference: () => undefined, - }, - update: () => undefined, - }), + useFloating: ({ onOpenChange, open }: { onOpenChange?: (open: boolean) => void; open?: boolean }) => { + testState.floatingOnOpenChange = onOpenChange ?? null; + return { + context: {}, + floatingStyles: {}, + open, + onOpenChange, + refs: { + setFloating: () => undefined, + setReference: () => undefined, + }, + update: () => undefined, + }; + }, useFocus: () => ({}), - useHover: () => ({}), - useInteractions: () => ({ + useHover: () => ({ + getReferenceProps: (props?: Record) => ({ + ...props, + onMouseEnter: () => testState.floatingOnOpenChange?.(true), + onMouseLeave: () => testState.floatingOnOpenChange?.(false), + }), + }), + useInteractions: (interactions: Array<{ getReferenceProps?: (props?: Record) => Record }>) => ({ getFloatingProps: (props?: Record) => props || {}, - getReferenceProps: (props?: Record) => props || {}, + getReferenceProps: (props?: Record) => + interactions.reduce((mergedProps, interaction) => interaction.getReferenceProps?.(mergedProps) || mergedProps, props || {}), }), })); @@ -75,8 +89,13 @@ vi.mock('../../../hooks/use-is-mobile', () => ({ })); vi.mock('../../../lib/utils/media-utils', () => ({ - getHasThumbnail: (linkMediaInfo?: { thumbnail?: string; type?: string }, href?: string) => - Boolean(linkMediaInfo?.thumbnail || linkMediaInfo?.type === 'image' || (href && testState.mediaInfoByHref[href]?.thumbnail)), + getHasThumbnail: (linkMediaInfo?: { patternThumbnailUrl?: string; thumbnail?: string; type?: string }, href?: string) => + Boolean( + linkMediaInfo?.thumbnail || + linkMediaInfo?.patternThumbnailUrl || + linkMediaInfo?.type === 'image' || + (href && (testState.mediaInfoByHref[href]?.thumbnail || testState.mediaInfoByHref[href]?.patternThumbnailUrl)), + ), getLinkMediaInfo: (href: string) => testState.mediaInfoByHref[href], })); @@ -139,8 +158,28 @@ vi.mock('../../../stores/use-post-number-store', () => ({ })); vi.mock('../../comment-media', () => ({ - default: ({ commentMediaInfo }: { commentMediaInfo?: { type?: string; url?: string } }) => - createElement('div', { 'data-testid': 'comment-media' }, `${commentMediaInfo?.type}:${commentMediaInfo?.url}`), + default: ({ + commentMediaInfo, + isFloatingEmbed, + showThumbnail, + }: { + commentMediaInfo?: { type?: string; url?: string }; + isFloatingEmbed?: boolean; + showThumbnail?: boolean; + }) => { + if (isFloatingEmbed) { + testState.floatingMediaProps = { showThumbnail }; + } + return createElement( + 'div', + { + 'data-floating': String(Boolean(isFloatingEmbed)), + 'data-show-thumbnail': String(showThumbnail), + 'data-testid': 'comment-media', + }, + `${commentMediaInfo?.type}:${commentMediaInfo?.url}`, + ); + }, })); vi.mock('../../embed', () => ({ @@ -198,6 +237,8 @@ describe('Markdown', () => { testState.internalPathByHref = {}; testState.isMobile = false; testState.mediaInfoByHref = {}; + testState.floatingMediaProps = null; + testState.floatingOnOpenChange = null; testState.numberToCid = {}; testState.unavailableCids = new Set(); @@ -460,6 +501,33 @@ describe('Markdown', () => { expect(lazyLinks.map((node) => node.textContent)).toEqual(['>>42', '>>>/fit/77']); }); + it('shows youtube thumbnails in the floating hover preview instead of loading the iframe', async () => { + testState.embeddableHosts = new Set(['www.youtube.com']); + testState.mediaInfoByHref = { + 'https://www.youtube.com/watch?v=abc123': { + patternThumbnailUrl: 'https://img.youtube.com/vi/abc123/0.jpg', + type: 'iframe', + url: 'https://www.youtube.com/watch?v=abc123', + }, + }; + + await renderMarkdown({ + content: 'https://www.youtube.com/watch?v=abc123', + }); + + const embedButton = Array.from(container.querySelectorAll('button')).find((node) => node.textContent === 'embed'); + expect(embedButton).toBeTruthy(); + + await act(async () => { + testState.floatingOnOpenChange?.(true); + }); + + const floatingMedia = container.querySelector('[data-floating="true"]'); + expect(floatingMedia).toBeTruthy(); + expect(floatingMedia?.getAttribute('data-show-thumbnail')).toBe('true'); + expect(testState.floatingMediaProps?.showThumbnail).toBe(true); + }); + it('toggles inline media embeds for embeddable links outside catalog view', async () => { testState.mediaInfoByHref = { 'https://cdn.example/image.png': { diff --git a/src/components/markdown/markdown.tsx b/src/components/markdown/markdown.tsx index 6a2dfd272..55b2a8f63 100644 --- a/src/components/markdown/markdown.tsx +++ b/src/components/markdown/markdown.tsx @@ -123,8 +123,8 @@ const ContentLinkEmbed = ({ children, href, linkMediaInfo }: ContentLinkEmbedPro disableToggle={true} isFloatingEmbed={true} isReply={false} - setShowThumbnail={setShowMedia} - showThumbnail={false} + setShowThumbnail={() => {}} + showThumbnail={true} />
)} diff --git a/src/components/post-desktop/post-desktop.tsx b/src/components/post-desktop/post-desktop.tsx index bd5766302..ea6b6e033 100644 --- a/src/components/post-desktop/post-desktop.tsx +++ b/src/components/post-desktop/post-desktop.tsx @@ -5,11 +5,11 @@ import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso'; import { Comment, useEditedComment, useReplies, useAccount } from '@bitsocial/bitsocial-react-hooks'; import getShortAddress from '../../lib/get-short-address'; import styles from '../../views/post/post.module.css'; -import { CommentMediaInfo, getDisplayMediaInfoType, getHasThumbnail, getMediaDimensions } from '../../lib/utils/media-utils'; +import { CommentMediaInfo, getHasThumbnail, getMediaDimensions, getPostMediaTypeLabel, getYouTubeEmbedPostMediaFileLink } from '../../lib/utils/media-utils'; import { hashStringToColor, getTextColorForBackground } from '../../lib/utils/post-utils'; import { getFormattedDate, getFormattedTimeAgo } from '../../lib/utils/time-utils'; import { approvePendingCommentModeration, isPendingApprovalRejected, rejectPendingCommentModeration } from '../../lib/utils/pending-approval-moderation'; -import { isValidURL } from '../../lib/utils/url-utils'; +import { isValidURL, parseHttpUrl } from '../../lib/utils/url-utils'; import { isAllView, isModQueueView, isModView, isPendingPostView, isPostPageView, isSubscriptionsView } from '../../lib/utils/view-utils'; import { formatUserIDForDisplay, truncateWithEllipsisInMiddle } from '../../lib/utils/string-utils'; import useModQueueStore from '../../stores/use-mod-queue-store'; @@ -642,12 +642,16 @@ const PostMedia = ({ type = 'static gif'; } - const embedUrl = url && new URL(url); + const youtubeFileLink = getYouTubeEmbedPostMediaFileLink(commentMediaInfo); + const fileLinkUrl = youtubeFileLink ?? url; + const embedUrl = url ? parseHttpUrl(url) : null; const [showThumbnail, setShowThumbnail] = useState(true); const mediaDimensions = getMediaDimensions(commentMediaInfo); const directoryEntry = findDirectoryByAddress(directories, communityAddress); const requirePostLinkIsMedia = directoryEntry?.features?.requirePostLinkIsMedia === true; + const fileLabel = youtubeFileLink || requirePostLinkIsMedia ? t('file') : t('link'); + const mediaTypeLabel = type ? lowerCase(getPostMediaTypeLabel(commentMediaInfo, type, t)) : ''; const boardPath = communityAddress ? getBoardPath(communityAddress, directories) : undefined; const displayBoardPath = boardPath && communityAddress && boardPath !== communityAddress @@ -666,10 +670,11 @@ const PostMedia = ({ {t('board')}: {displayBoardPath}{' '} )} - {requirePostLinkIsMedia ? t('file') : t('link')}:{' '} - + {fileLabel}:{' '} + {(() => { if (spoiler) return capitalize(t('spoiler')); + if (youtubeFileLink) return truncateWithEllipsisInMiddle(youtubeFileLink); if (requirePostLinkIsMedia && url) { try { const pathParts = new URL(url).pathname.split('/'); @@ -677,10 +682,10 @@ const PostMedia = ({ if (filename && /\.\w+$/.test(filename)) return truncateWithEllipsisInMiddle(filename); } catch {} } - return truncateWithEllipsisInMiddle(url ?? ''); + return truncateWithEllipsisInMiddle(fileLinkUrl ?? ''); })()} {' '} - ({type && lowerCase(getDisplayMediaInfoType(type, t))} + ({mediaTypeLabel} {mediaDimensions && `, ${mediaDimensions}`}) {!showThumbnail && (type === 'iframe' || type === 'video' || type === 'audio') && ( diff --git a/src/components/post-form/__tests__/post-form.test.tsx b/src/components/post-form/__tests__/post-form.test.tsx index 884f26fe4..54b480249 100644 --- a/src/components/post-form/__tests__/post-form.test.tsx +++ b/src/components/post-form/__tests__/post-form.test.tsx @@ -444,6 +444,7 @@ describe('PostForm', () => { testState.directories = [ { address: 'music-posting.eth', features: {}, title: '/mu/ - Music' }, { address: 'politically-incorrect.bso', directoryCode: 'pol', features: { hasFlags: true }, title: '/pol/ - Politically Incorrect' }, + { address: 'sports-posting.bso', directoryCode: 'sp', features: { hasFlags: true }, title: '/sp/ - Sports' }, { address: 'random-nsfw.bso', features: {}, title: '/b/ - Random' }, { address: 'flash-posting.bso', @@ -699,6 +700,30 @@ describe('PostForm', () => { }); }); + it('publishes geographic location on /sp/ without showing a flag field', async () => { + testState.resolvedCommunityAddress = 'sports-posting.bso'; + + await renderPostForm('/sp'); + await clickByText(container, 'start_new_thread'); + + const table = container.querySelector('table'); + const flagSelect = table?.querySelector('select[aria-label="flag"]'); + const textarea = table?.querySelector('textarea'); + + expect(flagSelect).toBeNull(); + + await dispatchInput(textarea as HTMLTextAreaElement, 'sports post'); + await clickByText(table as HTMLTableElement, 'post'); + + expect(testState.publishPostMock).toHaveBeenCalledWith({ + content: 'sports post', + challengeRequest: { + challengeAnswers: ['bitsocial-flags:5chan:flag:country:auto'], + }, + flairs: [{ type: 'country', code: 'auto', text: 'flag:country:auto' }], + }); + }); + it('publishes selected political flags from the post form', async () => { testState.resolvedCommunityAddress = 'politically-incorrect.bso'; diff --git a/src/components/post-form/post-form.tsx b/src/components/post-form/post-form.tsx index a550bf400..c8c1a0ed2 100644 --- a/src/components/post-form/post-form.tsx +++ b/src/components/post-form/post-form.tsx @@ -391,7 +391,7 @@ const PostFormFields = ({ {t('tag')} - {flashTagOptions.map((option) => (