mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-10 12:42:27 +09:00
Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a208b56354 | ||
|
|
71be6c1de4 | ||
|
|
eae905b1da | ||
|
|
10cd4f96a4 | ||
|
|
9d74daf8ad | ||
|
|
6f344def93 | ||
|
|
72f9f9c396 | ||
|
|
c8755885d4 | ||
|
|
12d503d4c5 | ||
|
|
2f6201bcbd | ||
|
|
ec681e6061 |
@@ -23,6 +23,10 @@ on:
|
||||
required: false
|
||||
type: string
|
||||
default: ""
|
||||
stale_apply_record:
|
||||
description: Before each update, leave behind an hour-old record of an update that never installed (passes only when the installed versions retry it)
|
||||
type: boolean
|
||||
default: false
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/desktop-windows-release-check.yaml
|
||||
@@ -53,6 +57,7 @@ jobs:
|
||||
VERSION: ${{ inputs.version || '2026.1009.20411' }}
|
||||
EXPECT_FAILURE: ${{ github.event_name == 'pull_request' && 'true' || inputs.expect_failure }}
|
||||
UPDATE_FROM: ${{ inputs.update_from || '' }}
|
||||
STALE_APPLY_RECORD: ${{ inputs.stale_apply_record && 'true' || 'false' }}
|
||||
ARCH: ${{ matrix.arch }}
|
||||
steps:
|
||||
- name: Checkout source
|
||||
@@ -108,6 +113,13 @@ jobs:
|
||||
Get-Process | Where-Object { $_.Path -like "$installRoot*" } | Stop-Process -Force -ErrorAction SilentlyContinue
|
||||
$exe = Get-ChildItem -Path (Join-Path $installRoot 'current') -Filter 'Fluxer*.exe' | Where-Object { $_.Name -notlike '*_ExecutionStub.exe' } | Select-Object -First 1
|
||||
if ($null -eq $exe) { $failures += "$from did not install"; continue }
|
||||
if ($env:STALE_APPLY_RECORD -eq 'true') {
|
||||
$dataRoot = Split-Path (Split-Path $logPath -Parent) -Parent
|
||||
New-Item -ItemType Directory -Force -Path $dataRoot | Out-Null
|
||||
$attemptedAt = [DateTimeOffset]::UtcNow.AddHours(-1).ToUnixTimeMilliseconds()
|
||||
Set-Content -Path (Join-Path $dataRoot 'update-apply-state.json') -Value "{`"version`":`"$env:VERSION`",`"attemptedAt`":$attemptedAt}" -NoNewline
|
||||
Write-Host "left a stale apply record for $env:VERSION"
|
||||
}
|
||||
Start-Process -FilePath $exe.FullName -ArgumentList '--disable-gpu'
|
||||
$deadline = (Get-Date).AddMinutes(8)
|
||||
$reported = $null
|
||||
|
||||
@@ -130,6 +130,9 @@ describe('DELETE /admin/reports/:report_id', () => {
|
||||
const profileKey = `reports/${reportId}/profile/user_avatar/abc${id}`;
|
||||
await harness.storageService.uploadObject({bucket: REPORTS_BUCKET, key: attachmentKey, body: new Uint8Array([1])});
|
||||
await harness.storageService.uploadObject({bucket: REPORTS_BUCKET, key: profileKey, body: new Uint8Array([2])});
|
||||
const uploadedAt = new Date(Date.now() - ms('1 hour'));
|
||||
harness.storageService.setObjectLastModified(REPORTS_BUCKET, attachmentKey, uploadedAt);
|
||||
harness.storageService.setObjectLastModified(REPORTS_BUCKET, profileKey, uploadedAt);
|
||||
const report = await repository.createReport({
|
||||
...Object.fromEntries(IAR_SUBMISSION_COLUMNS.map((column) => [column, null])),
|
||||
report_id: id,
|
||||
|
||||
@@ -47,7 +47,6 @@ export const CONTENT_I18N_MESSAGES = {
|
||||
'report_flow.label.csam': 'Real or AI-generated images or videos of child sexual abuse',
|
||||
'report_flow.label.discovery_listing': 'Discovery listing',
|
||||
'report_flow.label.dislike': "It's just not for me",
|
||||
'report_flow.label.dsa': "Content that's illegal in the EU (Digital Services Act)",
|
||||
'report_flow.label.eating_disorder_promotion': 'Encouraging disordered eating',
|
||||
'report_flow.label.eating_disorder_promotion_profile': 'Their profile promotes eating disorders',
|
||||
'report_flow.label.email': 'Email address',
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_AR_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "صور أو مقاطع فيديو حقيقية أو مولدة بالذكاء الاصطناعي تُظهر اعتداءً جنسيًا على الأطفال",
|
||||
"report_flow.label.discovery_listing": "قائمة الاكتشاف",
|
||||
"report_flow.label.dislike": "هذا ببساطة لا يناسبني",
|
||||
"report_flow.label.dsa": "محتوى غير قانوني في الاتحاد الأوروبي (قانون الخدمات الرقمية)",
|
||||
"report_flow.label.eating_disorder_promotion": "تشجيع سلوكيات الأكل المضطربة",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "ملفهم الشخصي يروج لاضطرابات الأكل",
|
||||
"report_flow.label.email": "عنوان البريد الإلكتروني",
|
||||
|
||||
@@ -34,10 +34,6 @@
|
||||
"msgctxt": "report_flow.label.dislike",
|
||||
"msgid": "It's just not for me"
|
||||
},
|
||||
{
|
||||
"msgctxt": "report_flow.label.dsa",
|
||||
"msgid": "Content that's illegal in the EU (Digital Services Act)"
|
||||
},
|
||||
{
|
||||
"msgctxt": "report_flow.label.eating_disorder_promotion",
|
||||
"msgid": "Encouraging disordered eating"
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_BG_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "Реални или генерирани от изкуствен интелект изображения или видеоклипове на сексуално насилие над деца",
|
||||
"report_flow.label.discovery_listing": "Списък за откриване",
|
||||
"report_flow.label.dislike": "Просто не е за мен",
|
||||
"report_flow.label.dsa": "Съдържание, което е незаконно в ЕС (Акт за цифровите услуги)",
|
||||
"report_flow.label.eating_disorder_promotion": "Насърчаване на хранителни разстройства",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Профилът им насърчава хранителни разстройства",
|
||||
"report_flow.label.email": "Имейл адрес",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_CS_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "Skutečné nebo pomocí AI vytvořené obrázky či videa sexuálního zneužívání dětí",
|
||||
"report_flow.label.discovery_listing": "Záznam v seznamu objevování",
|
||||
"report_flow.label.dislike": "Prostě to není pro mě",
|
||||
"report_flow.label.dsa": "Obsah, který je v EU nelegální (akt o digitálních službách)",
|
||||
"report_flow.label.eating_disorder_promotion": "Nabádání k poruchám příjmu potravy",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Jejich profil propaguje poruchy příjmu potravy",
|
||||
"report_flow.label.email": "E-mailová adresa",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_DA_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "Ægte eller AI-genererede billeder eller videoer af seksuelle overgreb mod børn",
|
||||
"report_flow.label.discovery_listing": "Opslag i Opdag",
|
||||
"report_flow.label.dislike": "Det er bare ikke noget for mig",
|
||||
"report_flow.label.dsa": "Indhold, der er ulovligt i EU (retsakten om digitale tjenester, DSA)",
|
||||
"report_flow.label.eating_disorder_promotion": "Opfordrer til spiseforstyrrelser",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Deres profil fremmer spiseforstyrrelser",
|
||||
"report_flow.label.email": "E-mailadresse",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_DE_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "Reale oder KI-generierte Bilder oder Videos von sexuellem Kindesmissbrauch",
|
||||
"report_flow.label.discovery_listing": "Eintrag in „Entdecken“",
|
||||
"report_flow.label.dislike": "Das ist einfach nichts für mich",
|
||||
"report_flow.label.dsa": "Inhalte, die in der EU illegal sind (Gesetz über digitale Dienste)",
|
||||
"report_flow.label.eating_disorder_promotion": "Zu gestörtem Essverhalten ermutigen",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Das Profil der Person fördert Essstörungen",
|
||||
"report_flow.label.email": "E-Mail-Adresse",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_EL_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "Πραγματικές ή δημιουργημένες με AI εικόνες ή βίντεο σεξουαλικής κακοποίησης παιδιών",
|
||||
"report_flow.label.discovery_listing": "Καταχώριση ανακάλυψης",
|
||||
"report_flow.label.dislike": "Απλά δεν μου ταιριάζει",
|
||||
"report_flow.label.dsa": "Περιεχόμενο που είναι παράνομο στην ΕΕ (πράξη για τις ψηφιακές υπηρεσίες, DSA)",
|
||||
"report_flow.label.eating_disorder_promotion": "Ενθάρρυνση διατροφικών διαταραχών",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Το προφίλ τους προωθεί διατροφικές διαταραχές",
|
||||
"report_flow.label.email": "Διεύθυνση email",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_EN_GB_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "Real or AI-generated images or videos of child sexual abuse",
|
||||
"report_flow.label.discovery_listing": "Discovery listing",
|
||||
"report_flow.label.dislike": "It's just not for me",
|
||||
"report_flow.label.dsa": "Content that's illegal in the EU (Digital Services Act)",
|
||||
"report_flow.label.eating_disorder_promotion": "Encouraging disordered eating",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Their profile promotes eating disorders",
|
||||
"report_flow.label.email": "Email address",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_ES_419_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "Imágenes o videos reales o generados por IA de abuso sexual infantil",
|
||||
"report_flow.label.discovery_listing": "Listado en Descubrir",
|
||||
"report_flow.label.dislike": "Simplemente no es para mí",
|
||||
"report_flow.label.dsa": "Contenido ilegal en la UE (Reglamento de Servicios Digitales)",
|
||||
"report_flow.label.eating_disorder_promotion": "Fomentar trastornos alimenticios",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Su perfil promueve trastornos alimenticios",
|
||||
"report_flow.label.email": "Dirección de correo electrónico",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_ES_ES_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "Imágenes o vídeos reales o generados por IA de abuso sexual infantil",
|
||||
"report_flow.label.discovery_listing": "Ficha en Descubrir",
|
||||
"report_flow.label.dislike": "Simplemente no es para mí",
|
||||
"report_flow.label.dsa": "Contenido ilegal en la UE (Reglamento de Servicios Digitales)",
|
||||
"report_flow.label.eating_disorder_promotion": "Fomentar trastornos de la conducta alimentaria",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Su perfil promueve trastornos de la conducta alimentaria",
|
||||
"report_flow.label.email": "Dirección de correo electrónico",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_FI_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "Aitoja tai tekoälyn luomia kuvia tai videoita lapsiin kohdistuvasta seksuaalisesta hyväksikäytöstä",
|
||||
"report_flow.label.discovery_listing": "Löydä-listaus",
|
||||
"report_flow.label.dislike": "Se ei vain ole minun juttuni",
|
||||
"report_flow.label.dsa": "Laiton sisältö EU:ssa (digipalvelusäädös, DSA)",
|
||||
"report_flow.label.eating_disorder_promotion": "Syömishäiriöihin kannustaminen",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Hänen profiilinsa edistää syömishäiriöitä",
|
||||
"report_flow.label.email": "Sähköpostiosoite",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_FR_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "Images ou vidéos réelles ou générées par IA représentant des abus sexuels sur des enfants",
|
||||
"report_flow.label.discovery_listing": "Fiche dans Découverte",
|
||||
"report_flow.label.dislike": "Ce n'est pas pour moi",
|
||||
"report_flow.label.dsa": "Contenu illégal dans l'UE (règlement sur les services numériques, DSA)",
|
||||
"report_flow.label.eating_disorder_promotion": "Encourager les troubles du comportement alimentaire",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Son profil fait la promotion des troubles du comportement alimentaire",
|
||||
"report_flow.label.email": "Adresse e-mail",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_HE_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "תמונות או סרטונים של פגיעה מינית בילדים, אמיתיים או שנוצרו באמצעות AI",
|
||||
"report_flow.label.discovery_listing": "רישום בגילוי",
|
||||
"report_flow.label.dislike": "זה פשוט לא בשבילי",
|
||||
"report_flow.label.dsa": "תוכן בלתי חוקי באיחוד האירופי (חוק השירותים הדיגיטליים, DSA)",
|
||||
"report_flow.label.eating_disorder_promotion": "עידוד הפרעות אכילה",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "הפרופיל שלהם מקדם הפרעות אכילה",
|
||||
"report_flow.label.email": "כתובת אימייל",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_HI_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "बाल यौन शोषण की असली या AI से बनाई गई तस्वीरें या वीडियो",
|
||||
"report_flow.label.discovery_listing": "डिस्कवरी लिस्टिंग",
|
||||
"report_flow.label.dislike": "यह बस मेरे लिए नहीं है",
|
||||
"report_flow.label.dsa": "यूरोपीय संघ में गैर-कानूनी सामग्री (डिजिटल सेवा अधिनियम)",
|
||||
"report_flow.label.eating_disorder_promotion": "खाने संबंधी विकार वाली आदतों को बढ़ावा देना",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "उनकी प्रोफ़ाइल खाने संबंधी विकारों को बढ़ावा देती है",
|
||||
"report_flow.label.email": "ईमेल पता",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_HR_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "Stvarne ili AI-generirane slike ili videozapisi seksualnog zlostavljanja djece",
|
||||
"report_flow.label.discovery_listing": "Unos u Otkrivanju",
|
||||
"report_flow.label.dislike": "Jednostavno mi ne odgovara",
|
||||
"report_flow.label.dsa": "Sadržaj koji je nezakonit u EU-u (Akt o digitalnim uslugama)",
|
||||
"report_flow.label.eating_disorder_promotion": "Poticanje poremećaja hranjenja",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Njihov profil promiče poremećaje hranjenja",
|
||||
"report_flow.label.email": "Adresa e-pošte",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_HU_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "Gyermekek szexuális bántalmazását ábrázoló valódi vagy mesterséges intelligencia által generált képek vagy videók",
|
||||
"report_flow.label.discovery_listing": "Listázás a Felfedezésben",
|
||||
"report_flow.label.dislike": "Egyszerűen nem nekem való",
|
||||
"report_flow.label.dsa": "Az EU-ban illegális tartalom (digitális szolgáltatásokról szóló rendelet, DSA)",
|
||||
"report_flow.label.eating_disorder_promotion": "Kóros étkezési szokásokra buzdítás",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "A profilja evészavarokat népszerűsít",
|
||||
"report_flow.label.email": "E-mail-cím",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_ID_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "Gambar atau video kekerasan seksual terhadap anak, baik yang asli maupun buatan AI",
|
||||
"report_flow.label.discovery_listing": "Listing di Discovery",
|
||||
"report_flow.label.dislike": "Ini tidak cocok untuk saya",
|
||||
"report_flow.label.dsa": "Konten yang ilegal di UE (Undang-Undang Layanan Digital/DSA)",
|
||||
"report_flow.label.eating_disorder_promotion": "Mendorong perilaku makan yang terganggu",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Profil mereka mempromosikan gangguan makan",
|
||||
"report_flow.label.email": "Alamat email",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_IT_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "Immagini o video reali o generati da IA di abusi sessuali su minori",
|
||||
"report_flow.label.discovery_listing": "Elenco in Scopri",
|
||||
"report_flow.label.dislike": "Non fa per me",
|
||||
"report_flow.label.dsa": "Contenuti illegali nell'UE (Regolamento sui servizi digitali, DSA)",
|
||||
"report_flow.label.eating_disorder_promotion": "Incoraggiare disturbi alimentari",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Il suo profilo promuove disturbi alimentari",
|
||||
"report_flow.label.email": "Indirizzo e-mail",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_JA_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "児童性的虐待の画像・動画(実在のもの、またはAI生成のもの)",
|
||||
"report_flow.label.discovery_listing": "「見つける」の掲載内容",
|
||||
"report_flow.label.dislike": "自分には合わない",
|
||||
"report_flow.label.dsa": "EUで違法なコンテンツ(デジタルサービス法、DSA)",
|
||||
"report_flow.label.eating_disorder_promotion": "摂食障害的な食行動を促している",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "プロフィールが摂食障害を助長している",
|
||||
"report_flow.label.email": "メールアドレス",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_KO_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "아동 성착취물(실제 또는 AI로 생성된 이미지 또는 동영상)",
|
||||
"report_flow.label.discovery_listing": "디스커버리 목록",
|
||||
"report_flow.label.dislike": "그냥 내 취향이 아닙니다",
|
||||
"report_flow.label.dsa": "EU에서 불법인 콘텐츠(디지털 서비스법, DSA)",
|
||||
"report_flow.label.eating_disorder_promotion": "섭식 장애 행동 조장",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "프로필에서 섭식 장애를 조장합니다",
|
||||
"report_flow.label.email": "이메일 주소",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_LT_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "Tikri ar dirbtinio intelekto sukurti vaikų seksualinės prievartos vaizdai ar vaizdo įrašai",
|
||||
"report_flow.label.discovery_listing": "Atradimo sąrašas",
|
||||
"report_flow.label.dislike": "Tai tiesiog ne man",
|
||||
"report_flow.label.dsa": "Turinys, kuris neteisėtas ES (Skaitmeninių paslaugų aktas)",
|
||||
"report_flow.label.eating_disorder_promotion": "Sutrikusių mitybos įpročių skatinimas",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Jų profilis propaguoja valgymo sutrikimus",
|
||||
"report_flow.label.email": "El. pašto adresas",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_NL_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "Echte of door AI gegenereerde beelden of video's van seksueel misbruik van kinderen",
|
||||
"report_flow.label.discovery_listing": "Vermelding bij Ontdekken",
|
||||
"report_flow.label.dislike": "Het is gewoon niets voor mij",
|
||||
"report_flow.label.dsa": "Inhoud die illegaal is in de EU (digitaledienstenverordening)",
|
||||
"report_flow.label.eating_disorder_promotion": "Gestoord eetgedrag aanmoedigen",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Hun profiel promoot eetstoornissen",
|
||||
"report_flow.label.email": "E-mailadres",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_NO_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "Ekte eller AI-genererte bilder eller videoer av seksuelle overgrep mot barn",
|
||||
"report_flow.label.discovery_listing": "Oppføring i Oppdag",
|
||||
"report_flow.label.dislike": "Det er bare ikke noe for meg",
|
||||
"report_flow.label.dsa": "Innhold som er ulovlig i EU (forordningen om digitale tjenester, DSA)",
|
||||
"report_flow.label.eating_disorder_promotion": "Oppfordrer til spiseforstyrrelser",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Profilen deres fremmer spiseforstyrrelser",
|
||||
"report_flow.label.email": "E-postadresse",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_PL_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "Prawdziwe lub wygenerowane przez AI obrazy lub filmy przedstawiające wykorzystywanie seksualne dzieci",
|
||||
"report_flow.label.discovery_listing": "Wpis w sekcji Odkrywanie",
|
||||
"report_flow.label.dislike": "To po prostu nie jest dla mnie",
|
||||
"report_flow.label.dsa": "Treści, które są nielegalne w UE (akt o usługach cyfrowych)",
|
||||
"report_flow.label.eating_disorder_promotion": "Zachęcanie do zaburzeń odżywiania",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Ich profil promuje zaburzenia odżywiania",
|
||||
"report_flow.label.email": "Adres e-mail",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_PT_BR_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "Imagens ou vídeos reais ou gerados por IA de abuso sexual infantil",
|
||||
"report_flow.label.discovery_listing": "Listagem em Descobrir",
|
||||
"report_flow.label.dislike": "Não é para mim",
|
||||
"report_flow.label.dsa": "Conteúdo ilegal na UE (Regulamento dos Serviços Digitais)",
|
||||
"report_flow.label.eating_disorder_promotion": "Incentivando transtornos alimentares",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "O perfil dele(a) promove transtornos alimentares",
|
||||
"report_flow.label.email": "Endereço de e-mail",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_RO_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "Imagini sau videoclipuri reale sau generate de AI cu abuz sexual asupra copiilor",
|
||||
"report_flow.label.discovery_listing": "Listarea în Discovery",
|
||||
"report_flow.label.dislike": "Pur și simplu nu este pentru mine",
|
||||
"report_flow.label.dsa": "Conținut ilegal în UE (Regulamentul privind serviciile digitale)",
|
||||
"report_flow.label.eating_disorder_promotion": "Încurajarea tulburărilor de alimentație",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Profilul său promovează tulburările de alimentație",
|
||||
"report_flow.label.email": "Adresă de e-mail",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_RU_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "Реальные или созданные ИИ изображения или видео сексуального насилия над детьми",
|
||||
"report_flow.label.discovery_listing": "Запись в каталоге",
|
||||
"report_flow.label.dislike": "Мне это не подходит",
|
||||
"report_flow.label.dsa": "Незаконный в ЕС контент (Закон о цифровых услугах, DSA)",
|
||||
"report_flow.label.eating_disorder_promotion": "Поощрение расстройств пищевого поведения",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Их профиль пропагандирует расстройства пищевого поведения",
|
||||
"report_flow.label.email": "Адрес электронной почты",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_SV_SE_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "Verkliga eller AI-genererade bilder eller videor av sexuella övergrepp mot barn",
|
||||
"report_flow.label.discovery_listing": "Listning i Upptäck",
|
||||
"report_flow.label.dislike": "Det är bara inget för mig",
|
||||
"report_flow.label.dsa": "Innehåll som är olagligt i EU (förordningen om digitala tjänster)",
|
||||
"report_flow.label.eating_disorder_promotion": "Uppmuntrar till ätstörningar",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Deras profil främjar ätstörningar",
|
||||
"report_flow.label.email": "E-postadress",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_TH_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "ภาพหรือวิดีโอการล่วงละเมิดทางเพศเด็ก ไม่ว่าจะเป็นของจริงหรือสร้างโดย AI",
|
||||
"report_flow.label.discovery_listing": "รายการใน Discovery",
|
||||
"report_flow.label.dislike": "ไม่เหมาะกับฉัน",
|
||||
"report_flow.label.dsa": "เนื้อหาที่ผิดกฎหมายในสหภาพยุโรป (กฎหมายบริการดิจิทัล หรือ DSA)",
|
||||
"report_flow.label.eating_disorder_promotion": "ส่งเสริมพฤติกรรมการกินที่ผิดปกติ",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "โปรไฟล์ของพวกเขาส่งเสริมความผิดปกติในการกิน",
|
||||
"report_flow.label.email": "ที่อยู่อีเมล",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_TR_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "Çocuk cinsel istismarına ait gerçek veya yapay zeka ile üretilmiş görseller ya da videolar",
|
||||
"report_flow.label.discovery_listing": "Keşfet listesi",
|
||||
"report_flow.label.dislike": "Bana göre değil",
|
||||
"report_flow.label.dsa": "AB'de yasa dışı içerik (Dijital Hizmetler Yasası)",
|
||||
"report_flow.label.eating_disorder_promotion": "Düzensiz yeme davranışlarını teşvik etme",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Profili yeme bozukluklarını teşvik ediyor",
|
||||
"report_flow.label.email": "E-posta adresi",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_UK_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "Реальні або згенеровані ШІ зображення чи відео сексуального насильства над дітьми",
|
||||
"report_flow.label.discovery_listing": "Запис у Discovery",
|
||||
"report_flow.label.dislike": "Мені це просто не підходить",
|
||||
"report_flow.label.dsa": "Вміст, незаконний в ЄС (Акт про цифрові послуги)",
|
||||
"report_flow.label.eating_disorder_promotion": "Заохочення розладів харчової поведінки",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Їхній профіль пропагує розлади харчової поведінки",
|
||||
"report_flow.label.email": "Адреса електронної пошти",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_VI_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "Ảnh hoặc video lạm dụng tình dục trẻ em, dù là thật hay do AI tạo ra",
|
||||
"report_flow.label.discovery_listing": "Danh sách khám phá",
|
||||
"report_flow.label.dislike": "Không hợp với tôi",
|
||||
"report_flow.label.dsa": "Nội dung bất hợp pháp tại EU (Đạo luật Dịch vụ Kỹ thuật số)",
|
||||
"report_flow.label.eating_disorder_promotion": "Khuyến khích chứng rối loạn ăn uống",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Hồ sơ của họ quảng bá chứng rối loạn ăn uống",
|
||||
"report_flow.label.email": "Địa chỉ email",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_ZH_CN_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "真实或 AI 生成的儿童性虐待图像或视频",
|
||||
"report_flow.label.discovery_listing": "社区发现列表",
|
||||
"report_flow.label.dislike": "我就是不喜欢",
|
||||
"report_flow.label.dsa": "在欧盟属违法的内容(《数字服务法》)",
|
||||
"report_flow.label.eating_disorder_promotion": "鼓励进食障碍行为",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "其个人资料宣传进食障碍",
|
||||
"report_flow.label.email": "电子邮件地址",
|
||||
|
||||
@@ -45,7 +45,6 @@ const CONTENT_I18N_ZH_TW_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"report_flow.label.csam": "兒童性虐待的真實或 AI 生成圖片或影片",
|
||||
"report_flow.label.discovery_listing": "探索列表",
|
||||
"report_flow.label.dislike": "對我來說不太適合",
|
||||
"report_flow.label.dsa": "在歐盟屬違法的內容(《數位服務法》)",
|
||||
"report_flow.label.eating_disorder_promotion": "鼓勵飲食失調",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "他們的個人檔案宣傳飲食失調",
|
||||
"report_flow.label.email": "電子郵件地址",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "صور أو مقاطع فيديو حقيقية أو مولدة بالذكاء الاصطناعي تُظهر اعتداءً جنسيًا على الأطفال",
|
||||
"report_flow.label.discovery_listing": "قائمة الاكتشاف",
|
||||
"report_flow.label.dislike": "هذا ببساطة لا يناسبني",
|
||||
"report_flow.label.dsa": "محتوى غير قانوني في الاتحاد الأوروبي (قانون الخدمات الرقمية)",
|
||||
"report_flow.label.eating_disorder_promotion": "تشجيع سلوكيات الأكل المضطربة",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "ملفهم الشخصي يروج لاضطرابات الأكل",
|
||||
"report_flow.label.email": "عنوان البريد الإلكتروني",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "Реални или генерирани от изкуствен интелект изображения или видеоклипове на сексуално насилие над деца",
|
||||
"report_flow.label.discovery_listing": "Списък за откриване",
|
||||
"report_flow.label.dislike": "Просто не е за мен",
|
||||
"report_flow.label.dsa": "Съдържание, което е незаконно в ЕС (Акт за цифровите услуги)",
|
||||
"report_flow.label.eating_disorder_promotion": "Насърчаване на хранителни разстройства",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Профилът им насърчава хранителни разстройства",
|
||||
"report_flow.label.email": "Имейл адрес",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "Skutečné nebo pomocí AI vytvořené obrázky či videa sexuálního zneužívání dětí",
|
||||
"report_flow.label.discovery_listing": "Záznam v seznamu objevování",
|
||||
"report_flow.label.dislike": "Prostě to není pro mě",
|
||||
"report_flow.label.dsa": "Obsah, který je v EU nelegální (akt o digitálních službách)",
|
||||
"report_flow.label.eating_disorder_promotion": "Nabádání k poruchám příjmu potravy",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Jejich profil propaguje poruchy příjmu potravy",
|
||||
"report_flow.label.email": "E-mailová adresa",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "Ægte eller AI-genererede billeder eller videoer af seksuelle overgreb mod børn",
|
||||
"report_flow.label.discovery_listing": "Opslag i Opdag",
|
||||
"report_flow.label.dislike": "Det er bare ikke noget for mig",
|
||||
"report_flow.label.dsa": "Indhold, der er ulovligt i EU (retsakten om digitale tjenester, DSA)",
|
||||
"report_flow.label.eating_disorder_promotion": "Opfordrer til spiseforstyrrelser",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Deres profil fremmer spiseforstyrrelser",
|
||||
"report_flow.label.email": "E-mailadresse",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "Reale oder KI-generierte Bilder oder Videos von sexuellem Kindesmissbrauch",
|
||||
"report_flow.label.discovery_listing": "Eintrag in „Entdecken“",
|
||||
"report_flow.label.dislike": "Das ist einfach nichts für mich",
|
||||
"report_flow.label.dsa": "Inhalte, die in der EU illegal sind (Gesetz über digitale Dienste)",
|
||||
"report_flow.label.eating_disorder_promotion": "Zu gestörtem Essverhalten ermutigen",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Das Profil der Person fördert Essstörungen",
|
||||
"report_flow.label.email": "E-Mail-Adresse",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "Πραγματικές ή δημιουργημένες με AI εικόνες ή βίντεο σεξουαλικής κακοποίησης παιδιών",
|
||||
"report_flow.label.discovery_listing": "Καταχώριση ανακάλυψης",
|
||||
"report_flow.label.dislike": "Απλά δεν μου ταιριάζει",
|
||||
"report_flow.label.dsa": "Περιεχόμενο που είναι παράνομο στην ΕΕ (πράξη για τις ψηφιακές υπηρεσίες, DSA)",
|
||||
"report_flow.label.eating_disorder_promotion": "Ενθάρρυνση διατροφικών διαταραχών",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Το προφίλ τους προωθεί διατροφικές διαταραχές",
|
||||
"report_flow.label.email": "Διεύθυνση email",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "Real or AI-generated images or videos of child sexual abuse",
|
||||
"report_flow.label.discovery_listing": "Discovery listing",
|
||||
"report_flow.label.dislike": "It's just not for me",
|
||||
"report_flow.label.dsa": "Content that's illegal in the EU (Digital Services Act)",
|
||||
"report_flow.label.eating_disorder_promotion": "Encouraging disordered eating",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Their profile promotes eating disorders",
|
||||
"report_flow.label.email": "Email address",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "Imágenes o videos reales o generados por IA de abuso sexual infantil",
|
||||
"report_flow.label.discovery_listing": "Listado en Descubrir",
|
||||
"report_flow.label.dislike": "Simplemente no es para mí",
|
||||
"report_flow.label.dsa": "Contenido ilegal en la UE (Reglamento de Servicios Digitales)",
|
||||
"report_flow.label.eating_disorder_promotion": "Fomentar trastornos alimenticios",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Su perfil promueve trastornos alimenticios",
|
||||
"report_flow.label.email": "Dirección de correo electrónico",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "Imágenes o vídeos reales o generados por IA de abuso sexual infantil",
|
||||
"report_flow.label.discovery_listing": "Ficha en Descubrir",
|
||||
"report_flow.label.dislike": "Simplemente no es para mí",
|
||||
"report_flow.label.dsa": "Contenido ilegal en la UE (Reglamento de Servicios Digitales)",
|
||||
"report_flow.label.eating_disorder_promotion": "Fomentar trastornos de la conducta alimentaria",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Su perfil promueve trastornos de la conducta alimentaria",
|
||||
"report_flow.label.email": "Dirección de correo electrónico",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "Aitoja tai tekoälyn luomia kuvia tai videoita lapsiin kohdistuvasta seksuaalisesta hyväksikäytöstä",
|
||||
"report_flow.label.discovery_listing": "Löydä-listaus",
|
||||
"report_flow.label.dislike": "Se ei vain ole minun juttuni",
|
||||
"report_flow.label.dsa": "Laiton sisältö EU:ssa (digipalvelusäädös, DSA)",
|
||||
"report_flow.label.eating_disorder_promotion": "Syömishäiriöihin kannustaminen",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Hänen profiilinsa edistää syömishäiriöitä",
|
||||
"report_flow.label.email": "Sähköpostiosoite",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "Images ou vidéos réelles ou générées par IA représentant des abus sexuels sur des enfants",
|
||||
"report_flow.label.discovery_listing": "Fiche dans Découverte",
|
||||
"report_flow.label.dislike": "Ce n'est pas pour moi",
|
||||
"report_flow.label.dsa": "Contenu illégal dans l'UE (règlement sur les services numériques, DSA)",
|
||||
"report_flow.label.eating_disorder_promotion": "Encourager les troubles du comportement alimentaire",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Son profil fait la promotion des troubles du comportement alimentaire",
|
||||
"report_flow.label.email": "Adresse e-mail",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "תמונות או סרטונים של פגיעה מינית בילדים, אמיתיים או שנוצרו באמצעות AI",
|
||||
"report_flow.label.discovery_listing": "רישום בגילוי",
|
||||
"report_flow.label.dislike": "זה פשוט לא בשבילי",
|
||||
"report_flow.label.dsa": "תוכן בלתי חוקי באיחוד האירופי (חוק השירותים הדיגיטליים, DSA)",
|
||||
"report_flow.label.eating_disorder_promotion": "עידוד הפרעות אכילה",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "הפרופיל שלהם מקדם הפרעות אכילה",
|
||||
"report_flow.label.email": "כתובת אימייל",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "बाल यौन शोषण की असली या AI से बनाई गई तस्वीरें या वीडियो",
|
||||
"report_flow.label.discovery_listing": "डिस्कवरी लिस्टिंग",
|
||||
"report_flow.label.dislike": "यह बस मेरे लिए नहीं है",
|
||||
"report_flow.label.dsa": "यूरोपीय संघ में गैर-कानूनी सामग्री (डिजिटल सेवा अधिनियम)",
|
||||
"report_flow.label.eating_disorder_promotion": "खाने संबंधी विकार वाली आदतों को बढ़ावा देना",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "उनकी प्रोफ़ाइल खाने संबंधी विकारों को बढ़ावा देती है",
|
||||
"report_flow.label.email": "ईमेल पता",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "Stvarne ili AI-generirane slike ili videozapisi seksualnog zlostavljanja djece",
|
||||
"report_flow.label.discovery_listing": "Unos u Otkrivanju",
|
||||
"report_flow.label.dislike": "Jednostavno mi ne odgovara",
|
||||
"report_flow.label.dsa": "Sadržaj koji je nezakonit u EU-u (Akt o digitalnim uslugama)",
|
||||
"report_flow.label.eating_disorder_promotion": "Poticanje poremećaja hranjenja",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Njihov profil promiče poremećaje hranjenja",
|
||||
"report_flow.label.email": "Adresa e-pošte",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "Gyermekek szexuális bántalmazását ábrázoló valódi vagy mesterséges intelligencia által generált képek vagy videók",
|
||||
"report_flow.label.discovery_listing": "Listázás a Felfedezésben",
|
||||
"report_flow.label.dislike": "Egyszerűen nem nekem való",
|
||||
"report_flow.label.dsa": "Az EU-ban illegális tartalom (digitális szolgáltatásokról szóló rendelet, DSA)",
|
||||
"report_flow.label.eating_disorder_promotion": "Kóros étkezési szokásokra buzdítás",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "A profilja evészavarokat népszerűsít",
|
||||
"report_flow.label.email": "E-mail-cím",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "Gambar atau video kekerasan seksual terhadap anak, baik yang asli maupun buatan AI",
|
||||
"report_flow.label.discovery_listing": "Listing di Discovery",
|
||||
"report_flow.label.dislike": "Ini tidak cocok untuk saya",
|
||||
"report_flow.label.dsa": "Konten yang ilegal di UE (Undang-Undang Layanan Digital/DSA)",
|
||||
"report_flow.label.eating_disorder_promotion": "Mendorong perilaku makan yang terganggu",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Profil mereka mempromosikan gangguan makan",
|
||||
"report_flow.label.email": "Alamat email",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "Immagini o video reali o generati da IA di abusi sessuali su minori",
|
||||
"report_flow.label.discovery_listing": "Elenco in Scopri",
|
||||
"report_flow.label.dislike": "Non fa per me",
|
||||
"report_flow.label.dsa": "Contenuti illegali nell'UE (Regolamento sui servizi digitali, DSA)",
|
||||
"report_flow.label.eating_disorder_promotion": "Incoraggiare disturbi alimentari",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Il suo profilo promuove disturbi alimentari",
|
||||
"report_flow.label.email": "Indirizzo e-mail",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "児童性的虐待の画像・動画(実在のもの、またはAI生成のもの)",
|
||||
"report_flow.label.discovery_listing": "「見つける」の掲載内容",
|
||||
"report_flow.label.dislike": "自分には合わない",
|
||||
"report_flow.label.dsa": "EUで違法なコンテンツ(デジタルサービス法、DSA)",
|
||||
"report_flow.label.eating_disorder_promotion": "摂食障害的な食行動を促している",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "プロフィールが摂食障害を助長している",
|
||||
"report_flow.label.email": "メールアドレス",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "아동 성착취물(실제 또는 AI로 생성된 이미지 또는 동영상)",
|
||||
"report_flow.label.discovery_listing": "디스커버리 목록",
|
||||
"report_flow.label.dislike": "그냥 내 취향이 아닙니다",
|
||||
"report_flow.label.dsa": "EU에서 불법인 콘텐츠(디지털 서비스법, DSA)",
|
||||
"report_flow.label.eating_disorder_promotion": "섭식 장애 행동 조장",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "프로필에서 섭식 장애를 조장합니다",
|
||||
"report_flow.label.email": "이메일 주소",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "Tikri ar dirbtinio intelekto sukurti vaikų seksualinės prievartos vaizdai ar vaizdo įrašai",
|
||||
"report_flow.label.discovery_listing": "Atradimo sąrašas",
|
||||
"report_flow.label.dislike": "Tai tiesiog ne man",
|
||||
"report_flow.label.dsa": "Turinys, kuris neteisėtas ES (Skaitmeninių paslaugų aktas)",
|
||||
"report_flow.label.eating_disorder_promotion": "Sutrikusių mitybos įpročių skatinimas",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Jų profilis propaguoja valgymo sutrikimus",
|
||||
"report_flow.label.email": "El. pašto adresas",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "Echte of door AI gegenereerde beelden of video's van seksueel misbruik van kinderen",
|
||||
"report_flow.label.discovery_listing": "Vermelding bij Ontdekken",
|
||||
"report_flow.label.dislike": "Het is gewoon niets voor mij",
|
||||
"report_flow.label.dsa": "Inhoud die illegaal is in de EU (digitaledienstenverordening)",
|
||||
"report_flow.label.eating_disorder_promotion": "Gestoord eetgedrag aanmoedigen",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Hun profiel promoot eetstoornissen",
|
||||
"report_flow.label.email": "E-mailadres",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "Ekte eller AI-genererte bilder eller videoer av seksuelle overgrep mot barn",
|
||||
"report_flow.label.discovery_listing": "Oppføring i Oppdag",
|
||||
"report_flow.label.dislike": "Det er bare ikke noe for meg",
|
||||
"report_flow.label.dsa": "Innhold som er ulovlig i EU (forordningen om digitale tjenester, DSA)",
|
||||
"report_flow.label.eating_disorder_promotion": "Oppfordrer til spiseforstyrrelser",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Profilen deres fremmer spiseforstyrrelser",
|
||||
"report_flow.label.email": "E-postadresse",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "Prawdziwe lub wygenerowane przez AI obrazy lub filmy przedstawiające wykorzystywanie seksualne dzieci",
|
||||
"report_flow.label.discovery_listing": "Wpis w sekcji Odkrywanie",
|
||||
"report_flow.label.dislike": "To po prostu nie jest dla mnie",
|
||||
"report_flow.label.dsa": "Treści, które są nielegalne w UE (akt o usługach cyfrowych)",
|
||||
"report_flow.label.eating_disorder_promotion": "Zachęcanie do zaburzeń odżywiania",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Ich profil promuje zaburzenia odżywiania",
|
||||
"report_flow.label.email": "Adres e-mail",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "Imagens ou vídeos reais ou gerados por IA de abuso sexual infantil",
|
||||
"report_flow.label.discovery_listing": "Listagem em Descobrir",
|
||||
"report_flow.label.dislike": "Não é para mim",
|
||||
"report_flow.label.dsa": "Conteúdo ilegal na UE (Regulamento dos Serviços Digitais)",
|
||||
"report_flow.label.eating_disorder_promotion": "Incentivando transtornos alimentares",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "O perfil dele(a) promove transtornos alimentares",
|
||||
"report_flow.label.email": "Endereço de e-mail",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "Imagini sau videoclipuri reale sau generate de AI cu abuz sexual asupra copiilor",
|
||||
"report_flow.label.discovery_listing": "Listarea în Discovery",
|
||||
"report_flow.label.dislike": "Pur și simplu nu este pentru mine",
|
||||
"report_flow.label.dsa": "Conținut ilegal în UE (Regulamentul privind serviciile digitale)",
|
||||
"report_flow.label.eating_disorder_promotion": "Încurajarea tulburărilor de alimentație",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Profilul său promovează tulburările de alimentație",
|
||||
"report_flow.label.email": "Adresă de e-mail",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "Реальные или созданные ИИ изображения или видео сексуального насилия над детьми",
|
||||
"report_flow.label.discovery_listing": "Запись в каталоге",
|
||||
"report_flow.label.dislike": "Мне это не подходит",
|
||||
"report_flow.label.dsa": "Незаконный в ЕС контент (Закон о цифровых услугах, DSA)",
|
||||
"report_flow.label.eating_disorder_promotion": "Поощрение расстройств пищевого поведения",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Их профиль пропагандирует расстройства пищевого поведения",
|
||||
"report_flow.label.email": "Адрес электронной почты",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "Verkliga eller AI-genererade bilder eller videor av sexuella övergrepp mot barn",
|
||||
"report_flow.label.discovery_listing": "Listning i Upptäck",
|
||||
"report_flow.label.dislike": "Det är bara inget för mig",
|
||||
"report_flow.label.dsa": "Innehåll som är olagligt i EU (förordningen om digitala tjänster)",
|
||||
"report_flow.label.eating_disorder_promotion": "Uppmuntrar till ätstörningar",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Deras profil främjar ätstörningar",
|
||||
"report_flow.label.email": "E-postadress",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "ภาพหรือวิดีโอการล่วงละเมิดทางเพศเด็ก ไม่ว่าจะเป็นของจริงหรือสร้างโดย AI",
|
||||
"report_flow.label.discovery_listing": "รายการใน Discovery",
|
||||
"report_flow.label.dislike": "ไม่เหมาะกับฉัน",
|
||||
"report_flow.label.dsa": "เนื้อหาที่ผิดกฎหมายในสหภาพยุโรป (กฎหมายบริการดิจิทัล หรือ DSA)",
|
||||
"report_flow.label.eating_disorder_promotion": "ส่งเสริมพฤติกรรมการกินที่ผิดปกติ",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "โปรไฟล์ของพวกเขาส่งเสริมความผิดปกติในการกิน",
|
||||
"report_flow.label.email": "ที่อยู่อีเมล",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "Çocuk cinsel istismarına ait gerçek veya yapay zeka ile üretilmiş görseller ya da videolar",
|
||||
"report_flow.label.discovery_listing": "Keşfet listesi",
|
||||
"report_flow.label.dislike": "Bana göre değil",
|
||||
"report_flow.label.dsa": "AB'de yasa dışı içerik (Dijital Hizmetler Yasası)",
|
||||
"report_flow.label.eating_disorder_promotion": "Düzensiz yeme davranışlarını teşvik etme",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Profili yeme bozukluklarını teşvik ediyor",
|
||||
"report_flow.label.email": "E-posta adresi",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "Реальні або згенеровані ШІ зображення чи відео сексуального насильства над дітьми",
|
||||
"report_flow.label.discovery_listing": "Запис у Discovery",
|
||||
"report_flow.label.dislike": "Мені це просто не підходить",
|
||||
"report_flow.label.dsa": "Вміст, незаконний в ЄС (Акт про цифрові послуги)",
|
||||
"report_flow.label.eating_disorder_promotion": "Заохочення розладів харчової поведінки",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Їхній профіль пропагує розлади харчової поведінки",
|
||||
"report_flow.label.email": "Адреса електронної пошти",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "Ảnh hoặc video lạm dụng tình dục trẻ em, dù là thật hay do AI tạo ra",
|
||||
"report_flow.label.discovery_listing": "Danh sách khám phá",
|
||||
"report_flow.label.dislike": "Không hợp với tôi",
|
||||
"report_flow.label.dsa": "Nội dung bất hợp pháp tại EU (Đạo luật Dịch vụ Kỹ thuật số)",
|
||||
"report_flow.label.eating_disorder_promotion": "Khuyến khích chứng rối loạn ăn uống",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Hồ sơ của họ quảng bá chứng rối loạn ăn uống",
|
||||
"report_flow.label.email": "Địa chỉ email",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "真实或 AI 生成的儿童性虐待图像或视频",
|
||||
"report_flow.label.discovery_listing": "社区发现列表",
|
||||
"report_flow.label.dislike": "我就是不喜欢",
|
||||
"report_flow.label.dsa": "在欧盟属违法的内容(《数字服务法》)",
|
||||
"report_flow.label.eating_disorder_promotion": "鼓励进食障碍行为",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "其个人资料宣传进食障碍",
|
||||
"report_flow.label.email": "电子邮件地址",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "兒童性虐待的真實或 AI 生成圖片或影片",
|
||||
"report_flow.label.discovery_listing": "探索列表",
|
||||
"report_flow.label.dislike": "對我來說不太適合",
|
||||
"report_flow.label.dsa": "在歐盟屬違法的內容(《數位服務法》)",
|
||||
"report_flow.label.eating_disorder_promotion": "鼓勵飲食失調",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "他們的個人檔案宣傳飲食失調",
|
||||
"report_flow.label.email": "電子郵件地址",
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
"report_flow.label.csam": "Real or AI-generated images or videos of child sexual abuse",
|
||||
"report_flow.label.discovery_listing": "Discovery listing",
|
||||
"report_flow.label.dislike": "It's just not for me",
|
||||
"report_flow.label.dsa": "Content that's illegal in the EU (Digital Services Act)",
|
||||
"report_flow.label.eating_disorder_promotion": "Encouraging disordered eating",
|
||||
"report_flow.label.eating_disorder_promotion_profile": "Their profile promotes eating disorders",
|
||||
"report_flow.label.email": "Email address",
|
||||
|
||||
@@ -121,7 +121,6 @@
|
||||
"message/private_info/threat_to_share": "item",
|
||||
"message/root_message/abuse": "screen:abuse",
|
||||
"message/root_message/dislike": "end",
|
||||
"message/root_message/dsa": "link:dsa",
|
||||
"message/root_message/private_info": "screen:private_info",
|
||||
"message/root_message/something_else": "screen:something_else_message",
|
||||
"message/root_message/spam": "submit:spam",
|
||||
@@ -215,7 +214,6 @@
|
||||
"user/profile_threat/violence_incitement": "submit:violence_incitement",
|
||||
"user/profile_threat/violent_threat": "submit:violent_threat",
|
||||
"user/root_user/abuse": "screen:profile_abuse",
|
||||
"user/root_user/dsa": "link:dsa",
|
||||
"user/root_user/hate_violence": "screen:profile_hate_violence",
|
||||
"user/root_user/impersonation": "screen:impersonation",
|
||||
"user/root_user/something_else": "screen:something_else_user",
|
||||
@@ -242,6 +240,8 @@
|
||||
"user/spam_profile/spam_profile": "submit:spam"
|
||||
},
|
||||
"retired": {
|
||||
"message/something_else_message/violence_misinfo": "screen:violence_misinfo"
|
||||
"message/root_message/dsa": "link:dsa",
|
||||
"message/something_else_message/violence_misinfo": "screen:violence_misinfo",
|
||||
"user/root_user/dsa": "link:dsa"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,6 +106,7 @@ const REPORT_FLOW_SURFACES: ReadonlyArray<ReportFlowSurface> = ['in_app', 'dsa']
|
||||
const REPORT_FLOW_ID_PATTERN = /^[a-z0-9_]{1,48}$/;
|
||||
const MAX_WALK_SCREENS = 10;
|
||||
const CRISIS_LINES_URL = 'https://befrienders.org';
|
||||
const COPYRIGHT_HELP_URL = 'https://fluxer.app/help/copyright';
|
||||
const HOSTED_REPORT_FLOW_INSTANCE: ReportFlowInstance = {selfHosted: false, guidelinesLinked: true};
|
||||
const REPORT_FLOW_CHECKED_INSTANCES: ReadonlyArray<ReportFlowInstance> = [
|
||||
HOSTED_REPORT_FLOW_INSTANCE,
|
||||
@@ -130,7 +131,6 @@ function isLinkAvailable(link: ReportFlowLinkId, instance: ReportFlowInstance):
|
||||
return true;
|
||||
case 'guidelines':
|
||||
return instance.guidelinesLinked;
|
||||
case 'dsa':
|
||||
case 'copyright':
|
||||
return !instance.selfHosted;
|
||||
}
|
||||
@@ -355,10 +355,9 @@ function collectDefinitionErrors(library: ReportFlowLibrary): Array<string> {
|
||||
checkKey(option.label, optionWhere);
|
||||
checkOutcome(option.outcome, optionWhere);
|
||||
const endsWithoutNotice = option.outcome.type === 'end' && option.outcome.noticeId === undefined;
|
||||
const linksToDsa =
|
||||
option.outcome.type === 'link' && (option.outcome.link === 'dsa' || option.outcome.link === 'copyright');
|
||||
if ((endsWithoutNotice || linksToDsa) && option.surface !== 'in_app') {
|
||||
errors.push(`${optionWhere}: a no-report or DSA link option must be limited to in_app`);
|
||||
const linksToCopyright = option.outcome.type === 'link' && option.outcome.link === 'copyright';
|
||||
if ((endsWithoutNotice || linksToCopyright) && option.surface !== 'in_app') {
|
||||
errors.push(`${optionWhere}: a no-report or copyright link option must be limited to in_app`);
|
||||
}
|
||||
}
|
||||
if (screen.checklist) {
|
||||
@@ -537,10 +536,8 @@ function getReportFlowInstance(guidelinesUrl: string | null): ReportFlowInstance
|
||||
|
||||
function getLinkUrl(link: ReportFlowLinkId, guidelinesUrl: string | null): string | null {
|
||||
switch (link) {
|
||||
case 'dsa':
|
||||
return `${Config.endpoints.webApp}/report`;
|
||||
case 'copyright':
|
||||
return `${Config.endpoints.webApp}/report?option=copyright_notice`;
|
||||
return COPYRIGHT_HELP_URL;
|
||||
case 'crisis_lines':
|
||||
return CRISIS_LINES_URL;
|
||||
case 'guidelines':
|
||||
|
||||
@@ -6,7 +6,7 @@ import type {ReportFlowSurface} from '@fluxer/schema/src/domains/report/ReportFl
|
||||
|
||||
export type ReportFlowCopyKey = Extract<ContentI18nKey, `report_flow.${string}`>;
|
||||
|
||||
export type ReportFlowLinkId = 'dsa' | 'copyright' | 'crisis_lines' | 'guidelines';
|
||||
export type ReportFlowLinkId = 'copyright' | 'crisis_lines' | 'guidelines';
|
||||
|
||||
export type ReportFlowOutcomeDef =
|
||||
| {type: 'screen'; screenId: string}
|
||||
@@ -110,7 +110,6 @@ export const REPORT_FLOW_SCREENS: ReadonlyArray<ReportFlowScreenDef> = [
|
||||
outcome: {type: 'screen', screenId: 'something_else_message'},
|
||||
},
|
||||
{id: 'dislike', label: 'report_flow.label.dislike', outcome: {type: 'end'}, surface: 'in_app'},
|
||||
{id: 'dsa', label: 'report_flow.label.dsa', outcome: {type: 'link', link: 'dsa'}, surface: 'in_app'},
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -521,7 +520,6 @@ export const REPORT_FLOW_SCREENS: ReadonlyArray<ReportFlowScreenDef> = [
|
||||
label: 'report_flow.label.something_else',
|
||||
outcome: {type: 'screen', screenId: 'something_else_user'},
|
||||
},
|
||||
{id: 'dsa', label: 'report_flow.label.dsa', outcome: {type: 'link', link: 'dsa'}, surface: 'in_app'},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -248,7 +248,7 @@ describe('report flow definitions', () => {
|
||||
expect(() => assertValidReportFlowLibrary(broken)).toThrow(/missing_screen is not defined/);
|
||||
});
|
||||
|
||||
test('a no-report or DSA option that is not limited to the app throws', () => {
|
||||
test('a no-report option that is not limited to the app throws', () => {
|
||||
const unlimitedDislike = editScreen(REPORT_FLOW_LIBRARY, 'root_message', (screen) => ({
|
||||
...screen,
|
||||
options: screen.options?.map((option) =>
|
||||
@@ -256,11 +256,6 @@ describe('report flow definitions', () => {
|
||||
),
|
||||
}));
|
||||
expect(() => assertValidReportFlowLibrary(unlimitedDislike)).toThrow(/limited to in_app/);
|
||||
const unlimitedDsaRow = editScreen(REPORT_FLOW_LIBRARY, 'root_user', (screen) => ({
|
||||
...screen,
|
||||
options: screen.options?.map((option) => (option.id === 'dsa' ? {...option, surface: undefined} : option)),
|
||||
}));
|
||||
expect(() => assertValidReportFlowLibrary(unlimitedDsaRow)).toThrow(/limited to in_app/);
|
||||
});
|
||||
|
||||
test('other broken definitions throw', () => {
|
||||
@@ -883,7 +878,6 @@ describe('report flow rendering', () => {
|
||||
'spam',
|
||||
'something_else',
|
||||
'dislike',
|
||||
'dsa',
|
||||
]);
|
||||
expect(root.options[5].outcome).toEqual({type: 'end', screen_id: null, reason: null, notice_id: null, url: null});
|
||||
expect(root.options[3].outcome).toEqual({
|
||||
@@ -893,7 +887,6 @@ describe('report flow rendering', () => {
|
||||
notice_id: null,
|
||||
url: null,
|
||||
});
|
||||
expect(root.options[6].outcome.url).toBe(`${config.endpoints.webApp}/report`);
|
||||
const copyright = message.screens
|
||||
.find((screen) => screen.id === 'something_else_message')!
|
||||
.options.find((option) => option.id === 'copyright');
|
||||
@@ -902,7 +895,7 @@ describe('report flow rendering', () => {
|
||||
screen_id: null,
|
||||
reason: null,
|
||||
notice_id: null,
|
||||
url: `${config.endpoints.webApp}/report?option=copyright_notice`,
|
||||
url: 'https://fluxer.app/help/copyright',
|
||||
});
|
||||
expect(root.checklist).toBeNull();
|
||||
expect(root.next_screen_id).toBeNull();
|
||||
@@ -920,6 +913,9 @@ describe('report flow rendering', () => {
|
||||
expect(sexual.options[0].id).toBe('minor_sexual');
|
||||
const user = getReportFlowResponse('user', 'in_app', 'en-US');
|
||||
expect(user.guidelines_url).toBe(`${config.endpoints.marketing}/guidelines`);
|
||||
expect(user.screens.find((screen) => screen.id === 'root_user')?.options.map((option) => option.id)).not.toContain(
|
||||
'dsa',
|
||||
);
|
||||
const intro = user.screens[0];
|
||||
expect(intro.next_screen_id).toBe('profile_parts');
|
||||
expect(intro.options_heading).toBe('Learn more');
|
||||
@@ -984,8 +980,8 @@ describe('report flow rendering', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('the in-app copyright rows open the DSA form on the copyright notice', () => {
|
||||
const url = `${getConfig().endpoints.webApp}/report?option=copyright_notice`;
|
||||
test('the in-app copyright rows open the copyright help page', () => {
|
||||
const url = 'https://fluxer.app/help/copyright';
|
||||
const copyrightUrl = (target: ReportFlowTargetType, screenId: string) =>
|
||||
getReportFlowResponse(target, 'in_app', 'en-US')
|
||||
.screens.find((screen) => screen.id === screenId)
|
||||
@@ -1031,7 +1027,7 @@ describe('report flow rendering', () => {
|
||||
).not.toMatch(dsaNames);
|
||||
});
|
||||
|
||||
test('self-hosted instances get no guidelines, DSA or copyright link rows', () => {
|
||||
test('self-hosted instances get no guidelines or copyright link rows', () => {
|
||||
const hostedUser = getReportFlowResponse('user', 'in_app', 'en-US');
|
||||
getConfig().instance.selfHosted = true;
|
||||
const user = getReportFlowResponse('user', 'in_app', 'en-US');
|
||||
@@ -1042,7 +1038,6 @@ describe('report flow rendering', () => {
|
||||
expect(intro.options_heading).toBeNull();
|
||||
expect(intro.next_screen_id).toBe('profile_parts');
|
||||
const userScreens = new Map(user.screens.map((screen) => [screen.id, screen]));
|
||||
expect(userScreens.get('root_user')?.options.map((option) => option.id)).not.toContain('dsa');
|
||||
expect(userScreens.get('something_else_user')?.options.map((option) => option.id)).not.toContain('copyright');
|
||||
const message = getReportFlowResponse('message', 'in_app', 'en-US');
|
||||
for (const screen of message.screens) {
|
||||
@@ -1051,7 +1046,6 @@ describe('report flow rendering', () => {
|
||||
}
|
||||
}
|
||||
const messageScreens = new Map(message.screens.map((screen) => [screen.id, screen]));
|
||||
expect(messageScreens.get('root_message')?.options.map((option) => option.id)).not.toContain('dsa');
|
||||
expect(messageScreens.get('something_else_message')?.options.map((option) => option.id)).not.toContain('copyright');
|
||||
const messageDsa = getReportFlowResponse('message', 'dsa', 'en-US');
|
||||
expect(
|
||||
|
||||
@@ -428,11 +428,12 @@ describe('Report flows', () => {
|
||||
.get('/reports/flows/message?surface=dsa')
|
||||
.expect(HTTP_STATUS.OK)
|
||||
.execute();
|
||||
const appOnly = ['dislike', 'rude_language', 'dsa', 'copyright', 'worried_self_harm', 'worried_suicide'];
|
||||
const appOnly = ['dislike', 'rude_language', 'copyright', 'worried_self_harm', 'worried_suicide'];
|
||||
for (const id of appOnly) {
|
||||
expect(optionIds(inApp), id).toContain(id);
|
||||
expect(optionIds(dsa), id).not.toContain(id);
|
||||
}
|
||||
expect(optionIds(inApp)).not.toContain('dsa');
|
||||
expect(optionIds(inApp)).not.toContain('copyright_notice');
|
||||
expect(optionIds(dsa)).toContain('copyright_notice');
|
||||
expect(dsa.revision_hash).not.toBe(inApp.revision_hash);
|
||||
|
||||
@@ -556,6 +556,14 @@ export class MockStorageService implements IStorageService {
|
||||
return this.objects.has(this.objectId(bucket, key));
|
||||
}
|
||||
|
||||
setObjectLastModified(bucket: string, key: string, lastModified: Date): void {
|
||||
const object = this.objects.get(this.objectId(bucket, key));
|
||||
if (!object) {
|
||||
throw new Error(`No stored object ${key} in ${bucket}`);
|
||||
}
|
||||
object.lastModified = lastModified;
|
||||
}
|
||||
|
||||
reset(): void {
|
||||
this.objects.clear();
|
||||
this.multipartUploads.clear();
|
||||
|
||||
@@ -41,6 +41,7 @@ import {useRemScaleTracking} from '@app/features/theme/hooks/useRemScaleTracking
|
||||
import {useThemeCssVariables} from '@app/features/theme/hooks/useThemeCssVariables';
|
||||
import Theme from '@app/features/theme/state/Theme';
|
||||
import ThemeLibrary from '@app/features/theme/state/ThemeLibrary';
|
||||
import WindowsFont from '@app/features/theme/state/WindowsFont';
|
||||
import {useThemeStudioBroadcast} from '@app/features/theme_studio/state/ThemeStudioBroadcast';
|
||||
import ThemeStudioState from '@app/features/theme_studio/state/ThemeStudioState';
|
||||
import {SVGMasks} from '@app/features/ui/components/SVGMasks';
|
||||
@@ -174,6 +175,7 @@ export const AppWrapper = observer(({children}: AppWrapperProps) => {
|
||||
useDocumentClassToggle('reduced-motion', reducedMotion);
|
||||
useDocumentClassToggle('mobile-layout', MobileLayout.platformMobileDetected || MobileLayout.enabled);
|
||||
useDocumentClassToggle(UNFOCUSED_FULLY_INTERACTIVE_CLASS, stayInteractiveWhenUnfocused);
|
||||
useDocumentClassToggle('windows-fluxer-sans', WindowsFont.useFluxerSans);
|
||||
useDesktopAllowTransparency(isNative);
|
||||
useWindowEventListeners();
|
||||
useRemScaleTracking();
|
||||
|
||||
@@ -17,56 +17,61 @@
|
||||
--font-fallback-mono:
|
||||
'Noto Sans Mono', 'Fluxer Sans SC', 'Fluxer Sans TC', 'Fluxer Sans JP', 'Fluxer Sans KR', var(--font-fallback-sans);
|
||||
|
||||
--font-sans-primary: 'Fluxer Sans';
|
||||
--font-sans:
|
||||
'Fluxer Sans', 'Fluxer Sans Arabic', 'Fluxer Sans Hebrew', 'Fluxer Sans Devanagari', 'Fluxer Sans Thai Looped',
|
||||
var(--font-sans-primary), 'Fluxer Sans Arabic', 'Fluxer Sans Hebrew', 'Fluxer Sans Devanagari', 'Fluxer Sans Thai Looped',
|
||||
'Fluxer Sans SC', 'Fluxer Sans TC', 'Fluxer Sans JP', 'Fluxer Sans KR', system-ui, -apple-system,
|
||||
BlinkMacSystemFont, 'Segoe UI', 'Roboto', var(--font-fallback-sans), sans-serif;
|
||||
--font-mono: 'Fluxer Mono', 'Menlo', 'Monaco', 'Courier New', var(--font-fallback-mono), monospace;
|
||||
}
|
||||
|
||||
:root.platform-windows:not(.windows-fluxer-sans) {
|
||||
--font-sans-primary: 'Segoe UI Variable Text', 'Segoe UI';
|
||||
}
|
||||
|
||||
:root:lang(ja) {
|
||||
--font-sans:
|
||||
'Fluxer Sans', 'Fluxer Sans JP', 'Fluxer Sans Arabic', 'Fluxer Sans Hebrew', 'Fluxer Sans Devanagari',
|
||||
var(--font-sans-primary), 'Fluxer Sans JP', 'Fluxer Sans Arabic', 'Fluxer Sans Hebrew', 'Fluxer Sans Devanagari',
|
||||
'Fluxer Sans Thai Looped', 'Fluxer Sans SC', 'Fluxer Sans TC', 'Fluxer Sans KR', system-ui, -apple-system,
|
||||
BlinkMacSystemFont, 'Hiragino Sans', 'Hiragino Kaku Gothic ProN', 'Yu Gothic', 'Meiryo',
|
||||
var(--font-fallback-sans), sans-serif;
|
||||
}
|
||||
:root:lang(ko) {
|
||||
--font-sans:
|
||||
'Fluxer Sans', 'Fluxer Sans KR', 'Fluxer Sans Arabic', 'Fluxer Sans Hebrew', 'Fluxer Sans Devanagari',
|
||||
var(--font-sans-primary), 'Fluxer Sans KR', 'Fluxer Sans Arabic', 'Fluxer Sans Hebrew', 'Fluxer Sans Devanagari',
|
||||
'Fluxer Sans Thai Looped', 'Fluxer Sans SC', 'Fluxer Sans TC', 'Fluxer Sans JP', system-ui, -apple-system,
|
||||
BlinkMacSystemFont, 'Malgun Gothic', 'Apple SD Gothic Neo', var(--font-fallback-sans), sans-serif;
|
||||
}
|
||||
:root:lang(zh-CN),
|
||||
:root:lang(zh-Hans) {
|
||||
--font-sans:
|
||||
'Fluxer Sans', 'Fluxer Sans SC', 'Fluxer Sans Arabic', 'Fluxer Sans Hebrew', 'Fluxer Sans Devanagari',
|
||||
var(--font-sans-primary), 'Fluxer Sans SC', 'Fluxer Sans Arabic', 'Fluxer Sans Hebrew', 'Fluxer Sans Devanagari',
|
||||
'Fluxer Sans Thai Looped', 'Fluxer Sans TC', 'Fluxer Sans JP', 'Fluxer Sans KR', system-ui, -apple-system,
|
||||
BlinkMacSystemFont, 'PingFang SC', 'Microsoft YaHei', var(--font-fallback-sans), sans-serif;
|
||||
}
|
||||
:root:lang(zh-Hant-TW),
|
||||
:root:lang(zh-TW) {
|
||||
--font-sans:
|
||||
'Fluxer Sans', 'Fluxer Sans TC', 'Fluxer Sans Arabic', 'Fluxer Sans Hebrew', 'Fluxer Sans Devanagari',
|
||||
var(--font-sans-primary), 'Fluxer Sans TC', 'Fluxer Sans Arabic', 'Fluxer Sans Hebrew', 'Fluxer Sans Devanagari',
|
||||
'Fluxer Sans Thai Looped', 'Fluxer Sans SC', 'Fluxer Sans JP', 'Fluxer Sans KR', system-ui, -apple-system,
|
||||
BlinkMacSystemFont, 'PingFang TC', 'Microsoft JhengHei', var(--font-fallback-sans), sans-serif;
|
||||
}
|
||||
:root:lang(zh-HK),
|
||||
:root:lang(zh-Hant-HK) {
|
||||
--font-sans:
|
||||
'Fluxer Sans', 'Fluxer Sans TC', 'Fluxer Sans Arabic', 'Fluxer Sans Hebrew', 'Fluxer Sans Devanagari',
|
||||
var(--font-sans-primary), 'Fluxer Sans TC', 'Fluxer Sans Arabic', 'Fluxer Sans Hebrew', 'Fluxer Sans Devanagari',
|
||||
'Fluxer Sans Thai Looped', 'Fluxer Sans SC', 'Fluxer Sans JP', 'Fluxer Sans KR', system-ui, -apple-system,
|
||||
BlinkMacSystemFont, 'PingFang HK', 'Microsoft JhengHei', var(--font-fallback-sans), sans-serif;
|
||||
}
|
||||
:root:lang(ar) {
|
||||
--font-sans:
|
||||
'Fluxer Sans', 'Fluxer Sans Arabic', 'Fluxer Sans Hebrew', 'Fluxer Sans Devanagari', 'Fluxer Sans Thai Looped',
|
||||
var(--font-sans-primary), 'Fluxer Sans Arabic', 'Fluxer Sans Hebrew', 'Fluxer Sans Devanagari', 'Fluxer Sans Thai Looped',
|
||||
'Fluxer Sans SC', 'Fluxer Sans TC', 'Fluxer Sans JP', 'Fluxer Sans KR', system-ui, -apple-system,
|
||||
BlinkMacSystemFont, 'Segoe UI', 'Geeza Pro', 'Arabic Typesetting', var(--font-fallback-sans), sans-serif;
|
||||
}
|
||||
:root:lang(he) {
|
||||
--font-sans:
|
||||
'Fluxer Sans', 'Fluxer Sans Hebrew', 'Fluxer Sans Arabic', 'Fluxer Sans Devanagari', 'Fluxer Sans Thai Looped',
|
||||
var(--font-sans-primary), 'Fluxer Sans Hebrew', 'Fluxer Sans Arabic', 'Fluxer Sans Devanagari', 'Fluxer Sans Thai Looped',
|
||||
'Fluxer Sans SC', 'Fluxer Sans TC', 'Fluxer Sans JP', 'Fluxer Sans KR', system-ui, -apple-system,
|
||||
BlinkMacSystemFont, 'Segoe UI', 'Arial Hebrew', var(--font-fallback-sans), sans-serif;
|
||||
}
|
||||
@@ -75,13 +80,13 @@
|
||||
:root:lang(ne),
|
||||
:root:lang(sa) {
|
||||
--font-sans:
|
||||
'Fluxer Sans', 'Fluxer Sans Devanagari', 'Fluxer Sans Arabic', 'Fluxer Sans Hebrew', 'Fluxer Sans Thai Looped',
|
||||
var(--font-sans-primary), 'Fluxer Sans Devanagari', 'Fluxer Sans Arabic', 'Fluxer Sans Hebrew', 'Fluxer Sans Thai Looped',
|
||||
'Fluxer Sans SC', 'Fluxer Sans TC', 'Fluxer Sans JP', 'Fluxer Sans KR', system-ui, -apple-system,
|
||||
BlinkMacSystemFont, 'Nirmala UI', 'Noto Sans Devanagari', var(--font-fallback-sans), sans-serif;
|
||||
}
|
||||
:root:lang(th) {
|
||||
--font-sans:
|
||||
'Fluxer Sans', 'Fluxer Sans Thai Looped', 'Fluxer Sans Arabic', 'Fluxer Sans Hebrew', 'Fluxer Sans Devanagari',
|
||||
var(--font-sans-primary), 'Fluxer Sans Thai Looped', 'Fluxer Sans Arabic', 'Fluxer Sans Hebrew', 'Fluxer Sans Devanagari',
|
||||
'Fluxer Sans SC', 'Fluxer Sans TC', 'Fluxer Sans JP', 'Fluxer Sans KR', system-ui, -apple-system,
|
||||
BlinkMacSystemFont, 'Leelawadee UI', 'Thonburi', var(--font-fallback-sans), sans-serif;
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ import {
|
||||
getSectionIdsForTab,
|
||||
getSectionsForTab,
|
||||
getUserSettingsTabLabel,
|
||||
PRIVACY_REVIEW_NEEDED_DESCRIPTOR,
|
||||
tabHasMultipleLinkableSections,
|
||||
USER_SETTINGS_LABEL_DESCRIPTOR,
|
||||
} from '@app/features/user/components/settings_utils/SettingsConstants';
|
||||
@@ -79,6 +80,7 @@ import {buildUserSettingsDeepLink} from '@app/features/user/components/settings_
|
||||
import {useSettingsContentKey} from '@app/features/user/hooks/useSettingsContentKey';
|
||||
import {useUnsavedChangesFlash} from '@app/features/user/hooks/useUnsavedChangesFlash';
|
||||
import {ScrollSpyProvider, useScrollSpyContext} from '@app/features/user/state/ScrollSpyContext';
|
||||
import UserSettings from '@app/features/user/state/UserSettings';
|
||||
import Users from '@app/features/user/state/Users';
|
||||
import {
|
||||
collapseSettingsTreeTab,
|
||||
@@ -380,6 +382,7 @@ export const DesktopSettingsView: React.FC<DesktopSettingsViewProps> = observer(
|
||||
const activeTabPanelId = selectedTab ? `settings-tabpanel-${selectedTab}` : undefined;
|
||||
const activeTabId = selectedTab ? `settings-tab-${selectedTab}` : undefined;
|
||||
const shouldShowWhatsNew = hasWhatsNewEntries();
|
||||
const privacySetupPending = UserSettings.isPrivacySetupPending();
|
||||
const scrollKey = useMemo(() => {
|
||||
const subtabKey = contentKey ?? initialSubtab ?? 'root';
|
||||
if (isSearchActive) {
|
||||
@@ -585,6 +588,11 @@ export const DesktopSettingsView: React.FC<DesktopSettingsViewProps> = observer(
|
||||
</div>
|
||||
}
|
||||
selected={isSelected}
|
||||
attentionLabel={
|
||||
tab.type === 'privacy_safety' && privacySetupPending
|
||||
? i18n._(PRIVACY_REVIEW_NEEDED_DESCRIPTOR)
|
||||
: undefined
|
||||
}
|
||||
onClick={() => handleTabSelect(tab.type)}
|
||||
onRequestContentFocus={focusContentPanel}
|
||||
id={tabId}
|
||||
|
||||
@@ -21,6 +21,7 @@ import * as ModalCommands from '@app/features/ui/commands/ModalCommands';
|
||||
import {modal} from '@app/features/ui/commands/ModalCommands';
|
||||
import * as TextCopyCommands from '@app/features/ui/commands/TextCopyCommands';
|
||||
import {MentionBadgeAnimated} from '@app/features/ui/components/MentionBadge';
|
||||
import {NotificationDot} from '@app/features/ui/components/NotificationDot';
|
||||
import {Scroller, type ScrollerHandle} from '@app/features/ui/components/Scroller';
|
||||
import {Spinner} from '@app/features/ui/components/Spinner';
|
||||
import {StatusAwareAvatar} from '@app/features/ui/components/StatusAwareAvatar';
|
||||
@@ -31,6 +32,7 @@ import type {SettingsTab} from '@app/features/user/components/settings_utils/Set
|
||||
import {
|
||||
getCategoryLabel,
|
||||
getUserSettingsTabLabel,
|
||||
PRIVACY_REVIEW_NEEDED_DESCRIPTOR,
|
||||
} from '@app/features/user/components/settings_utils/SettingsConstants';
|
||||
import {isSettingsItemNew} from '@app/features/user/components/settings_utils/SettingsMetadata';
|
||||
import {
|
||||
@@ -44,6 +46,7 @@ import {buildUserSettingsDeepLink} from '@app/features/user/components/settings_
|
||||
import type {MobileNavigationState} from '@app/features/user/hooks/useMobileNavigation';
|
||||
import {useSettingsContentKey} from '@app/features/user/hooks/useSettingsContentKey';
|
||||
import {useUnsavedChangesFlash} from '@app/features/user/hooks/useUnsavedChangesFlash';
|
||||
import UserSettings from '@app/features/user/state/UserSettings';
|
||||
import Users from '@app/features/user/state/Users';
|
||||
import {msg} from '@lingui/core/macro';
|
||||
import {useLingui} from '@lingui/react/macro';
|
||||
@@ -137,9 +140,10 @@ interface PressableSettingsItemProps {
|
||||
tab: SettingsTab;
|
||||
onSelect: () => void;
|
||||
badge?: React.ReactNode;
|
||||
attention?: string;
|
||||
}
|
||||
|
||||
const PressableSettingsItem: React.FC<PressableSettingsItemProps> = observer(({tab, onSelect, badge}) => {
|
||||
const PressableSettingsItem: React.FC<PressableSettingsItemProps> = observer(({tab, onSelect, badge, attention}) => {
|
||||
const {isPressed, pressableProps} = usePressable();
|
||||
const {handleLongPressCopy, consumeSuppressedClick} = useSettingsPageDeepLinkLongPress(tab.type);
|
||||
const handleClick = useCallback(
|
||||
@@ -187,6 +191,9 @@ const PressableSettingsItem: React.FC<PressableSettingsItemProps> = observer(({t
|
||||
{badge}
|
||||
</div>
|
||||
</div>
|
||||
{attention && (
|
||||
<NotificationDot label={attention} data-flx="app.mobile-settings-view.pressable-settings-item.attention-dot" />
|
||||
)}
|
||||
<ArrowLeftIcon
|
||||
className={styles.settingsItemArrow}
|
||||
data-flx="app.mobile-settings-view.pressable-settings-item.settings-item-arrow"
|
||||
@@ -362,6 +369,7 @@ const MobileSettingsList = observer(
|
||||
const {i18n} = useLingui();
|
||||
const currentUser = Users.currentUser;
|
||||
const shouldShowWhatsNew = hasWhatsNewEntries();
|
||||
const privacySetupPending = UserSettings.isPrivacySetupPending();
|
||||
const advancedSettingsHasNew = useMemo(
|
||||
() =>
|
||||
getAdvancedSettingItems().some((item) => isSettingsItemNew(item, Date.now(), currentUser?.createdAt ?? null)),
|
||||
@@ -432,6 +440,11 @@ const MobileSettingsList = observer(
|
||||
tab={tab}
|
||||
onSelect={() => onTabSelect(tab.type, tab.label)}
|
||||
badge={badge}
|
||||
attention={
|
||||
tab.type === 'privacy_safety' && privacySetupPending
|
||||
? i18n._(PRIVACY_REVIEW_NEEDED_DESCRIPTOR)
|
||||
: undefined
|
||||
}
|
||||
data-flx="app.mobile-settings-view.mobile-settings-list.pressable-settings-item.tab-select"
|
||||
/>
|
||||
{(!isLastTab || isLastCategory) && (
|
||||
|
||||
+22
-1
@@ -406,9 +406,30 @@
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.sidebarItemTrailing {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-inline-start: 0.25rem;
|
||||
min-width: 1rem;
|
||||
min-height: 1rem;
|
||||
}
|
||||
|
||||
.sidebarItemAttentionDot {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.sidebarItem[data-expandable='true'].sidebarItemSelected .sidebarItemAttentionDot,
|
||||
.sidebarItem[data-expandable='true'][aria-expanded='true'] .sidebarItemAttentionDot,
|
||||
.sidebarItem[data-expandable='true']:hover .sidebarItemAttentionDot,
|
||||
.sidebarItem[data-expandable='true'].sidebarItemFocused .sidebarItemAttentionDot {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.sidebarItemChevron {
|
||||
flex-shrink: 0;
|
||||
margin-inline-start: 0.25rem;
|
||||
color: var(--text-tertiary);
|
||||
opacity: 0;
|
||||
transform: rotate(0deg);
|
||||
|
||||
@@ -4,6 +4,7 @@ import Accessibility from '@app/features/accessibility/state/Accessibility';
|
||||
import styles from '@app/features/app/components/dialogs/shared/SettingsModalLayout.module.css';
|
||||
import {SETTINGS_SECTIONS_DESCRIPTOR} from '@app/features/i18n/utils/CommonMessageDescriptors';
|
||||
import {remFromPx} from '@app/features/theme/layout/RemFromPx';
|
||||
import {NotificationDot} from '@app/features/ui/components/NotificationDot';
|
||||
import {Scroller, type ScrollerHandle} from '@app/features/ui/components/Scroller';
|
||||
import FocusRing from '@app/features/ui/focus_ring/FocusRing';
|
||||
import {
|
||||
@@ -292,6 +293,7 @@ export const SettingsModalSidebarItem: React.FC<SettingsModalSidebarItemProps> =
|
||||
expandableId,
|
||||
sectionsGroupId,
|
||||
toggleOnSelectedClick = true,
|
||||
attentionLabel,
|
||||
}) => {
|
||||
const {tabIndex, buttonRef} = useSettingsModalSidebarItemLogic({selected});
|
||||
const focusContentAfterActivationRef = useRef(false);
|
||||
@@ -354,14 +356,28 @@ export const SettingsModalSidebarItem: React.FC<SettingsModalSidebarItemProps> =
|
||||
>
|
||||
{label}
|
||||
</span>
|
||||
{expandable && (
|
||||
<CaretRightIcon
|
||||
className={styles.sidebarItemChevron}
|
||||
size={remFromPx(16)}
|
||||
weight="bold"
|
||||
aria-hidden="true"
|
||||
data-flx="app.settings-modal-layout.settings-modal-sidebar-item.sidebar-item-chevron"
|
||||
/>
|
||||
{(expandable || attentionLabel) && (
|
||||
<span
|
||||
className={styles.sidebarItemTrailing}
|
||||
data-flx="app.settings-modal-layout.settings-modal-sidebar-item.sidebar-item-trailing"
|
||||
>
|
||||
{attentionLabel && (
|
||||
<NotificationDot
|
||||
className={styles.sidebarItemAttentionDot}
|
||||
label={attentionLabel}
|
||||
data-flx="app.settings-modal-layout.settings-modal-sidebar-item.attention-dot"
|
||||
/>
|
||||
)}
|
||||
{expandable && (
|
||||
<CaretRightIcon
|
||||
className={styles.sidebarItemChevron}
|
||||
size={remFromPx(16)}
|
||||
weight="bold"
|
||||
aria-hidden="true"
|
||||
data-flx="app.settings-modal-layout.settings-modal-sidebar-item.sidebar-item-chevron"
|
||||
/>
|
||||
)}
|
||||
</span>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -1283,10 +1283,10 @@ const SKELETON_NAGBAR_ROW_SHAPES: Record<NagbarType, SkeletonNagbarRowShape> = {
|
||||
[NagbarType.VISIONARY_MFA]: {tone: SkeletonNagbarTone.BRAND, hasActions: true},
|
||||
[NagbarType.VOICE_SESSION_RESTORE]: {tone: SkeletonNagbarTone.VOICE, hasActions: true},
|
||||
[NagbarType.TERMS_ACCEPTANCE]: {tone: SkeletonNagbarTone.LEGAL, hasActions: true},
|
||||
[NagbarType.PRIVACY_SETUP]: {tone: SkeletonNagbarTone.BRAND, hasActions: true},
|
||||
[NagbarType.SOFTWARE_ENCODER]: {tone: SkeletonNagbarTone.ENCODER, hasActions: true},
|
||||
[NagbarType.STREAMER_MODE]: {tone: SkeletonNagbarTone.STREAMER, hasActions: true},
|
||||
[NagbarType.DOMAIN_MOVED]: {tone: SkeletonNagbarTone.BRAND, hasActions: true},
|
||||
[NagbarType.WINDOWS_FONT]: {tone: SkeletonNagbarTone.BRAND, hasActions: true},
|
||||
};
|
||||
|
||||
const CONNECTION_SKELETON_NAGBAR_TONES: Record<ConnectionNoticeTone, SkeletonNagbarTone> = {
|
||||
|
||||
@@ -253,3 +253,13 @@
|
||||
height: 1.25rem;
|
||||
width: 1.25rem;
|
||||
}
|
||||
|
||||
.controlIconWithDot {
|
||||
mask-image: radial-gradient(circle at 85% 15%, transparent 0.34375rem, #000 calc(0.34375rem + 0.03125rem));
|
||||
}
|
||||
|
||||
.controlDot {
|
||||
position: absolute;
|
||||
top: 0.3125rem;
|
||||
right: 0.3125rem;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {UserSettingsModal} from '@app/features/app/components/dialogs/LoadableSettingsModals';
|
||||
import {UserAreaPopout} from '@app/features/app/components/floating/UserAreaPopout';
|
||||
import styles from '@app/features/app/components/layout/UserArea.module.css';
|
||||
import {
|
||||
@@ -18,9 +17,8 @@ import {getPushToTalkHoldLabel} from '@app/features/input/utils/PushToTalkHint';
|
||||
import Presence from '@app/features/presence/state/Presence';
|
||||
import {SettingsContextMenu} from '@app/features/ui/action_menu/SettingsContextMenu';
|
||||
import * as ContextMenuCommands from '@app/features/ui/commands/ContextMenuCommands';
|
||||
import * as ModalCommands from '@app/features/ui/commands/ModalCommands';
|
||||
import {modal} from '@app/features/ui/commands/ModalCommands';
|
||||
import {FocusRingWrapper} from '@app/features/ui/components/FocusRingWrapper';
|
||||
import {NotificationDot} from '@app/features/ui/components/NotificationDot';
|
||||
import {StatusAwareAvatar} from '@app/features/ui/components/StatusAwareAvatar';
|
||||
import FocusRing from '@app/features/ui/focus_ring/FocusRing';
|
||||
import {usePopout} from '@app/features/ui/hooks/usePopout';
|
||||
@@ -28,8 +26,13 @@ import {TooltipWithKeybind} from '@app/features/ui/keybind_hint/KeybindHint';
|
||||
import {Popout} from '@app/features/ui/popover/PopoverPopout';
|
||||
import MobileLayout from '@app/features/ui/state/MobileLayout';
|
||||
import {Tooltip} from '@app/features/ui/tooltip/Tooltip';
|
||||
import {USER_SETTINGS_LABEL_DESCRIPTOR} from '@app/features/user/components/settings_utils/SettingsConstants';
|
||||
import {openUserSettingsModal} from '@app/features/user/commands/UserSettingsModalCommands';
|
||||
import {
|
||||
USER_SETTINGS_LABEL_DESCRIPTOR,
|
||||
USER_SETTINGS_PRIVACY_REVIEW_NEEDED_DESCRIPTOR,
|
||||
} from '@app/features/user/components/settings_utils/SettingsConstants';
|
||||
import type {User} from '@app/features/user/models/User';
|
||||
import UserSettings from '@app/features/user/state/UserSettings';
|
||||
import * as NicknameUtils from '@app/features/user/utils/NicknameUtils';
|
||||
import {VoiceConnectionStatus} from '@app/features/voice/components/VoiceConnectionStatus';
|
||||
import {VoiceAudioSettingsMenu} from '@app/features/voice/components/VoiceSettingsMenus';
|
||||
@@ -140,14 +143,10 @@ const UserAreaInner = observer(
|
||||
/>
|
||||
));
|
||||
};
|
||||
const handleSettingsClick = () => {
|
||||
ModalCommands.push(
|
||||
modal(
|
||||
() => <UserSettingsModal data-flx="app.user-area.handle-settings-click.user-settings-modal" />,
|
||||
'user-settings',
|
||||
),
|
||||
);
|
||||
};
|
||||
const privacySetupPending = UserSettings.isPrivacySetupPending();
|
||||
const settingsLabel = privacySetupPending
|
||||
? i18n._(USER_SETTINGS_PRIVACY_REVIEW_NEEDED_DESCRIPTOR)
|
||||
: i18n._(USER_SETTINGS_LABEL_DESCRIPTOR);
|
||||
const storeConnectedChannelId = MediaEngine.channelId;
|
||||
const forceShowVoiceConnection = DeveloperOptions.forceShowVoiceConnection;
|
||||
const hasVoiceConnection = !MobileLayout.enabled && (forceShowVoiceConnection || !!storeConnectedChannelId);
|
||||
@@ -420,7 +419,7 @@ const UserAreaInner = observer(
|
||||
<Tooltip
|
||||
text={() => (
|
||||
<TooltipWithKeybind
|
||||
label={i18n._(USER_SETTINGS_LABEL_DESCRIPTOR)}
|
||||
label={settingsLabel}
|
||||
action="system_toggle_settings"
|
||||
data-flx="app.user-area.user-area-inner.tooltip-with-keybind--3"
|
||||
/>
|
||||
@@ -431,9 +430,9 @@ const UserAreaInner = observer(
|
||||
<button
|
||||
ref={settingsButtonRef}
|
||||
type="button"
|
||||
aria-label={i18n._(USER_SETTINGS_LABEL_DESCRIPTOR)}
|
||||
aria-label={settingsLabel}
|
||||
className={clsx(styles.controlButton, settingsContextMenuOpen && styles.contextMenuHover)}
|
||||
onClick={handleSettingsClick}
|
||||
onClick={openUserSettingsModal}
|
||||
onContextMenu={(event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
@@ -446,7 +445,16 @@ const UserAreaInner = observer(
|
||||
}}
|
||||
data-flx="app.user-area.user-area-inner.control-button.settings-click"
|
||||
>
|
||||
<GearIcon className={styles.controlIcon} data-flx="app.user-area.user-area-inner.control-icon--5" />
|
||||
<GearIcon
|
||||
className={clsx(styles.controlIcon, privacySetupPending && styles.controlIconWithDot)}
|
||||
data-flx="app.user-area.user-area-inner.control-icon--5"
|
||||
/>
|
||||
{privacySetupPending && (
|
||||
<NotificationDot
|
||||
className={styles.controlDot}
|
||||
data-flx="app.user-area.user-area-inner.privacy-review-dot"
|
||||
/>
|
||||
)}
|
||||
</button>
|
||||
</FocusRing>
|
||||
</Tooltip>
|
||||
|
||||
@@ -27,12 +27,11 @@ import {
|
||||
shouldShowPremiumFeatures,
|
||||
} from '@app/features/premium/utils/PremiumUtils';
|
||||
import StreamerMode from '@app/features/streamer_mode/state/StreamerMode';
|
||||
import WindowsFont, {WINDOWS_FONT_CHANGED_AT_MS} from '@app/features/theme/state/WindowsFont';
|
||||
import Nagbar from '@app/features/ui/state/Nagbar';
|
||||
import {hasUnavailableElectronNativeContext, isDesktop} from '@app/features/ui/utils/NativeUtils';
|
||||
import {hasUnavailableElectronNativeContext, isDesktop, isNativeWindows} from '@app/features/ui/utils/NativeUtils';
|
||||
import {isStandalonePwa} from '@app/features/ui/utils/PwaUtils';
|
||||
import {PRIVACY_SETUP_VERSION} from '@app/features/user/constants/PrivacySetupConstants';
|
||||
import StatusPage from '@app/features/user/state/StatusPage';
|
||||
import UserSettings from '@app/features/user/state/UserSettings';
|
||||
import Users from '@app/features/user/state/Users';
|
||||
import MediaEngine, {useVoiceEngineV2Model} from '@app/features/voice/engine/MediaEngineFacade';
|
||||
import {selectVoiceEngineV2AppConnectionWithFallback} from '@app/features/voice/engine/v2/VoiceEngineV2AppSelectors';
|
||||
@@ -260,6 +259,12 @@ export const useNagbarConditions = (): NagbarConditions => {
|
||||
})();
|
||||
const canShowSoftwareEncoder = SoftwareEncoderWarning.showWarning;
|
||||
const canShowStreamerMode = StreamerMode.shouldShowNagbar;
|
||||
const canShowWindowsFont =
|
||||
isNativeWindows() &&
|
||||
user != null &&
|
||||
user.createdAt.getTime() < WINDOWS_FONT_CHANGED_AT_MS &&
|
||||
!WindowsFont.useFluxerSans &&
|
||||
!WindowsFont.nagbarDismissed;
|
||||
const canShowDomainMoved = nagbarState.forceHideDomainMoved
|
||||
? false
|
||||
: nagbarState.forceDomainMoved
|
||||
@@ -287,13 +292,6 @@ export const useNagbarConditions = (): NagbarConditions => {
|
||||
(!user.privacyAgreedAt || user.privacyAgreedAt.toISOString() < PRIVACY_POLICY_LAST_UPDATED);
|
||||
return termsOutdated || privacyOutdated;
|
||||
})();
|
||||
const needsPrivacySetup = (() => {
|
||||
if (nagbarState.forceHidePrivacySetup) return false;
|
||||
if (nagbarState.forcePrivacySetup) return true;
|
||||
if (!user || !UserSettings.isHydrated()) return false;
|
||||
const privacySetupVersion = UserSettings.getPrivacySetupVersion();
|
||||
return privacySetupVersion !== null && privacySetupVersion < PRIVACY_SETUP_VERSION;
|
||||
})();
|
||||
return {
|
||||
canShowBuildEnvironment,
|
||||
canShowConnection,
|
||||
@@ -334,10 +332,10 @@ export const useNagbarConditions = (): NagbarConditions => {
|
||||
canShowVisionaryMfa,
|
||||
canShowVoiceSessionRestore,
|
||||
needsTermsAcceptance,
|
||||
needsPrivacySetup,
|
||||
canShowSoftwareEncoder,
|
||||
canShowStreamerMode,
|
||||
canShowDomainMoved,
|
||||
canShowWindowsFont,
|
||||
};
|
||||
};
|
||||
export const useActiveNagbars = (conditions: NagbarConditions): Array<NagbarState> => {
|
||||
@@ -367,12 +365,6 @@ export const useActiveNagbars = (conditions: NagbarConditions): Array<NagbarStat
|
||||
visible: conditions.needsTermsAcceptance,
|
||||
dismissible: false,
|
||||
},
|
||||
{
|
||||
type: NagbarType.PRIVACY_SETUP,
|
||||
priority: -2.75,
|
||||
visible: conditions.needsPrivacySetup,
|
||||
dismissible: false,
|
||||
},
|
||||
{
|
||||
type: NagbarType.SCHEDULED_MAINTENANCE,
|
||||
priority: -1,
|
||||
@@ -481,6 +473,12 @@ export const useActiveNagbars = (conditions: NagbarConditions): Array<NagbarStat
|
||||
visible: conditions.canShowDomainMoved,
|
||||
dismissible: true,
|
||||
},
|
||||
{
|
||||
type: NagbarType.WINDOWS_FONT,
|
||||
priority: 4.5,
|
||||
visible: conditions.canShowWindowsFont,
|
||||
dismissible: true,
|
||||
},
|
||||
];
|
||||
return selectVisibleNagbars(nagbars);
|
||||
}, [conditions]);
|
||||
|
||||
@@ -22,10 +22,10 @@ export const NagbarType = {
|
||||
VISIONARY_MFA: 'visionary-mfa',
|
||||
VOICE_SESSION_RESTORE: 'voice-session-restore',
|
||||
TERMS_ACCEPTANCE: 'terms-acceptance',
|
||||
PRIVACY_SETUP: 'privacy-setup',
|
||||
SOFTWARE_ENCODER: 'software-encoder',
|
||||
STREAMER_MODE: 'streamer-mode',
|
||||
DOMAIN_MOVED: 'domain-moved',
|
||||
WINDOWS_FONT: 'windows-font',
|
||||
} as const;
|
||||
|
||||
export type NagbarType = ValueOf<typeof NagbarType>;
|
||||
@@ -61,8 +61,8 @@ export interface NagbarConditions {
|
||||
canShowVisionaryMfa: boolean;
|
||||
canShowVoiceSessionRestore: boolean;
|
||||
needsTermsAcceptance: boolean;
|
||||
needsPrivacySetup: boolean;
|
||||
canShowSoftwareEncoder: boolean;
|
||||
canShowStreamerMode: boolean;
|
||||
canShowDomainMoved: boolean;
|
||||
canShowWindowsFont: boolean;
|
||||
}
|
||||
|
||||
@@ -17,13 +17,13 @@ import {PremiumExpiredNagbar} from '@app/features/app/components/layout/app_layo
|
||||
import {PremiumGracePeriodNagbar} from '@app/features/app/components/layout/app_layout/nagbars/PremiumGracePeriodNagbar';
|
||||
import {PremiumOnboardingNagbar} from '@app/features/app/components/layout/app_layout/nagbars/PremiumOnboardingNagbar';
|
||||
import {PriceAnnouncementNagbar} from '@app/features/app/components/layout/app_layout/nagbars/PriceAnnouncementNagbar';
|
||||
import {PrivacySetupNagbar} from '@app/features/app/components/layout/app_layout/nagbars/PrivacySetupNagbar';
|
||||
import {ScheduledMaintenanceNagbar} from '@app/features/app/components/layout/app_layout/nagbars/ScheduledMaintenanceNagbar';
|
||||
import {StreamerModeNagbar} from '@app/features/app/components/layout/app_layout/nagbars/StreamerModeNagbar';
|
||||
import {TermsAcceptanceNagbar} from '@app/features/app/components/layout/app_layout/nagbars/TermsAcceptanceNagbar';
|
||||
import {UnclaimedAccountNagbar} from '@app/features/app/components/layout/app_layout/nagbars/UnclaimedAccountNagbar';
|
||||
import {VisionaryMfaNagbar} from '@app/features/app/components/layout/app_layout/nagbars/VisionaryMfaNagbar';
|
||||
import {VoiceSessionRestoreNagbar} from '@app/features/app/components/layout/app_layout/nagbars/VoiceSessionRestoreNagbar';
|
||||
import {WindowsFontNagbar} from '@app/features/app/components/layout/app_layout/nagbars/WindowsFontNagbar';
|
||||
import {shouldShowPremiumFeatures} from '@app/features/premium/utils/PremiumUtils';
|
||||
import MobileLayout from '@app/features/ui/state/MobileLayout';
|
||||
import {SoftwareEncoderNagbar} from '@app/features/voice/components/SoftwareEncoderNagbar';
|
||||
@@ -81,14 +81,6 @@ export const NagbarContainer: React.FC<NagbarContainerProps> = observer(({nagbar
|
||||
data-flx="app.app-layout.nagbar-container.terms-acceptance-nagbar"
|
||||
/>
|
||||
);
|
||||
case NagbarType.PRIVACY_SETUP:
|
||||
return (
|
||||
<PrivacySetupNagbar
|
||||
key={nagbar.type}
|
||||
isMobile={mobileLayout.enabled}
|
||||
data-flx="app.app-layout.nagbar-container.privacy-setup-nagbar"
|
||||
/>
|
||||
);
|
||||
case NagbarType.SCHEDULED_MAINTENANCE:
|
||||
return (
|
||||
<ScheduledMaintenanceNagbar
|
||||
@@ -239,6 +231,14 @@ export const NagbarContainer: React.FC<NagbarContainerProps> = observer(({nagbar
|
||||
data-flx="app.app-layout.nagbar-container.domain-moved-nagbar"
|
||||
/>
|
||||
);
|
||||
case NagbarType.WINDOWS_FONT:
|
||||
return (
|
||||
<WindowsFontNagbar
|
||||
key={nagbar.type}
|
||||
isMobile={mobileLayout.enabled}
|
||||
data-flx="app.app-layout.nagbar-container.windows-font-nagbar"
|
||||
/>
|
||||
);
|
||||
default:
|
||||
throw new UnexpectedNagbarTypeError(nagbar.type);
|
||||
}
|
||||
|
||||
-55
@@ -1,55 +0,0 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {Nagbar} from '@app/features/app/components/layout/Nagbar';
|
||||
import {NagbarButton} from '@app/features/app/components/layout/NagbarButton';
|
||||
import {NagbarContent} from '@app/features/app/components/layout/NagbarContent';
|
||||
import {NAGBAR_TONES, NagbarToneKind} from '@app/features/app/components/layout/NagbarTones';
|
||||
import * as ModalCommands from '@app/features/ui/commands/ModalCommands';
|
||||
import {modal} from '@app/features/ui/commands/ModalCommands';
|
||||
import {PrivacySetupModal} from '@app/features/user/components/modals/PrivacySetupModal';
|
||||
import {msg} from '@lingui/core/macro';
|
||||
import {useLingui} from '@lingui/react/macro';
|
||||
import {observer} from 'mobx-react-lite';
|
||||
import {useCallback} from 'react';
|
||||
|
||||
const PRIVACY_SETUP_MESSAGE_DESCRIPTOR = msg({
|
||||
message: 'Choose who can send you direct messages.',
|
||||
comment: 'Nagbar body asking the user to review who can send them direct messages.',
|
||||
});
|
||||
const REVIEW_PRIVACY_SETTINGS_DESCRIPTOR = msg({
|
||||
message: 'Review privacy settings',
|
||||
comment: 'Button label on the privacy setup nagbar. Opens the privacy setup modal.',
|
||||
});
|
||||
export const PrivacySetupNagbar = observer(({isMobile}: {isMobile: boolean}) => {
|
||||
const {i18n} = useLingui();
|
||||
const handleOpen = useCallback(() => {
|
||||
ModalCommands.push(
|
||||
modal(() => (
|
||||
<PrivacySetupModal data-flx="app.app-layout.nagbars.privacy-setup-nagbar.handle-open.privacy-setup-modal" />
|
||||
)),
|
||||
);
|
||||
}, []);
|
||||
return (
|
||||
<Nagbar
|
||||
isMobile={isMobile}
|
||||
backgroundColor={NAGBAR_TONES[NagbarToneKind.BRAND].backgroundColor}
|
||||
textColor={NAGBAR_TONES[NagbarToneKind.BRAND].textColor}
|
||||
data-flx="app.app-layout.nagbars.privacy-setup-nagbar.nagbar"
|
||||
>
|
||||
<NagbarContent
|
||||
isMobile={isMobile}
|
||||
message={i18n._(PRIVACY_SETUP_MESSAGE_DESCRIPTOR)}
|
||||
actions={
|
||||
<NagbarButton
|
||||
isMobile={isMobile}
|
||||
onClick={handleOpen}
|
||||
data-flx="app.app-layout.nagbars.privacy-setup-nagbar.nagbar-button.open"
|
||||
>
|
||||
{i18n._(REVIEW_PRIVACY_SETTINGS_DESCRIPTOR)}
|
||||
</NagbarButton>
|
||||
}
|
||||
data-flx="app.app-layout.nagbars.privacy-setup-nagbar.nagbar-content"
|
||||
/>
|
||||
</Nagbar>
|
||||
);
|
||||
});
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {UserSettingsModal} from '@app/features/app/components/dialogs/LoadableSettingsModals';
|
||||
import {Nagbar} from '@app/features/app/components/layout/Nagbar';
|
||||
import {NagbarButton} from '@app/features/app/components/layout/NagbarButton';
|
||||
import {NagbarContent} from '@app/features/app/components/layout/NagbarContent';
|
||||
import {NAGBAR_TONES, NagbarToneKind} from '@app/features/app/components/layout/NagbarTones';
|
||||
import WindowsFont from '@app/features/theme/state/WindowsFont';
|
||||
import * as ModalCommands from '@app/features/ui/commands/ModalCommands';
|
||||
import {modal} from '@app/features/ui/commands/ModalCommands';
|
||||
import {getAdvancedSettingRowElementId} from '@app/features/user/components/modals/tabs/advanced_settings_tab/AdvancedSettingsItemUtils';
|
||||
import {msg} from '@lingui/core/macro';
|
||||
import {useLingui} from '@lingui/react/macro';
|
||||
import {observer} from 'mobx-react-lite';
|
||||
|
||||
const WINDOWS_FONT_CHANGED_DESCRIPTOR = msg({
|
||||
message: 'Text on Windows now uses the system font. You can switch back to Fluxer Sans in settings.',
|
||||
comment:
|
||||
'Nagbar message shown once to existing Windows users after the default app font changed to the Windows system font. Fluxer Sans is a font name and must not be translated.',
|
||||
});
|
||||
const SWITCH_BACK_DESCRIPTOR = msg({
|
||||
message: 'Switch back to Fluxer Sans',
|
||||
comment:
|
||||
'Nagbar button that opens the setting for switching the app font back to Fluxer Sans. Fluxer Sans is a font name and must not be translated.',
|
||||
});
|
||||
|
||||
export const WindowsFontNagbar = observer(({isMobile}: {isMobile: boolean}) => {
|
||||
const {i18n} = useLingui();
|
||||
const openSetting = () => {
|
||||
ModalCommands.push(
|
||||
modal(
|
||||
() => (
|
||||
<UserSettingsModal
|
||||
initialTab="advanced_settings"
|
||||
initialSubtab={getAdvancedSettingRowElementId('advanced-windows-fluxer-sans')}
|
||||
data-flx="app.app-layout.nagbars.windows-font-nagbar.open-setting.user-settings-modal"
|
||||
/>
|
||||
),
|
||||
'user-settings',
|
||||
),
|
||||
);
|
||||
};
|
||||
return (
|
||||
<Nagbar
|
||||
isMobile={isMobile}
|
||||
backgroundColor={NAGBAR_TONES[NagbarToneKind.BRAND].backgroundColor}
|
||||
textColor={NAGBAR_TONES[NagbarToneKind.BRAND].textColor}
|
||||
dismissible
|
||||
onDismiss={WindowsFont.dismissNagbar}
|
||||
data-flx="app.app-layout.nagbars.windows-font-nagbar.nagbar"
|
||||
>
|
||||
<NagbarContent
|
||||
isMobile={isMobile}
|
||||
onDismiss={WindowsFont.dismissNagbar}
|
||||
message={i18n._(WINDOWS_FONT_CHANGED_DESCRIPTOR)}
|
||||
actions={
|
||||
<NagbarButton
|
||||
isMobile={isMobile}
|
||||
onClick={openSetting}
|
||||
data-flx="app.app-layout.nagbars.windows-font-nagbar.switch-back-button"
|
||||
>
|
||||
{i18n._(SWITCH_BACK_DESCRIPTOR)}
|
||||
</NagbarButton>
|
||||
}
|
||||
data-flx="app.app-layout.nagbars.windows-font-nagbar.content"
|
||||
/>
|
||||
</Nagbar>
|
||||
);
|
||||
});
|
||||
@@ -63,6 +63,7 @@
|
||||
}
|
||||
|
||||
.settingsButton {
|
||||
position: relative;
|
||||
display: flex;
|
||||
height: 2.5rem;
|
||||
width: 2.5rem;
|
||||
@@ -78,6 +79,16 @@
|
||||
width: 1.25rem;
|
||||
}
|
||||
|
||||
.settingsIconWithDot {
|
||||
mask-image: radial-gradient(circle at 85% 15%, transparent 0.34375rem, #000 calc(0.34375rem + 0.03125rem));
|
||||
}
|
||||
|
||||
.settingsDot {
|
||||
position: absolute;
|
||||
top: 0.5625rem;
|
||||
right: 0.5625rem;
|
||||
}
|
||||
|
||||
.userInfo {
|
||||
margin-top: 0.75rem;
|
||||
}
|
||||
|
||||
@@ -8,13 +8,17 @@ import {OPEN_SETTINGS_DESCRIPTOR} from '@app/features/i18n/utils/CommonMessageDe
|
||||
import Presence from '@app/features/presence/state/Presence';
|
||||
import * as ModalCommands from '@app/features/ui/commands/ModalCommands';
|
||||
import {modal} from '@app/features/ui/commands/ModalCommands';
|
||||
import {NotificationDot} from '@app/features/ui/components/NotificationDot';
|
||||
import {Scroller} from '@app/features/ui/components/Scroller';
|
||||
import {StatusAwareAvatar} from '@app/features/ui/components/StatusAwareAvatar';
|
||||
import {openUserSettingsModal} from '@app/features/user/commands/UserSettingsModalCommands';
|
||||
import {NoteEditSheet} from '@app/features/user/components/modals/NoteEditSheet';
|
||||
import {UserProfileBadges} from '@app/features/user/components/popouts/UserProfileBadges';
|
||||
import {UserProfileBio, UserProfileMembershipInfo} from '@app/features/user/components/popouts/UserProfileShared';
|
||||
import {USER_SETTINGS_PRIVACY_REVIEW_NEEDED_DESCRIPTOR} from '@app/features/user/components/settings_utils/SettingsConstants';
|
||||
import {normalizeCustomStatus} from '@app/features/user/state/CustomStatus';
|
||||
import UserNote from '@app/features/user/state/UserNote';
|
||||
import UserSettings from '@app/features/user/state/UserSettings';
|
||||
import Users from '@app/features/user/state/Users';
|
||||
import * as AvatarUtils from '@app/features/user/utils/AvatarUtils';
|
||||
import * as NicknameUtils from '@app/features/user/utils/NicknameUtils';
|
||||
@@ -22,6 +26,7 @@ import {createMockProfile} from '@app/features/user/utils/ProfileUtils';
|
||||
import {msg} from '@lingui/core/macro';
|
||||
import {Trans, useLingui} from '@lingui/react/macro';
|
||||
import {GearIcon, NotePencilIcon, PencilIcon} from '@phosphor-icons/react';
|
||||
import {clsx} from 'clsx';
|
||||
import {observer} from 'mobx-react-lite';
|
||||
import {useMemo, useState} from 'react';
|
||||
|
||||
@@ -39,11 +44,7 @@ export const YouPage = observer(({onAvatarClick}: YouPageProps) => {
|
||||
const user = Users.currentUser;
|
||||
const userNote = user ? UserNote.getUserNote(user.id) : '';
|
||||
const [noteSheetOpen, setNoteSheetOpen] = useState(false);
|
||||
const handleSettings = () => {
|
||||
ModalCommands.push(
|
||||
modal(() => <UserSettingsModal data-flx="app.you-page.handle-settings.user-settings-modal" />, 'user-settings'),
|
||||
);
|
||||
};
|
||||
const privacySetupPending = UserSettings.isPrivacySetupPending();
|
||||
const handleEditProfile = () => {
|
||||
ModalCommands.push(
|
||||
modal(
|
||||
@@ -109,12 +110,23 @@ export const YouPage = observer(({onAvatarClick}: YouPageProps) => {
|
||||
<div className={styles.actions} data-flx="app.you-page.actions">
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleSettings}
|
||||
onClick={openUserSettingsModal}
|
||||
className={styles.settingsButton}
|
||||
aria-label={i18n._(OPEN_SETTINGS_DESCRIPTOR)}
|
||||
aria-label={
|
||||
privacySetupPending
|
||||
? i18n._(USER_SETTINGS_PRIVACY_REVIEW_NEEDED_DESCRIPTOR)
|
||||
: i18n._(OPEN_SETTINGS_DESCRIPTOR)
|
||||
}
|
||||
data-flx="app.you-page.settings-button"
|
||||
>
|
||||
<GearIcon className={styles.settingsIcon} weight="fill" data-flx="app.you-page.settings-icon" />
|
||||
<GearIcon
|
||||
className={clsx(styles.settingsIcon, privacySetupPending && styles.settingsIconWithDot)}
|
||||
weight="fill"
|
||||
data-flx="app.you-page.settings-icon"
|
||||
/>
|
||||
{privacySetupPending && (
|
||||
<NotificationDot className={styles.settingsDot} data-flx="app.you-page.privacy-review-dot" />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
<div className={styles.userInfo} data-flx="app.you-page.user-info">
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import {Routes} from '@app/app/Routes';
|
||||
import Accessibility from '@app/features/accessibility/state/Accessibility';
|
||||
import {ConfirmModal} from '@app/features/app/components/dialogs/ConfirmModal';
|
||||
import {UserSettingsModal} from '@app/features/app/components/dialogs/LoadableSettingsModals';
|
||||
import type {HandlerHost} from '@app/features/app/keybindings/keybind_manager/handlers/types';
|
||||
import {
|
||||
PUSH_TO_TALK_WHILE_DEAFENED_DESCRIPTION_DESCRIPTOR,
|
||||
@@ -49,6 +48,7 @@ import {getUnreadThreadIds} from '@app/features/threads/utils/ThreadViewUtils';
|
||||
import * as ModalCommands from '@app/features/ui/commands/ModalCommands';
|
||||
import {modal} from '@app/features/ui/commands/ModalCommands';
|
||||
import * as TextCopyCommands from '@app/features/ui/commands/TextCopyCommands';
|
||||
import {openUserSettingsModal} from '@app/features/user/commands/UserSettingsModalCommands';
|
||||
import {openVoiceMessageComposerModal} from '@app/features/voice/components/VoiceMessageComposerModal';
|
||||
import MediaEngine from '@app/features/voice/engine/MediaEngineFacade';
|
||||
import LocalVoiceState from '@app/features/voice/state/LocalVoiceState';
|
||||
@@ -255,7 +255,7 @@ export function registerDefaultKeybindHandlers(host: HandlerHost, i18n: I18n): v
|
||||
});
|
||||
host.register('system_toggle_settings', ({type}) => {
|
||||
if (type !== 'press') return;
|
||||
ModalCommands.push(modal(() => React.createElement(UserSettingsModal), 'user-settings'));
|
||||
openUserSettingsModal();
|
||||
});
|
||||
host.register('system_open_theme_studio_popout', ({type}) => {
|
||||
if (type !== 'press') return;
|
||||
|
||||
@@ -491,10 +491,5 @@
|
||||
position: absolute;
|
||||
bottom: 0.3rem;
|
||||
right: 0.35rem;
|
||||
width: 0.5rem;
|
||||
height: 0.5rem;
|
||||
border-radius: 624.9375rem;
|
||||
background-color: var(--status-danger);
|
||||
box-shadow: 0 0 0 0.08rem var(--channel-header-background);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
+2
-2
@@ -6,6 +6,7 @@ import {ChannelHeaderIcon} from '@app/features/channel/components/channel_header
|
||||
import {ChannelPinsPopout} from '@app/features/channel/components/popouts/ChannelPinsPopout';
|
||||
import type {Channel} from '@app/features/channel/models/Channel';
|
||||
import ReadStates from '@app/features/read_state/state/ReadStates';
|
||||
import {NotificationDot} from '@app/features/ui/components/NotificationDot';
|
||||
import {usePopout} from '@app/features/ui/hooks/usePopout';
|
||||
import {Popout} from '@app/features/ui/popover/PopoverPopout';
|
||||
import MobileLayout from '@app/features/ui/state/MobileLayout';
|
||||
@@ -43,9 +44,8 @@ export const ChannelPinsButton = observer(({channel}: ChannelPinsButtonProps) =>
|
||||
}
|
||||
}, [isMobile]);
|
||||
const indicator = hasUnreadPins ? (
|
||||
<div
|
||||
<NotificationDot
|
||||
className={styles.unreadPinIndicator}
|
||||
aria-hidden="true"
|
||||
data-flx="channel.channel-header-components.channel-pins-button.unread-pin-indicator"
|
||||
/>
|
||||
) : null;
|
||||
|
||||
@@ -66,10 +66,6 @@ const TERMS_ACCEPTANCE_NAGBAR_DESCRIPTOR = msg({
|
||||
message: 'Terms acceptance nagbar',
|
||||
comment: 'Developer control label for the terms-acceptance banner.',
|
||||
});
|
||||
const PRIVACY_SETUP_NAGBAR_DESCRIPTOR = msg({
|
||||
message: 'Privacy setup nagbar',
|
||||
comment: 'Developer control label for the privacy setup banner.',
|
||||
});
|
||||
const VOICE_SESSION_RESTORE_NAGBAR_DESCRIPTOR = msg({
|
||||
message: 'Voice session restore nagbar',
|
||||
comment: 'Developer control label for the voice-session-restore banner.',
|
||||
@@ -305,18 +301,6 @@ export const getNagbarControls = (): Array<NagbarControlDefinition> => [
|
||||
forceShowDisabled: (state) => state.forceTermsAcceptance,
|
||||
forceHideDisabled: (state) => state.forceHideTermsAcceptance,
|
||||
},
|
||||
{
|
||||
key: 'forcePrivacySetup',
|
||||
label: PRIVACY_SETUP_NAGBAR_DESCRIPTOR,
|
||||
forceKey: 'forcePrivacySetup',
|
||||
forceHideKey: 'forceHidePrivacySetup',
|
||||
resetKeys: ['forcePrivacySetup'],
|
||||
status: (state) =>
|
||||
state.forcePrivacySetup ? FORCE_ENABLED : state.forceHidePrivacySetup ? FORCE_DISABLED : USING_ACTUAL_STATE,
|
||||
useActualDisabled: (state) => !state.forcePrivacySetup && !state.forceHidePrivacySetup,
|
||||
forceShowDisabled: (state) => state.forcePrivacySetup,
|
||||
forceHideDisabled: (state) => state.forceHidePrivacySetup,
|
||||
},
|
||||
{
|
||||
key: 'forceDesktopDownload',
|
||||
label: DESKTOP_DOWNLOAD_NAGBAR_DESCRIPTOR,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -47,6 +47,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Shift"
|
||||
},
|
||||
@@ -127,6 +130,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Shift"
|
||||
},
|
||||
@@ -300,6 +306,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Shift"
|
||||
},
|
||||
@@ -810,6 +819,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Send"
|
||||
},
|
||||
@@ -1463,6 +1475,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Smileys"
|
||||
},
|
||||
@@ -1927,6 +1942,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Shift"
|
||||
},
|
||||
@@ -2104,6 +2122,12 @@
|
||||
{
|
||||
"msgid": "Added the tag {name}"
|
||||
},
|
||||
{
|
||||
"msgid": "Added {createdDate}, last used {lastUsedDate}"
|
||||
},
|
||||
{
|
||||
"msgid": "Added {createdDate}, never used"
|
||||
},
|
||||
{
|
||||
"msgid": "Allow AV1 for screen sharing"
|
||||
},
|
||||
@@ -2149,6 +2173,9 @@
|
||||
{
|
||||
"msgid": "Allows members to start threads that only invited members and moderators can see."
|
||||
},
|
||||
{
|
||||
"msgid": "Also change the communities below to match"
|
||||
},
|
||||
{
|
||||
"msgid": "An update for {appName} is available."
|
||||
},
|
||||
@@ -2173,6 +2200,9 @@
|
||||
{
|
||||
"msgid": "Anyone in my communities"
|
||||
},
|
||||
{
|
||||
"msgid": "Anyone who finds you can send a request. Turn this off to pick groups below."
|
||||
},
|
||||
{
|
||||
"msgid": "Anyone with this key can reset your password. Never share it."
|
||||
},
|
||||
@@ -2183,7 +2213,10 @@
|
||||
"msgid": "App audio isn't available right now on Windows."
|
||||
},
|
||||
{
|
||||
"msgid": "Apply to these communities too"
|
||||
"msgid": "Applies to bots in communities you join from now on. You can also change it for each community."
|
||||
},
|
||||
{
|
||||
"msgid": "Applies to communities you join from now on. You can also change it for each community."
|
||||
},
|
||||
{
|
||||
"msgid": "Approval required"
|
||||
@@ -2191,6 +2224,9 @@
|
||||
{
|
||||
"msgid": "Approve this app from the {productName} app you already use. No password needed."
|
||||
},
|
||||
{
|
||||
"msgid": "Apps and devices"
|
||||
},
|
||||
{
|
||||
"msgid": "Are you sure you want to delete {threadName}? This cannot be undone."
|
||||
},
|
||||
@@ -2200,6 +2236,9 @@
|
||||
{
|
||||
"msgid": "Ask for a passkey after your password when you sign in"
|
||||
},
|
||||
{
|
||||
"msgid": "Ask for a second step after your password when you sign in."
|
||||
},
|
||||
{
|
||||
"msgid": "Attach an image or a video to post in a media channel."
|
||||
},
|
||||
@@ -2275,9 +2314,15 @@
|
||||
{
|
||||
"msgid": "CSS files"
|
||||
},
|
||||
{
|
||||
"msgid": "Calls you allow still come through, but they don't ring."
|
||||
},
|
||||
{
|
||||
"msgid": "Camera access is needed for device previews"
|
||||
},
|
||||
{
|
||||
"msgid": "Can message you"
|
||||
},
|
||||
{
|
||||
"msgid": "Can't find {path}. Using the last loaded version."
|
||||
},
|
||||
@@ -2374,6 +2419,9 @@
|
||||
{
|
||||
"msgid": "Choose the reason again"
|
||||
},
|
||||
{
|
||||
"msgid": "Choose what happens to images and videos flagged as sensitive. Show displays them as usual, Blur hides them until you click, and Block hides them completely."
|
||||
},
|
||||
{
|
||||
"msgid": "Choose what members must have before they can post or DM community members. Members with roles can bypass these checks. For public spaces, we recommend enabling verification."
|
||||
},
|
||||
@@ -2381,7 +2429,16 @@
|
||||
"msgid": "Choose where its published messages should go. You can unfollow any time in Community settings → Webhooks."
|
||||
},
|
||||
{
|
||||
"msgid": "Choose who can send you direct messages."
|
||||
"msgid": "Choose whether people who share a community with you can send you direct messages without being friends first."
|
||||
},
|
||||
{
|
||||
"msgid": "Choose who can add you to a group chat without asking first."
|
||||
},
|
||||
{
|
||||
"msgid": "Choose who can send you a friend request."
|
||||
},
|
||||
{
|
||||
"msgid": "Choose who can start a call with you."
|
||||
},
|
||||
{
|
||||
"msgid": "Choose your defaults"
|
||||
@@ -2437,6 +2494,9 @@
|
||||
{
|
||||
"msgid": "Code from the {productName} app"
|
||||
},
|
||||
{
|
||||
"msgid": "Codes from your authenticator app are your second step when you sign in."
|
||||
},
|
||||
{
|
||||
"msgid": "Combobox"
|
||||
},
|
||||
@@ -2449,6 +2509,12 @@
|
||||
{
|
||||
"msgid": "Communities you can join"
|
||||
},
|
||||
{
|
||||
"msgid": "Communities you join from now on will use this."
|
||||
},
|
||||
{
|
||||
"msgid": "Communities you join from now on will use this. Your current communities keep their settings."
|
||||
},
|
||||
{
|
||||
"msgid": "Community overrides"
|
||||
},
|
||||
@@ -2644,6 +2710,9 @@
|
||||
{
|
||||
"msgid": "Cropping {percent}%"
|
||||
},
|
||||
{
|
||||
"msgid": "Current"
|
||||
},
|
||||
{
|
||||
"msgid": "Custom emoji {emojiName} from a community"
|
||||
},
|
||||
@@ -2680,6 +2749,9 @@
|
||||
{
|
||||
"msgid": "Delete other members' messages in this channel. Pinning is controlled separately."
|
||||
},
|
||||
{
|
||||
"msgid": "Delete passkey {passkeyName}"
|
||||
},
|
||||
{
|
||||
"msgid": "Delete prompt"
|
||||
},
|
||||
@@ -2722,6 +2794,9 @@
|
||||
{
|
||||
"msgid": "Disable direct messages and friend requests"
|
||||
},
|
||||
{
|
||||
"msgid": "Disable or delete your account"
|
||||
},
|
||||
{
|
||||
"msgid": "Disable translation DOM guard"
|
||||
},
|
||||
@@ -2969,7 +3044,13 @@
|
||||
"msgid": "Forum"
|
||||
},
|
||||
{
|
||||
"msgid": "Friends can always send you direct messages. Choose whether people who share a community with you can message you without sending a friend request first."
|
||||
"msgid": "Friends can always message you."
|
||||
},
|
||||
{
|
||||
"msgid": "Friends can always message you. These settings cover people and bots you only share a community with."
|
||||
},
|
||||
{
|
||||
"msgid": "Friends see which voice channel you're in on their Active now list. You can change this once every 24 hours."
|
||||
},
|
||||
{
|
||||
"msgid": "From {sourceGuildName}"
|
||||
@@ -3040,6 +3121,9 @@
|
||||
{
|
||||
"msgid": "Got it!"
|
||||
},
|
||||
{
|
||||
"msgid": "Group chats"
|
||||
},
|
||||
{
|
||||
"msgid": "H.265 (requires opt-in)"
|
||||
},
|
||||
@@ -3205,6 +3289,9 @@
|
||||
{
|
||||
"msgid": "Keep attachments when clearing an edit"
|
||||
},
|
||||
{
|
||||
"msgid": "Keep my current settings"
|
||||
},
|
||||
{
|
||||
"msgid": "Keep this page somewhere safe. If you forget your password, you can use it to get back into your account. Anyone with this recovery key can reset your password, so never share it."
|
||||
},
|
||||
@@ -3322,6 +3409,9 @@
|
||||
{
|
||||
"msgid": "Make the instance yours"
|
||||
},
|
||||
{
|
||||
"msgid": "Manage devices"
|
||||
},
|
||||
{
|
||||
"msgid": "Manage posts"
|
||||
},
|
||||
@@ -3331,9 +3421,18 @@
|
||||
{
|
||||
"msgid": "May cause compatibility issues for viewers. We’re working on improving this."
|
||||
},
|
||||
{
|
||||
"msgid": "Media in channels that are not marked 18+. Channels marked 18+ always show it."
|
||||
},
|
||||
{
|
||||
"msgid": "Media in group chats and in direct messages from people who aren't your friends."
|
||||
},
|
||||
{
|
||||
"msgid": "Media items you can save for later"
|
||||
},
|
||||
{
|
||||
"msgid": "Media your friends send you in direct messages."
|
||||
},
|
||||
{
|
||||
"msgid": "Members who can manage posts can add or remove it."
|
||||
},
|
||||
@@ -3436,6 +3535,9 @@
|
||||
{
|
||||
"msgid": "No part of {query} could be applied. Fix the underlined value or add something to search for."
|
||||
},
|
||||
{
|
||||
"msgid": "No passkeys yet. Add one to sign in with your fingerprint, face or a security key."
|
||||
},
|
||||
{
|
||||
"msgid": "No posts match your search"
|
||||
},
|
||||
@@ -3472,6 +3574,9 @@
|
||||
{
|
||||
"msgid": "Nothing to search for"
|
||||
},
|
||||
{
|
||||
"msgid": "Nothing will change. This just confirms your settings."
|
||||
},
|
||||
{
|
||||
"msgid": "OP"
|
||||
},
|
||||
@@ -3607,6 +3712,12 @@
|
||||
{
|
||||
"msgid": "Pay once and get a gift link to share. Gifts never renew."
|
||||
},
|
||||
{
|
||||
"msgid": "People in your communities can message you without being friends."
|
||||
},
|
||||
{
|
||||
"msgid": "People in your communities need to be your friend before they can message you."
|
||||
},
|
||||
{
|
||||
"msgid": "People need to be your friend before they can message you. They can still send you a friend request."
|
||||
},
|
||||
@@ -3619,6 +3730,12 @@
|
||||
{
|
||||
"msgid": "People who share a community with you can message you directly."
|
||||
},
|
||||
{
|
||||
"msgid": "People who share a community with you."
|
||||
},
|
||||
{
|
||||
"msgid": "People who share at least one friend with you."
|
||||
},
|
||||
{
|
||||
"msgid": "Per-device volume"
|
||||
},
|
||||
@@ -3718,9 +3835,6 @@
|
||||
{
|
||||
"msgid": "Print"
|
||||
},
|
||||
{
|
||||
"msgid": "Privacy setup nagbar"
|
||||
},
|
||||
{
|
||||
"msgid": "Private channel"
|
||||
},
|
||||
@@ -3802,6 +3916,9 @@
|
||||
{
|
||||
"msgid": "Reason (optional)."
|
||||
},
|
||||
{
|
||||
"msgid": "Receive calls silently"
|
||||
},
|
||||
{
|
||||
"msgid": "Recently active"
|
||||
},
|
||||
@@ -3853,6 +3970,9 @@
|
||||
{
|
||||
"msgid": "Removing the timeout will allow <0>{targetUserTag}</0> to send messages, react, and join voice channels again."
|
||||
},
|
||||
{
|
||||
"msgid": "Rename passkey {passkeyName}"
|
||||
},
|
||||
{
|
||||
"msgid": "Reply to message above"
|
||||
},
|
||||
@@ -3964,12 +4084,21 @@
|
||||
{
|
||||
"msgid": "Retry"
|
||||
},
|
||||
{
|
||||
"msgid": "Review needed"
|
||||
},
|
||||
{
|
||||
"msgid": "Review privacy settings"
|
||||
},
|
||||
{
|
||||
"msgid": "Review the permissions {productName} uses for voice, video, screen sharing, and shortcuts."
|
||||
},
|
||||
{
|
||||
"msgid": "Review who can message you"
|
||||
},
|
||||
{
|
||||
"msgid": "Right now"
|
||||
},
|
||||
{
|
||||
"msgid": "Run the instance as one community instead of many. This can only be enabled now, during setup."
|
||||
},
|
||||
@@ -4048,6 +4177,9 @@
|
||||
{
|
||||
"msgid": "See this channel. Denying it for {everyoneMention} makes the channel private."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Select the account you want to sign in with on your new device."
|
||||
},
|
||||
@@ -4165,6 +4297,9 @@
|
||||
{
|
||||
"msgid": "Show store folder"
|
||||
},
|
||||
{
|
||||
"msgid": "Show text in Fluxer Sans, the previous default font, instead of the Windows system font"
|
||||
},
|
||||
{
|
||||
"msgid": "Showed media download options"
|
||||
},
|
||||
@@ -4216,6 +4351,9 @@
|
||||
{
|
||||
"msgid": "Sign-in method"
|
||||
},
|
||||
{
|
||||
"msgid": "Sign-in methods"
|
||||
},
|
||||
{
|
||||
"msgid": "Signing in as {name}"
|
||||
},
|
||||
@@ -4348,6 +4486,9 @@
|
||||
{
|
||||
"msgid": "Subscriber badge on your profile"
|
||||
},
|
||||
{
|
||||
"msgid": "Switch back to Fluxer Sans"
|
||||
},
|
||||
{
|
||||
"msgid": "Switch price"
|
||||
},
|
||||
@@ -4381,9 +4522,15 @@
|
||||
{
|
||||
"msgid": "Tags help people find posts. You can add up to {count} tags."
|
||||
},
|
||||
{
|
||||
"msgid": "Take a moment to check who can message you. Nothing changes unless you choose to."
|
||||
},
|
||||
{
|
||||
"msgid": "Tap Share, then Add to Home Screen."
|
||||
},
|
||||
{
|
||||
"msgid": "Text on Windows now uses the system font. You can switch back to Fluxer Sans in settings."
|
||||
},
|
||||
{
|
||||
"msgid": "Thanks for flagging this"
|
||||
},
|
||||
@@ -4609,6 +4756,9 @@
|
||||
{
|
||||
"msgid": "Turn off audio sharing for this source or try again in a moment."
|
||||
},
|
||||
{
|
||||
"msgid": "Turn off authenticator app"
|
||||
},
|
||||
{
|
||||
"msgid": "Turn on"
|
||||
},
|
||||
@@ -4687,6 +4837,9 @@
|
||||
{
|
||||
"msgid": "Upload files and media in this channel."
|
||||
},
|
||||
{
|
||||
"msgid": "Use Fluxer Sans on Windows"
|
||||
},
|
||||
{
|
||||
"msgid": "Use a different account"
|
||||
},
|
||||
@@ -4747,6 +4900,9 @@
|
||||
{
|
||||
"msgid": "Used in Custom mode. The Gaming and Screen share presets set their own hint."
|
||||
},
|
||||
{
|
||||
"msgid": "User settings, privacy review needed"
|
||||
},
|
||||
{
|
||||
"msgid": "Username sign-in is still rolling out to the mobile apps. Full support on every platform is coming soon."
|
||||
},
|
||||
@@ -5171,7 +5327,7 @@
|
||||
"msgid": "{count, plural, one {# channel follows} other {# channels follow}} this channel. Converting it to a text channel removes those follows."
|
||||
},
|
||||
{
|
||||
"msgid": "{count, plural, one {# community uses a different setting} other {# communities use a different setting}}"
|
||||
"msgid": "{count, plural, one {# community has its own setting} other {# communities have their own setting}}"
|
||||
},
|
||||
{
|
||||
"msgid": "{count, plural, one {# file} other {# files}}"
|
||||
@@ -5191,6 +5347,9 @@
|
||||
{
|
||||
"msgid": "{count, plural, one {# new message} other {# new messages}}"
|
||||
},
|
||||
{
|
||||
"msgid": "{count, plural, one {# passkey} other {# passkeys}}"
|
||||
},
|
||||
{
|
||||
"msgid": "{count, plural, one {# video} other {# videos}}"
|
||||
},
|
||||
@@ -5457,6 +5616,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Social"
|
||||
},
|
||||
@@ -5846,6 +6008,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Social"
|
||||
},
|
||||
@@ -6180,6 +6345,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Slovakia"
|
||||
},
|
||||
@@ -6685,6 +6853,9 @@
|
||||
{
|
||||
"msgid": "Secret"
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Session"
|
||||
},
|
||||
@@ -6787,6 +6958,9 @@
|
||||
{
|
||||
"msgid": "{count, plural, one {# message} other {# messages}}"
|
||||
},
|
||||
{
|
||||
"msgid": "{count, plural, one {# passkey} other {# passkeys}}"
|
||||
},
|
||||
{
|
||||
"msgid": "{desktopChannel} Desktop {desktopVersion}"
|
||||
},
|
||||
@@ -7064,6 +7238,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Shift"
|
||||
},
|
||||
@@ -7320,6 +7497,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Shift"
|
||||
},
|
||||
@@ -7672,6 +7852,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Shift"
|
||||
},
|
||||
@@ -8179,6 +8362,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Shift"
|
||||
},
|
||||
@@ -8739,6 +8925,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Slovenia"
|
||||
},
|
||||
@@ -9122,6 +9311,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Shift"
|
||||
},
|
||||
@@ -9231,6 +9423,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Shift"
|
||||
},
|
||||
@@ -9364,6 +9559,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Shift"
|
||||
},
|
||||
@@ -9771,6 +9969,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Shift"
|
||||
},
|
||||
@@ -9906,6 +10107,9 @@
|
||||
{
|
||||
"msgid": "{context} · {accountName}"
|
||||
},
|
||||
{
|
||||
"msgid": "{count, plural, one {# passkey} other {# passkeys}}"
|
||||
},
|
||||
{
|
||||
"msgid": "{formattedPresenceCount} online"
|
||||
},
|
||||
@@ -10336,6 +10540,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Send"
|
||||
},
|
||||
@@ -10765,6 +10972,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Shift"
|
||||
},
|
||||
@@ -11141,6 +11351,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Shift"
|
||||
},
|
||||
@@ -11641,6 +11854,9 @@
|
||||
{
|
||||
"msgid": "Secret"
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Shift"
|
||||
},
|
||||
@@ -12037,6 +12253,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Shift"
|
||||
},
|
||||
@@ -12239,6 +12458,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Session"
|
||||
},
|
||||
@@ -12635,6 +12857,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Shift"
|
||||
},
|
||||
@@ -12816,6 +13041,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Shift"
|
||||
},
|
||||
@@ -13125,6 +13353,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Shift"
|
||||
},
|
||||
@@ -13297,6 +13528,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Shift"
|
||||
},
|
||||
@@ -13616,6 +13850,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Shift"
|
||||
},
|
||||
@@ -13736,6 +13973,9 @@
|
||||
{
|
||||
"msgid": "Searching..."
|
||||
},
|
||||
{
|
||||
"msgid": "Segoe UI"
|
||||
},
|
||||
{
|
||||
"msgid": "Shift"
|
||||
},
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user