diff --git a/Cargo.lock b/Cargo.lock index 6f9db13928c..08cd406d82e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1418,7 +1418,7 @@ dependencies = [ [[package]] name = "common" -version = "0.1.7" +version = "0.2.0" dependencies = [ "anyhow", "base64 0.20.0", @@ -2790,7 +2790,7 @@ dependencies = [ [[package]] name = "extensions" -version = "0.1.7" +version = "0.2.0" dependencies = [ "dioxus", "libloading 0.7.4", @@ -4235,7 +4235,7 @@ dependencies = [ [[package]] name = "icons" -version = "0.1.7" +version = "0.2.0" dependencies = [ "dioxus", "dioxus-html", @@ -4683,7 +4683,7 @@ dependencies = [ [[package]] name = "kit" -version = "0.1.7" +version = "0.2.0" dependencies = [ "arboard", "base64 0.20.0", @@ -9708,7 +9708,7 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "uplink" -version = "0.1.7" +version = "0.2.0" dependencies = [ "anyhow", "arboard", diff --git a/common/locales/bs-BA/bs-BA.ftl b/common/locales/bs-BA/bs-BA.ftl index dc8e8591129..24ecc06834b 100644 --- a/common/locales/bs-BA/bs-BA.ftl +++ b/common/locales/bs-BA/bs-BA.ftl @@ -45,6 +45,7 @@ uplink = Uplink .copy-text = Kopiraj text .copy = Kopiraj .paste = Zalijepi + .go-back = Idi nazad community = Zajednica .invited = Pozvan si! @@ -224,6 +225,13 @@ settings-profile = Postavke profila .status-idle = Neaktivan .status-do-not-disturb = Nemoj ometati .status-offline = Offline + .recovery-seed = Ključ za oporavak + .recovery-seed-description = Ovaj ključ predstavlja "glavni ključ" za vaš račun. Čuvajte ga sigurno na mjestu kako biste održali ispravnu kontrolu i sigurnost nad svojim Uplink računom. + .reveal-recovery-seed = Otkrij Ključ za Oporavak + .hide-recovery-seed = Sakrij Ključ za Oporavak + .store-on-account = Spremi ključ za oporavak na račun (onemogući ovo radi povećane sigurnosti) + .remove-recovery-seed = Ukloni Ključnu Riječ za Oporavak + .remove-recovery-seed-description = Uklanjanje ključne riječi iz pohrane može povećati sigurnost vašeg računa. Međutim, ova radnja je nepovratna, i ako niste prethodno napravili sigurnosnu kopiju ključne riječi, trebali biste odabrati 'Otkaži' ispod. settings-general = Opće postavke .overlay = Uplink Overlay @@ -277,10 +285,19 @@ settings-files = Postavke datoteka .open-sync-folder = Otvori mapu za sinkronizaciju .open-sync-folder-description = Otvori mapu gdje su vaše datoteke sinkronizirane. -settings-keybinds = Postavke tipkovnih prečaca +settings-keybinds = Postavke Tipkovnih Prečaca + .reset = Vrati na prethodno + .reset-keybinds = Vrati Tipkovne Prečace + .reset-keybinds-description = Vrati tipkovne prečace na zadane postavke. + .info = Globalni tipkovni prečaci su onemogućeni dok ste na ovoj stranici. Kliknite za uređivanje tipkovnih prečaca, pritisnite tipkovni prečac za označavanje i pronalaženje određenih prečaca. .increase-font-size = Povećaj veličinu fonta unutar Uplinka. .decrease-font-size = Smanji veličinu fonta unutar Uplinka. + .toggle-mute = Uključi/isključi mikrofon. + .toggle-deafen = Uključi/isključi sve zvukove, uključujući mikrofon i slušalice. + .conflicting-keybinds = Sukobljeni Tipkovni Prečaci. .change-keybind = Snimi novi tipkovni prečac + .open-dev-tools = Otvori Web Inspektora + .toggle-devmode = Uključi/isključi Razvojni Način .cancel-change-keybind = Odustani od snimanja settings-extensions = Postavke proširenja @@ -342,38 +359,53 @@ settings-about = O postavkama .made-in = Napravljeno u .team = Naš tim je širom svijeta s različitim pozadinama i svakodnevnim životima, svi rade na zajedničkom cilju izgradnje Uplinka i Satelita zajedno. -media-player = Media Player - .enable-camera = Omogući kameru +media-player = Multimedijski Preglednik + .enable-camera = Omogući Kameru .fullscreen = Puni zaslon - .popout-player = Iskočni player - .screenshare = Dijeljenje ekrana - -remote-controls = Daljinski upravljači - .mute = Bez zvuka - .unmute = Uključi zvuk + .popout-player = Izdvojeni Preglednik + .screenshare = Dijeljenje zaslona + +remote-controls = Daljinski Upravljači + .mute = Isključi zvuk + .unmute = Uključi zvuk .listen = Slušaj - .silence = Tišina - .start-recording = Počni snimati + .silence = Utihni + .start-recording = Počni snimanje .stop-recording = Zaustavi snimanje - .incoming-call = Dolazna prijenos ... - .outgoing-call = Odlazna prijenos ... + .incoming-call = Dolazni prijenos ... + .outgoing-call = Odlazni prijenos ... .empty = Nitko nije ovdje unlock = Otključaj - .notice = (ovo se koristi za šifriranje svih podataka koje Uplink pohranjuje na vašem računalu kad ga ne koristite, tako da nitko ne može čitati vaše podatke.) + .notice = (Ovo se koristi za šifriranje svih podataka koje Uplink pohranjuje na vašem računalu kada ga ne koristite kako nitko ne bi mogao čitati vaše podatke.) .enter-pin = Unesite PIN - .create-account = Stvori račun - .unlock-account = Otključaj račun + .create-account = Kreiraj Račun + .unlock-account = Otključaj Račun .welcome = Dobrodošli natrag, { $name } .create-password = Odaberite svoju lozinku - .error-pin = Nešto nije u redu s PIN-om koji ste naveli. - .invalid-pin = Hmm, taj PIN nije radio. - .error-unknown-pin = Dogodila se nepoznata pogreška. + .error-pin = Nešto nije u redu s unesenim PIN-om. + .invalid-pin = Hmm, taj PIN ne radi. + .error-unknown-pin = Došlo je do nepoznate pogreške. .help = Pomoć (desni klik) .logging-in = Prijavljivanje... +create-or-recover = Stvaranje Računa + .create = Stvori Novi Račun + .instructions = Kreirat ćemo račun za vas. Na sljedećem zaslonu vidjet ćete niz riječi. Screenshotajte ili ih zapišite. Ovo je jedini način za sigurnosnu kopiju vašeg računa. + .recover = Uvezi Račun + +copy-seed-words = Recovery Seed + .instructions = Zapišite ove riječi u redoslijedu u kojem se pojavljuju. Točan redoslijed je ključan prilikom obnavljanja računa. + .finished = Spremio Sam + +enter-seed-words = Recovery Seed + .instructions = Upišite vaš recovery seed ovdje. Možete unijeti jednu riječ po jednu ili sve odjednom razdvojene razmacima. + .submit = Obnovi Račun + .placeholder = Unesite Recovery Seed... + auth = Stvaranje računa .enter-username = Unesite korisničko ime + .enter-username-subtext = Vrijeme je da odaberete svoje korisničko ime, možete ga kasnije promijeniti u postavkama. sidebar = Bočna traka .subtext = { $user } poslao je više privitaka @@ -396,4 +428,3 @@ toast_actions = Akcije obavijesti .DisplayChat = Otvori razgovor .FriendListPending = Lista prijatelja .Dummy = Dummy akcija - \ No newline at end of file diff --git a/common/locales/en-US/main.ftl b/common/locales/en-US/main.ftl index 781671cd0d1..30c2e05dd75 100644 --- a/common/locales/en-US/main.ftl +++ b/common/locales/en-US/main.ftl @@ -229,6 +229,9 @@ settings-profile = Profile Settings .recovery-seed-description = This seed represents the "master key" for your account. Keep this safe and secure somewhere in order to maintain proper control and security over your Uplink account. .reveal-recovery-seed = Reveal Recovery Seed .hide-recovery-seed = Hide Recovery Seed + .store-on-account = Store recovery seed on account (disable this for increased security) + .remove-recovery-seed = Remove Seed Phrase + .remove-recovery-seed-description = Removing the seed phrase from storage can increase security on your account. However, this action is irreversable and if you have not backed up your seed phrase yet you should select 'Cancel' below. settings-general = General Settings .overlay = Uplink Overlay diff --git a/common/locales/hr-HR/hr-HR.ftl b/common/locales/hr-HR/hr-HR.ftl index dc8e8591129..24ecc06834b 100644 --- a/common/locales/hr-HR/hr-HR.ftl +++ b/common/locales/hr-HR/hr-HR.ftl @@ -45,6 +45,7 @@ uplink = Uplink .copy-text = Kopiraj text .copy = Kopiraj .paste = Zalijepi + .go-back = Idi nazad community = Zajednica .invited = Pozvan si! @@ -224,6 +225,13 @@ settings-profile = Postavke profila .status-idle = Neaktivan .status-do-not-disturb = Nemoj ometati .status-offline = Offline + .recovery-seed = Ključ za oporavak + .recovery-seed-description = Ovaj ključ predstavlja "glavni ključ" za vaš račun. Čuvajte ga sigurno na mjestu kako biste održali ispravnu kontrolu i sigurnost nad svojim Uplink računom. + .reveal-recovery-seed = Otkrij Ključ za Oporavak + .hide-recovery-seed = Sakrij Ključ za Oporavak + .store-on-account = Spremi ključ za oporavak na račun (onemogući ovo radi povećane sigurnosti) + .remove-recovery-seed = Ukloni Ključnu Riječ za Oporavak + .remove-recovery-seed-description = Uklanjanje ključne riječi iz pohrane može povećati sigurnost vašeg računa. Međutim, ova radnja je nepovratna, i ako niste prethodno napravili sigurnosnu kopiju ključne riječi, trebali biste odabrati 'Otkaži' ispod. settings-general = Opće postavke .overlay = Uplink Overlay @@ -277,10 +285,19 @@ settings-files = Postavke datoteka .open-sync-folder = Otvori mapu za sinkronizaciju .open-sync-folder-description = Otvori mapu gdje su vaše datoteke sinkronizirane. -settings-keybinds = Postavke tipkovnih prečaca +settings-keybinds = Postavke Tipkovnih Prečaca + .reset = Vrati na prethodno + .reset-keybinds = Vrati Tipkovne Prečace + .reset-keybinds-description = Vrati tipkovne prečace na zadane postavke. + .info = Globalni tipkovni prečaci su onemogućeni dok ste na ovoj stranici. Kliknite za uređivanje tipkovnih prečaca, pritisnite tipkovni prečac za označavanje i pronalaženje određenih prečaca. .increase-font-size = Povećaj veličinu fonta unutar Uplinka. .decrease-font-size = Smanji veličinu fonta unutar Uplinka. + .toggle-mute = Uključi/isključi mikrofon. + .toggle-deafen = Uključi/isključi sve zvukove, uključujući mikrofon i slušalice. + .conflicting-keybinds = Sukobljeni Tipkovni Prečaci. .change-keybind = Snimi novi tipkovni prečac + .open-dev-tools = Otvori Web Inspektora + .toggle-devmode = Uključi/isključi Razvojni Način .cancel-change-keybind = Odustani od snimanja settings-extensions = Postavke proširenja @@ -342,38 +359,53 @@ settings-about = O postavkama .made-in = Napravljeno u .team = Naš tim je širom svijeta s različitim pozadinama i svakodnevnim životima, svi rade na zajedničkom cilju izgradnje Uplinka i Satelita zajedno. -media-player = Media Player - .enable-camera = Omogući kameru +media-player = Multimedijski Preglednik + .enable-camera = Omogući Kameru .fullscreen = Puni zaslon - .popout-player = Iskočni player - .screenshare = Dijeljenje ekrana - -remote-controls = Daljinski upravljači - .mute = Bez zvuka - .unmute = Uključi zvuk + .popout-player = Izdvojeni Preglednik + .screenshare = Dijeljenje zaslona + +remote-controls = Daljinski Upravljači + .mute = Isključi zvuk + .unmute = Uključi zvuk .listen = Slušaj - .silence = Tišina - .start-recording = Počni snimati + .silence = Utihni + .start-recording = Počni snimanje .stop-recording = Zaustavi snimanje - .incoming-call = Dolazna prijenos ... - .outgoing-call = Odlazna prijenos ... + .incoming-call = Dolazni prijenos ... + .outgoing-call = Odlazni prijenos ... .empty = Nitko nije ovdje unlock = Otključaj - .notice = (ovo se koristi za šifriranje svih podataka koje Uplink pohranjuje na vašem računalu kad ga ne koristite, tako da nitko ne može čitati vaše podatke.) + .notice = (Ovo se koristi za šifriranje svih podataka koje Uplink pohranjuje na vašem računalu kada ga ne koristite kako nitko ne bi mogao čitati vaše podatke.) .enter-pin = Unesite PIN - .create-account = Stvori račun - .unlock-account = Otključaj račun + .create-account = Kreiraj Račun + .unlock-account = Otključaj Račun .welcome = Dobrodošli natrag, { $name } .create-password = Odaberite svoju lozinku - .error-pin = Nešto nije u redu s PIN-om koji ste naveli. - .invalid-pin = Hmm, taj PIN nije radio. - .error-unknown-pin = Dogodila se nepoznata pogreška. + .error-pin = Nešto nije u redu s unesenim PIN-om. + .invalid-pin = Hmm, taj PIN ne radi. + .error-unknown-pin = Došlo je do nepoznate pogreške. .help = Pomoć (desni klik) .logging-in = Prijavljivanje... +create-or-recover = Stvaranje Računa + .create = Stvori Novi Račun + .instructions = Kreirat ćemo račun za vas. Na sljedećem zaslonu vidjet ćete niz riječi. Screenshotajte ili ih zapišite. Ovo je jedini način za sigurnosnu kopiju vašeg računa. + .recover = Uvezi Račun + +copy-seed-words = Recovery Seed + .instructions = Zapišite ove riječi u redoslijedu u kojem se pojavljuju. Točan redoslijed je ključan prilikom obnavljanja računa. + .finished = Spremio Sam + +enter-seed-words = Recovery Seed + .instructions = Upišite vaš recovery seed ovdje. Možete unijeti jednu riječ po jednu ili sve odjednom razdvojene razmacima. + .submit = Obnovi Račun + .placeholder = Unesite Recovery Seed... + auth = Stvaranje računa .enter-username = Unesite korisničko ime + .enter-username-subtext = Vrijeme je da odaberete svoje korisničko ime, možete ga kasnije promijeniti u postavkama. sidebar = Bočna traka .subtext = { $user } poslao je više privitaka @@ -396,4 +428,3 @@ toast_actions = Akcije obavijesti .DisplayChat = Otvori razgovor .FriendListPending = Lista prijatelja .Dummy = Dummy akcija - \ No newline at end of file diff --git a/common/locales/pl/pl.ftl b/common/locales/pl/pl.ftl new file mode 100644 index 00000000000..294953af1fc --- /dev/null +++ b/common/locales/pl/pl.ftl @@ -0,0 +1,400 @@ +uplink = Uplink + .unknown = Unknown - Nieznany + .home = Strona główna + .add = Dodaj + .added = Dodane! + .add-members = Dodaj uczestników + .current-members = Aktualni uczestnicy + .call = Połączenie + .users = Użytkownicy + .groups = Grupy + .members = Uczestnicy + .members-count = Liczba uczestników: ({ $num }) + .reset-account = Zresetuj konto (Nieodwracalne!) + .coming-soon = Już wkrótce/Już niedługo + .chat = Rozmowa + .chats = Rozmowy + .send = Wyślij + .remove = Usuń + .cancel = Anuluj + .clear-unreads = Wyczyść nieodczytane + .delete-group-chat = Usuń grupę + .leave-group = Opuść grupę + .delete-conversation = Usuń rozmowę + .hide-chat = Ukryj rozmowę + .search-placeholder = Szukaj… + .nothing-here = Niczego nie znaleziono… + .end = Zakończ + .pre-release = Wersja przedpremierowa | Problemy/Opinie + .username = Nazwa użytkownika + .status = Status + .delete = Usuń + .dismiss = Odrzuć + .pick-download-directory = Wybierz miejsce do pobrania aktualizacji + .update-available = Dostępna aktualizacja: { $version } + .update-downloading = Pobierana aktualizacja: { $progress }% + .update-downloaded = Aktualizacja pobrana. Kliknij aby zainstalować. + .update-menu-dismiss = Odrzuć + .update-menu-download = Pobierz + .update-menu-install = Zainstaluj + .check-for-updates = Sprawdź dostępne aktualizacje + .download-update = Pobierz aktualizację + .date-time-format = %d/%m/%Y %H:%M %p + .open-devtools = Otwórz konsolę + .clear-unreads = Wyczyść nieprzeczytane + .copy-text = Kopiuj tekst + .copy = Kopiuj + .paste = Wklej + +community = Społeczność + .invited = Zostałeś zaproszony! + .join = Dołącz + .joined = Dołączono! + +updates = Aktualizacje + .title = Aktualizacja Uplink jest dostępna. Postępuj według danych kroków i zainstaluj najnowszą aktualizację. + .instruction1 = 1. Pobierz aktualizację z naszej strony + .instruction2 = 2. Zamknij Uplink + .instruction3 = 3. Otwórz instalator. Starsza wersja Uplink będzie nadpisana, pozostawiając twoje konto nienaruszone. + .instruction4 = 4. Otwórz Uplink i rozmawiaj ponownie! + .instruction5 = *Usprawnimy ten proces w następnych aktualizacjach + .download-label = Pobierz aktualizację + +warning-messages = Ostrzeżenie + .please-enter-at-least-one = Proszę wprowadź przynajmniej 1 znak + .please-enter-at-least = Proszę wprowadź przynajmniej następującą liczbę znaków: { $num } + .maximum-of = Przekroczono maksymalną liczbę znaków: { $num } + .disallowed-characters = Niedozwolone znak(i): { $chars } + .spaces-not-allowed = Spacje są niedozwolone + .error = Błąd + +messages = Wiadomości + .edit = Edytuj + .cancel-edit = Anuluj edycje + .new = Nowa wiadomość + .replying = Odpowiedź do: + .react = Zareaguj + .reply = Odpowiedz + .loading = Ładowanie… + .say-something-placeholder = Napisz coś… + .user-sent-message = { $user } wysłał/a Ci wiadomość + .unknown-sent-message = Ktoś wysłał/a Ci wiadomość + .msg-banner = Wiadomości są zabezpieczane przez szyfrowanie typu end-to-end and wysyłane poprzez sieć peer-to-peer. + .create-group-chat = Stwórz rozmowę grupową + .group-name = Nazwa grupy + .view = Zobacz wiadomości + .hide = Ukryj wiadomości + .blocked = { $amount } wiadomości zablokowanych + .group-name-invalid = Nieprawidłowa nazwa grupy + .fetching = Przynosze więcej wiadomości… + .group-creator-label = Twórca grupy + .user-typing = { $user } pisze… + .users-typing = { $users } piszą… + .users-multiple-typing = Wielu użytkowników pisze… + .maximum-amount-files-per-message = Osiągnąłeś limit { $amount } plików na wiadomość + .scroll-bottom = Przewiń do dołu + .pin = Przypnij wiadomość + .unpin = Odepnij wiadomość + .pin-view = Przypięte wiadomości + .pin-button-goto = Idź do + .pin-button-unpin = Odepnij + .pinned-none = Brak przypiętych wiadomości w tej rozmowie + .pinned-max = Osiągnąłeś maksymalną liczbę przypiętych wiadomości w tej rozmowie! + .missing-emoji-picker = Rozszerzenie emotikonki jest niedostępne + .unknown-identity = Nie znaleziono użytkownika: + .emoji-suggestion = Proponowane emotikony + .username-suggestion = Proponowani użytkownicy + .control-group = Więcej + +favorites = Ulubione + .favorites = Ulubione + .add = Dodaj do Ulubionych + .remove = Usuń z Ulubionych + +friends = Znajomi + .friends = Znajomi + .cta-text = Wszystko jest lepsze ze znajomymi + .add = Dodaj Kogoś + .go-to-friends = Idź do Znajomych + .placeholder = NazwaUżytkownika#0000 + .block = Zablokuj + .all = Wszyscy Znajomi + .remove = Usuń ze Znajomych + .edit-group = Edytuj Grupę + .view-group = Pokaż Grupę + .cannot-add-self = Przecież nie możesz dodać sam siebie! + .incoming_requests = Oczekujące prośby + .outgoing_requests = Wysłane prośby + .cancel = Anuluj prośbę + .requested = Prośba wysłana + .sent = Wysłane + .blocked-desc = Zablokowana/y + .add-existing-friend = Już jesteście znajomymi! + .add-failed = Dany użytkownik nie został znaleziony! + .pending = Oczekujące + .key-blocked = Użytkownik zablokowany/a + .blocked = Zablokowane + .accept = Zaakceptuj + .deny = Odrzuć prośbę + .request-sent = Prośba o dodanie do Znajomych wysłana! + .new-request = Nowa prośba o dodanie do Znajomych + .new-request-name = { $name } wysłał/a prośbę o dodanie do Znajomych + .copied-did = Skopiowano nazwę do schowku! + .unblock = Odblokuj + .request-exist = Ta prośba o dodanie do znajomych jest już oczekująca! + .add-name = Dodaj { $name } + .already-friends = Już jesteście Znajomymi! + .nothing-to-see-here = Nic tutaj nie ma + .share = Udostępnij DID + .select-chat = Wybierz rozmowę + .share-to-chat = Udostępnij w rozmowie + .search = Szukaj Znajomych + .search-placeholder = Szukaj Znajomego + +files = Pliki + .file = Plik + .files = Pliki + .new-folder = Nowy folder + .upload = Wyślij + .storage-max-size = Maksymalny rozmiar: + .storage-current-size = Aktualna przestrzeń: + .rename = Zmień nazwę: + .download = Pobierz + .thumbnail-uploaded = Wysłano miniaturkę + .no-thumbnail = Brak miniaturki + .one-file-to-upload = Liczba plików do wysłania: 1! + .files-to-upload = Liczba plików do wysłania: { $num }! + .no-thumbnail-preview = Brak dostępnej miniaturki do podglądu + .file-already-opened = Plik został już otworzony + .directory-already-with-name = Katalog z tą nazwą już istnieje + .no-size-available = Brak rozmiaru dostępnego dla pliku: { $file } + .file-already-with-name = Plik z tą nazwą już istnieje + .uploading-file = Wysyłam plik… + .finishing-upload = Kończę… + .cancelling-upload = Anuluję… + .checking-duplicated-name = Sprawdzam zduplikowaną nazwę… + .checking-thumbnail = Sprawdzam miniaturkę… + .files-in-queue = Pliki w kolejce + .error-to-upload = Błąd w wysyłaniu plików + .send-files-text-amount = Wyślij daną liczbę plików: { $amount } + .select-chats = Wybierz rozmowy + .attach-files-from-local-disk = Dodaj plik + .attach-files-from-storage = Przeglądaj pliki + .upload-in-progress-please-wait = Wysyłanie plików w trakcie. Proszę poczekaj + .no-files-available = Brak dodanych plików + .share-files = Udostępnij pliki + .go-to-files = Idź do Plików + .download-failed = Nieudane pobieranie pliku { $file } + .download-success = Pobrano plik { $file } + +settings = Ustawienia + .settings = Ustawienia + .profile = Profil + .general = Menu główne + .messages = Wiadomości + .privacy = Prywatność + .audio = Dźwięki & Audio + .files = Pliki + .extensions = Rozszerzenia + .keybinds = Skróty klawiszowe + .accessibility = Dostępność + .notifications = Powiadomienia + .developer = Deweloper + .about = O nas + .licenses = Licencje + .search-placeholder = Poszukaj w Ustawieniach… + .please-select-area-you-want-to-crop = Proszę wybierz obszar, który chcesz przyciąć + .no-extensions-installed = Brak zainstalowanych rozszerzeń + +settings-profile = Ustawienia profilu + .failed = Nie udało się zaktualizować profilu + .change-banner = Zmień baner + .clear-banner = Clear banner - Wyczyść baner + .clear-avatar = Wyczyść avatar + .too-large = Zbyt duży obraz + .welcome = Twój nowy profil! + .updated = Profil zaktualizowany + .welcome-desc = Opowiedz światu o sobie! A przynajmniej tyle ile możesz, kiedy my wciąż jesteśmy w budowie + .welcome-cta = Pierwszy krok, wybierz swoje zdjęcie profilowe! A może nawet baner? + .copy-id = Skopiuj ID + .copy-did = Skopiuj klucz DID + .online-status = Status Online + .online-status-description = Wybierz wygląd twojego statusu online + .status-online = Online + .status-idle = Zajęty + .status-do-not-disturb = Nie przeszkadzać + .status-offline = Offline + +settings-general = Ustawienia główne + .overlay = Nakładka Uplink + .overlay-description = Upoważnij nakładkę Uplink do wyświetlania na ekranie. Będzie ona pokazywać informację o aktywnych połączeniach, a także pozwoli Ci dodawać dopasowane widgety do twojego ekranu. + .app-language = Język aplikacji + .change-language = Zmień język + .theme = Motyw + .theme-description = Zmień motyw aplikacji + .font-scaling = Skalowanie czcionki + .font-scaling-description = Powiększ lub zmniejsz czcionkę zgodnie z Twoimi oczekiwaniami + .font = Czcionka + .font-description = Zmień czcionkę aplikacji + .clear-accent = Wyczyść kolor akcentu + +settings-messages = Ustawienia wiadomości + .emoji-conversion = Zmień emotki + .emoji-conversion-description = Zmień emotki tekstowe typu ‘:)’ w emotki graficzne, takie jak ‘😊’ + .markdown-support = Wsparcie markdown + .markdown-support-description = Uruchom wsparcie języka znaczników Markdown w wiadomościach + +settings-privacy = Ustawienia prywatności + .backup-recovery-phrase = Zdanie przywracające kopię zapasową + .backup-phrase = Zdanie przywracające + .backup-phrase-description = Powtórz to zdanie! Razem z hasłem odpowiadają one twojemu kontu. Jeśli je zgubisz, nie możemy pomóc Ci je odzyskać. + +settings-audio = Ustawienia dźwieku&audio + .input-device = Urządzenie wejściowe + .input-device-description = Wybierz swoje urządzenie wejściowe (zazwyczaj mikrofon) + .output-device = Urządzenie wyjściowe + .output-device-description = Czyli gdzie twoje dźwięki będą odtwarzane (zazwyczaj Twoje słuchawki) + .device-test = Test + .sample-rate = Dźwięk próbny + .sample-rate-description = Wyższe dźwięki próbne łapią więcej ‘dźwięków’ z Twojego audio i mają ‘czystsze’ brzmienie + .noise-suppression = Tłumienie szumów + .noise-suppression-description = Pomaga zmniejszyć dźwięki w tle do minimum i skupić się na Twoim głosie + .echo-cancellation = Wyciszenie echa + .echo-cancellation-description = Pomaga zmniejszyć przekaz z Twoich głośników do mikrofonu + .call-timer = Czas połączenia + .call-timer-description = Po włączeniu czas trwania aktywnego połączenia będzie pokazywany na ekranie + .interface-sounds = Dźwięki interfejsu + .interface-sounds-description = Po włączeniu podczas Twojej interakcji z aplikacji będa odtwarzane dodatkowe dźwieki + .media-sounds = Dźwięki mediów + .media-sounds-description = Po włączeniu odtwarzane będą dźwięki wydarzeń związanych z mediami (takie jak włączenie mikrofonu lub słuchawek, a także inne wydarzenia odbywające się w danym momencie). + .message-sounds = Dźwięki wiadomości + .message-sounds-description = Po włączeniu będziesz otrzymywać dźwięk powiadomienia z każdą nową wiadomością. + .failed = Nieudana aktualizacja ustawień. + +settings-files = Ustawienia plików + .local-sync = Synchronizacja lokalna + .local-sync-description = Po włączeniu pliki będą synchronizowane z Twoim urządzeniem + .open-sync-folder = Otwórz Folder Zsynchronizowany + .open-sync-folder-description = Otwórz folder zawierający Twoje synchronizowane pliki + +settings-keybinds = Ustawienia klawiszy + .increase-font-size = Powiększ rozmiar czcionki w aplikacji Uplink + .decrease-font-size = Zmniejsz rozmiar czcionki w aplikacji Uplink + .change-keybind = Skrót klawiszowy dla rozpoczęcia nagrywania + .cancel-change-keybind = Skrót klawiszowy dla anulowania nagrywania + +settings-extensions = Ustawienia rozszerzeń + .open-extensions-folder = Otwórz Rozszerzenia + .auto-enable = Uruchom automatycznie + .auto-enable-description = Po włączeniu, nowe rozszerzenia będą uruchamiane automatycznie + .banner = Rozszerzenia są prekompilowane na urządzeniach zewnętrznych. Dla dodatkowej ochrony możesz skompilować rozszerzenia ze źródła i umieścić je w folderze Rozszerzeń. + .open-folder-description = Otwórz katalog lokalny zawierający Twoje zainstalowane Rozszerzenia. + .installed = Zainstalowane + .explore = Przeglądaj + .settings = Ustawienia + +settings-accessibility = Ustawienia dostępności + .dyslexia = Open Dyslexic + .dyslexia-description = Uruchom 'OpenDyslexic', aby włączyć czcionkę ułatwiającą czytanie dla osób z dysleksją + +settings-notifications = Powiadomienia + .enabled = Włączone + .enabled-description = Włącz powiadomienia dla połączeń przychodzących, wiadomości i więcej + .grant-permissions = Przyznaj dostęp + .grant-permissions-description = Wyraź zgodę na otrzymanie powiadomień + .friends-description = Enable notifications for friend requests - Uruchom powiadomienia o zaproszeniach do znajomych + + + .messages-description = Uruchom powiadomienia o nowych wiadomościach + .settings-description = Uruchom powiadomienia o aktualizacjach i alarmach + +settings-developer = Ustawienia developerskie + .developer-mode = Tryb dewelopera + .developer-mode-description = Włączenie trybu dewelopera dodaje logowanie oraz wyświetla informacje przydatne w debugowaniu w interfejsie użytkownika. + .experimental-features = Funkcje eksperymentalne + .experimental-features-description = Uruchamia funkcje eksperymentalne, które mogą być niekompletne bądź niedziałające + .test-notification = Test powiadomień + .test-notification-description = Wysyłane jest powiadomienie testowe + .test-popup = Test + .open-cache = Otwórz pamięć podręczną (cache) + .open-cache-description = Otwórz pamięć podręczną (cache) w domyślnym folderze przeglądarki + .open-cache-folder = Otwórz folder + .compress-download-cache = Skompresuj oraz pobierz pamięć podręczną (cache) + .compress-download-cache-description = Dla debugowania z innymi deweloperami, możesz skompresować swoją pamięć podręczna (cache) do formatu .zip i ją udostępnić. Nie rób tego jeśli jest to twoje prawdziwe konto. + .compress = Skompresuj + .clear-cache = Wyczyść pamięć podręczna (cache) + .clear-cache-description = Działa to jak zresetowanie Twojego konta + .clear = Wyczyść + .save-logs-to-file = Zapisz swoje logi w folderze + .save-logs-to-file-description = Po włączeniu tej opcji logi będą zapisywane w folderze oraz będą trwałe. + .print-state = Wydrukuj status + .print-state-description = Pokaż status w rejestratorze debugowania + +settings-about = O ustawieniach + .info = O + .version = Wersja + .open-website = Otwórz naszą stronę + .open-website-description = Otwórz naszą stronę w Twojej domyślnej przeglądarce internetowej + .open-codebase = Otwórz kod źródłowy + .open-codebase-description = Otwiera kod źródłowy w Twojej domyślnej przeglądarce internetowej + .no-update-available = Twoje oprogramowanie jest aktualne! + .update-check-error = Nie udało się pobrać aktualizacji. Sprawdź swoje logi aby uzyskać więcej informacji + .update-check-error-timeout = Nie udało się pobrać aktualizacji! Upłynął limit czasu żądania + .update-check-error-request = Nie udało się pobrać aktualizacji! Nie udało się pobrać aktualizacji. Sprawdź swoje połączenie internetowej. + .made-in = Stworzone w + .team = Nasz zespół tworzą osoby z całego świata - posiadające różne pochodzenie, życie codziennie, ale mające wspólny cel - wspólne tworzenie i praca nad Uplink oraz Satellite. + +media-player = Odtwarzacz multimedialny + .enable-camera = Uruchom kamerę + .fullscreen = Pełny ekran + .popout-player = Otwórz odtwarzacz w nowym oknie + .screenshare = Udostępnij swój ekran + +remote-controls = Zdalne sterowanie + .mute = Wycisz + .unmute = Wyłącz wyciszenie + .listen = Słuchaj + .silence = Cisza + .start-recording = Rozpocznij nagrywanie + .stop-recording = Zakończ nagrywanie + .incoming-call = Przychodząca transmisja + .outgoing-call = Wychodząca transmisja + .empty = Nikogo tu nie ma + +unlock = Odblokuj + .notice = (Służy to do szyfrowania wszystkich danych przechowywanych przez Uplink na twoim komputerze kiedy z niego nie korzystasz, aby nikt nie mógł odczytywać Twoich danych.) + .enter-pin = Wprowadź PIN + .create-account = Stwórz konto + .unlock-account = Odblokuj konto + .welcome = Witaj z powrotem, { $name } + .create-password = Stwórz swoje hasło + .error-pin = Pin podany przez Ciebie jest niepoprawny + .invalid-pin = Podany PIN jest nieprawidłowy + .error-unknown-pin = Nastąpił nieznany błąd + .help = Pomoc (prawy przycisk) + .logging-in = Trwa logowanie… + +auth = Stwórz konto + .enter-username = Wpisz nazwę użytkownika + +sidebar = boczny + .subtext = { $user } wysłał/a wiele załączników + .chat-new = Brak wiadomości, wyślij pierwszą! + +quickprofile = Szybki profil + .profile = Profil + .message = Wiadomość + .call = Połączenie + .friend-remove = Usuń Znajomego + .block = Zablokuj użytkownika + .unblock = Odblokuj użytkownika + .chat-placeholder = Wiadomość + .self-edit = Edytuj profil + .volume = Głośność użytkownika + .friend-request = Wyślij prośbę o dodanie do Znajomych + .pending-friend-request = Oczekująca prośba o dodanie do Znajomych + +toast_actions = Toast Actions + .DisplayChat = Otwórz rozmowę + .FriendListPending = Lista znajomych + .Dummy = Akcja fikcyjna (dummy action) diff --git a/common/locales/sr-RS/sr-RS.ftl b/common/locales/sr-RS/sr-RS.ftl index b8714e4076c..171077ac939 100644 --- a/common/locales/sr-RS/sr-RS.ftl +++ b/common/locales/sr-RS/sr-RS.ftl @@ -45,6 +45,7 @@ uplink = Uplink .copy-text = Копирај текст .copy = Копирај .paste = Залепи + .go-back = Врати се community = Заједница .invited = Позвани сте! @@ -224,6 +225,13 @@ settings-profile = Подешавања профила .status-idle = Неактиван .status-do-not-disturb = Не ометај .status-offline = Изван мреже + .recovery-seed = Семе за обнављање + .recovery-seed-description = Ово семе представља "главни клуч" за ваш налог. Сачувајте га на безбедном и сигурном месту како бисте одржали контролу и безбедност свог Uplink налога. + .reveal-recovery-seed = Откриј Семе за обнављање + .hide-recovery-seed = Сакриј Семе за обнављање + .store-on-account = Сачувај семе за обнављање на налогу (онемогућите ово за повећану безбедност) + .remove-recovery-seed = Уклони Семе фразе за обнављање + .remove-recovery-seed-description = Уклањање семена фразе из складишта може повећати безбедност на вашем налогу. Међутим, ова радња је неопозива и ако још увек нисте направили резервну копију своје семена фразе, требало би да изаберете 'Откажи' испод. settings-general = Генерална подешавања .overlay = Uplink Overlay @@ -277,21 +285,30 @@ settings-files = Подешавања Фајлова .open-sync-folder = Отвори фолдер синхронизације .open-sync-folder-description = Отвори фолдер где су твоји фајлови синхронизовани. -settings-keybinds = Подешавања Пречица Тастатуре - .increase-font-size = Увећај величину фонтова у Уплинку. - .decrease-font-size = Смањи величину фонтова у Уплинку. - .change-keybind = Сними нову пречицу тастатуре - .cancel-change-keybind = Откажи снимање +settings-keybinds = Поставке тастатурских пречица + .reset = Поништи + .reset-keybinds = Поништи тастатурске пречице + .reset-keybinds-description = Вратите тастатурске пречице на подразумеване мапинге. + .info = Глобалне тастатурске пречице су онемогућене на овој страници. Кликните да бисте изменели тастатурску пречицу, притисните тастатурску пречицу да бисте је истакли и пронашли одређени скраћеница. + .increase-font-size = Увећајте величину фонта у Уплинку. + .decrease-font-size = Смањите величину фонта у Уплинку. + .toggle-mute = Искључите и укључите микрофон. + .toggle-deafen = Промените искључивање свих звукова, укључујући микрофон и слушалице. + .conflicting-keybinds = Сукоб тастатурских пречица. + .change-keybind = Запиши нову тастатурску пречицу + .open-dev-tools = Отвори веб инспектор + .toggle-devmode = Промени режим програмера + .cancel-change-keybind = Откажи записivanje -settings-extensions = Подешавања Екстензија - .open-extensions-folder = Отвори фолдер за екстензије +settings-extensions = Поставке додатака + .open-extensions-folder = Отвори фасциклу са додацима .auto-enable = Аутоматско омогућавање - .auto-enable-description = Када је укључено, нове екстензије ће аутоматски бити укључене као подразумеване. - .banner = Екстензије су претпроцесиране на спољнем хардверу. Ради додатне безбедности, можете компајлирати екстензије из изворног кода и поставити их у фолдер `extensions`. - .open-folder-description = Отвори локални директоријум са инсталираним екстензијама. - .installed = Инсталиране + .auto-enable-description = Када је укључено, нови додаци ће аутоматски бити омогућени као подразумевано. + .banner = Додаци су претходно компајлирани на спољним хардверима. Ради додатне безбедности, можете компајлирати додатке из изворног кода и ставити их у фасциклу extensions. + .open-folder-description = Отвори локални директоријум са инсталираним додацима. + .installed = Инсталирани .explore = Истражи - .settings = Подешавања + .settings = Поставке settings-accessibility = Подешавања Приступачности .dyslexia = Отвори Дислексични фонт @@ -306,7 +323,6 @@ settings-notifications = Подешавања Обавештења .messages-description = Омогући обавештења за нове поруке. .settings-description = Омогући обавештења за ажурирања и важна обавештења. - settings-developer = Подешавања за Развијача .developer-mode = Режим развијача .developer-mode-description = Укључивање режима развијача додаје записивање и приказ корисних информација за дебагирање на корисничком интерфејсу. @@ -373,8 +389,23 @@ unlock = Откључај .help = Помоћ (десни клик) .logging-in = Пријављивање... +create-or-recover = Креирање Налога + .create = Креирај Нови Налог + .instructions = Креираћемо налог за тебе. На следећем екрану видећеш сет речи. Ухвати слику или их запиши. Ово је једини начин за бекап твог налога. + .recover = Увези Налог + +copy-seed-words = Речи За Повратак Налога + .instructions = Запиши ове речи у редоследу у коме се појављују. Имати тачан редослед је битан када повраћаш свој налог. + .finished = Сачувано + +enter-seed-words = Речи За Повратак Налога + .instructions = Унеси твоје речи за повратак овде. Можеш уносити по једну реч или све одједном, раздвојене размаком. + .submit = Поврати Налог + .placeholder = Унеси Речи За Повратак... + auth = Креирај Налог .enter-username = Унесите Корисничко Име + .enter-username-subtext = Време је да изаберете своје корисничко име, можете касније променити ово у било које време у поставкама. sidebar = Бочна Трака .subtext = { $user } послао је више прилога @@ -397,4 +428,3 @@ toast_actions = Акције Тоста .DisplayChat = Отвори Ћасканје .FriendListPending = Листа Пријатеља .Dummy = Лажна Акција - \ No newline at end of file diff --git a/common/src/language/mod.rs b/common/src/language/mod.rs index 94bd220ef62..7b7f9165922 100644 --- a/common/src/language/mod.rs +++ b/common/src/language/mod.rs @@ -25,6 +25,7 @@ static LANGUAGES: Lazy> = La add(&mut map, &(langid!("de"), "Deutsch")); add(&mut map, &(langid!("sr-RS"), "Serbia (Srbija)")); add(&mut map, &(langid!("hr-HR"), "Croatia (Hrvatska)")); + add(&mut map, &(langid!("pl"), "Polski (Polska)")); add( &mut map, &( diff --git a/common/src/lib.rs b/common/src/lib.rs index 568c320b59f..fcaff79cc87 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -103,7 +103,7 @@ pub struct StaticArgs { /// a debug log which is only written to when the settings are enabled. otherwise logs are only sent to stdout pub logger_path: PathBuf, /// contains the keypair used for IPFS - pub tesseract_path: PathBuf, + pub tesseract_file: String, /// the unlock and auth pages don't have access to State but need to know if they should play a notification. /// part of state is serialized and saved here pub login_config_path: PathBuf, @@ -158,7 +158,7 @@ pub static STATIC_ARGS: Lazy = Lazy::new(|| { logger_path: uplink_path.join("debug.log"), typing_indicator_refresh: 5, typing_indicator_timeout: 6, - tesseract_path: warp_path.join("tesseract.json"), + tesseract_file: "tesseract.json".into(), login_config_path: uplink_path.join("login_config.json"), use_mock, discovery: args.discovery.unwrap_or_default(), diff --git a/common/src/warp_runner/manager/commands/tesseract_commands.rs b/common/src/warp_runner/manager/commands/tesseract_commands.rs index 3e87c639697..76c27f36400 100644 --- a/common/src/warp_runner/manager/commands/tesseract_commands.rs +++ b/common/src/warp_runner/manager/commands/tesseract_commands.rs @@ -10,6 +10,14 @@ pub enum TesseractCmd { GetMnemonic { rsp: oneshot::Sender>, }, + #[display(fmt = "DeleteMnemonic")] + DeleteMnemonic { + rsp: oneshot::Sender>, + }, + #[display(fmt = "CheckMnemonicExist")] + CheckMnemonicExist { + rsp: oneshot::Sender>, + }, } impl std::fmt::Debug for TesseractCmd { @@ -19,7 +27,17 @@ impl std::fmt::Debug for TesseractCmd { } pub fn handle_tesseract_cmd(cmd: TesseractCmd, tesseract: &Tesseract) { - if let TesseractCmd::GetMnemonic { rsp } = cmd { - let _ = rsp.send(tesseract.retrieve("mnemonic")); + match cmd { + TesseractCmd::AccountExists { rsp: _ } => {} + TesseractCmd::GetMnemonic { rsp } => { + let _ = rsp.send(tesseract.retrieve("mnemonic")); + } + TesseractCmd::DeleteMnemonic { rsp } => { + let _ = rsp.send(tesseract.delete("mnemonic")); + } + TesseractCmd::CheckMnemonicExist { rsp } => { + let exists = tesseract.exist("mnemonic"); + let _ = rsp.send(Ok(exists)); + } } } diff --git a/common/src/warp_runner/mod.rs b/common/src/warp_runner/mod.rs index 6c41817d921..08e79f24433 100644 --- a/common/src/warp_runner/mod.rs +++ b/common/src/warp_runner/mod.rs @@ -189,15 +189,9 @@ async fn handle_login(notify: Arc) { location: multipass::ImportLocation::Remote, passphrase: seed_words }).await { - Ok(ident) => match save_tesseract(&warp.tesseract) { - Ok(_) => { - let _ = rsp.send(Ok(ident)); - break Some(warp); - } - Err(e) => { - let _ = rsp.send(Err(e)); - continue; - } + Ok(ident) => { + let _ = rsp.send(Ok(ident)); + break Some(warp); }, Err(e) => { warp.tesseract.lock(); @@ -234,15 +228,9 @@ async fn handle_login(notify: Arc) { }; match warp.multipass.create_identity(Some(&username), Some(&seed_words)).await { Ok(_id) => match wait_for_multipass(&mut warp, notify.clone()).await { - Ok(ident) => match save_tesseract(&warp.tesseract) { - Ok(_) => { - let _ = rsp.send(Ok(ident)); - break Some(warp); - } - Err(e) => { - let _ = rsp.send(Err(e)); - continue; - } + Ok(ident) => { + let _ = rsp.send(Ok(ident)); + break Some(warp); }, Err(e) => { warp.tesseract.lock(); @@ -330,62 +318,26 @@ async fn wait_for_multipass( // assumes that all anyone needs from tesseract is "keypair" // otherwise, Tesseract::to_file probably needs to call file.sync_all() async fn init_tesseract(overwrite_old_account: bool) -> Result { - log::trace!("initializing tesseract"); - - let configure_tesseract = |tesseract: Tesseract| { - // prevent other things from corrupting the real tesseract file. - tesseract.set_file(STATIC_ARGS.warp_path.join("fake_tesseract.json")); - tesseract.set_autosave(); - tesseract - }; - - // this code path addresses cross-platform issues involving account recreation. - // the tesseract file was being overwritten incorrectly. - // to fix this, manually delete the file and re-create it. - if overwrite_old_account { - // delete old account data - if let Err(e) = std::fs::remove_dir_all(&STATIC_ARGS.uplink_path) { - log::warn!("failed to delete uplink directory: {}", e); - } - - // create directories - if let Err(e) = std::fs::create_dir_all(&STATIC_ARGS.warp_path) { - log::warn!("failed to create warp directory: {}", e); - } + tokio::task::spawn_blocking(move || { + log::trace!("initializing tesseract"); - // create the tesseract key file so it can be saved later - if let Err(e) = std::fs::File::create(&STATIC_ARGS.tesseract_path) { - log::error!("failed to create tesseract file: {}", e); - return Err(warp::error::Error::CannotSaveTesseract); - } - - return Ok(configure_tesseract(Tesseract::default())); - } - - // open existing file or create new one - let tesseract = match std::fs::File::open(&STATIC_ARGS.tesseract_path) { - Ok(mut file) => match Tesseract::from_reader(&mut file) { - Ok(tesseract) => configure_tesseract(tesseract), - Err(e) => { - log::error!("failed to deserialize tesseract: {}", e); - log::warn!("creating new tesseract"); - configure_tesseract(Tesseract::default()) + if overwrite_old_account { + // delete old account data + if let Err(e) = std::fs::remove_dir_all(&STATIC_ARGS.uplink_path) { + log::warn!("failed to delete uplink directory: {}", e); } - }, - Err(e) => { - log::error!("failed to open file: {}", e); - log::warn!("creating new tesseract"); - // create the file so it can be saved later - if let Err(e) = std::fs::File::create(&STATIC_ARGS.tesseract_path) { - log::error!("failed to create tesseract file: {}", e); - return Err(warp::error::Error::CannotSaveTesseract); + // create directories + if let Err(e) = std::fs::create_dir_all(&STATIC_ARGS.warp_path) { + log::warn!("failed to create warp directory: {}", e); } - configure_tesseract(Tesseract::default()) } - }; - Ok(tesseract) + // open existing file or create new one + Tesseract::open_or_create(&STATIC_ARGS.warp_path, &STATIC_ARGS.tesseract_file) + }) + .await + .map_err(anyhow::Error::from)? } impl From<&DiscoveryMode> for Discovery { @@ -469,30 +421,3 @@ async fn warp_initialization(tesseract: Tesseract) -> Result Result<(), Error> { - log::info!("saving tesseract"); - let mut file = match std::fs::OpenOptions::new() - .write(true) - .append(false) - .create(false) - .open(&STATIC_ARGS.tesseract_path) - { - Ok(f) => f, - Err(e) => { - log::error!("failed to open tesseract keystore for saving: {}", e); - return Err(Error::CorruptedDataStore); - } - }; - if let Err(e) = tesseract.to_writer(&mut file) { - log::error!("tesseract.to_writer() failed: {}", e); - return Err(e); - } - - if let Err(e) = file.sync_all() { - log::error!("failed to sync tesseract: {}", e); - return Err(Error::CorruptedDataStore); - } - - Ok(()) -} diff --git a/kit/src/elements/checkbox/style.scss b/kit/src/elements/checkbox/style.scss index 1750bb55c65..ec2ed0277d9 100644 --- a/kit/src/elements/checkbox/style.scss +++ b/kit/src/elements/checkbox/style.scss @@ -8,7 +8,6 @@ div.input-checkbox { flex-direction: row; align-items: center; justify-content: center; - margin-right: 1rem; svg { fill: transparent; diff --git a/kit/src/elements/select/mod.rs b/kit/src/elements/select/mod.rs index 8672a5333af..5ccd3092abd 100644 --- a/kit/src/elements/select/mod.rs +++ b/kit/src/elements/select/mod.rs @@ -110,9 +110,11 @@ pub fn FancySelect<'a>(cx: Scope<'a, FancySelectProps<'a>>) -> Element<'a> { rsx!( div { class: "fancy-select-options", + aria_label: "selector-options-list", iter.map(|(val, element)| rsx!(div { class: "fancy-select-option", + aria_label: "selector-option", onclick: move |e| { if let Some(f) = &cx.props.onselect { f.call(val.clone()) diff --git a/kit/src/elements/textarea/event_listeners.js b/kit/src/elements/textarea/event_listeners.js deleted file mode 100644 index f2d509a3001..00000000000 --- a/kit/src/elements/textarea/event_listeners.js +++ /dev/null @@ -1,51 +0,0 @@ -var MULTI_LINE = $MULTI_LINE; - -var sendButton = document.getElementsByClassName("controls") -var textareas = document.getElementsByClassName("input_textarea") -for (let i = 0; i < textareas.length; i++) { - var txt = textareas[i]; - //Update the height on load - updateHeight(txt); - if (!txt.event_listener) { - txt.addEventListener("input", inputListener); - txt.addEventListener("keypress", keyPressListener); - txt.addEventListener("keydown", arrowHandlerListener); - txt.event_listener = true; - if (i == 0) { - txt.addEventListener("keypress", (event) => { - if (event.keyCode === 13 && !event.shiftKey) { - textareas[0].style.height = "22px"; - textareas[0].value = ""; - } - }); - } - } -} - -sendButton[1].addEventListener("click", (event) => { - textareas[0].style.height = "22px"; - textareas[0].value = ""; -}) - -function inputListener(e) { - updateHeight(this); -} - -function updateHeight(element) { - element.style.height = "auto"; - if (!element.value || MULTI_LINE) { - element.style.height = "0px"; - } - element.style.height = element.scrollHeight + "px"; -} -function keyPressListener(e) { - if (e.key == "Enter" && MULTI_LINE && !e.shiftKey) { - e.preventDefault(); - } -} - -function arrowHandlerListener(e) { - if (this.classList.contains("up-down-disabled") && (e.key == "ArrowUp" || e.key == "ArrowDown")) { - e.preventDefault(); - } -} diff --git a/kit/src/elements/textarea/script.js b/kit/src/elements/textarea/script.js index 68c39fa80cd..2417cecd068 100644 --- a/kit/src/elements/textarea/script.js +++ b/kit/src/elements/textarea/script.js @@ -27,8 +27,14 @@ sendButton[1].addEventListener("click", (event) => { textareas[0].value = ""; }) -if (textareas[0].style.height === "66px") { - textareas[0].style.height = "22px"; +switch (textareas[0].style.height) { + case "66px": + case "44px": + case "330px": + textareas[0].style.height = "22px"; + break; + default: + break; } function inputListener(e) { diff --git a/ui/src/components/debug_logger/mod.rs b/ui/src/components/debug_logger/mod.rs index e404a8e7d2a..9dc7bac3cf0 100644 --- a/ui/src/components/debug_logger/mod.rs +++ b/ui/src/components/debug_logger/mod.rs @@ -69,6 +69,7 @@ pub fn DebugLogger(cx: Scope) -> Element { aria_label: "debug-logger-nav", Button { text: "Logs".into(), + aria_label: "logs-button".into(), icon: Icon::CommandLine, appearance: if *active_tab.get() == Tab::Logs { Appearance::Primary } else { Appearance::Secondary }, onpress: |_| { @@ -77,11 +78,14 @@ pub fn DebugLogger(cx: Scope) -> Element { }, (active_tab.get() == &Tab::Logs).then(|| cx.render(rsx!{ div { + aria_label: "filter-section", class: "section", Label { + aria_label: "filter-label".into(), text: "Filter:".into(), }, Button { + aria_label: "debug-level-button".into(), icon: Icon::BugAnt, appearance: Appearance::Secondary, onpress: |_| { @@ -95,6 +99,7 @@ pub fn DebugLogger(cx: Scope) -> Element { )), }, Button { + aria_label: "info-level-button".into(), icon: Icon::InformationCircle, appearance: if *filter_level.get() == Level::Info { Appearance::Info } else { Appearance::Secondary }, onpress: |_| { @@ -108,6 +113,7 @@ pub fn DebugLogger(cx: Scope) -> Element { )), }, Button { + aria_label: "error-level-button".into(), icon: Icon::ExclamationTriangle, appearance: if *filter_level.get() == Level::Error { Appearance::Danger } else { Appearance::Secondary }, onpress: |_| { @@ -121,6 +127,7 @@ pub fn DebugLogger(cx: Scope) -> Element { )), }, Button { + aria_label: "trace-level-button".into(), icon: Icon::Eye, appearance: Appearance::Secondary, onpress: |_| { @@ -136,6 +143,7 @@ pub fn DebugLogger(cx: Scope) -> Element { } })), Button { + aria_label: "state-button".into(), text: "State".into(), icon: Icon::Square3Stack3d, appearance: if *active_tab.get() == Tab::State { Appearance::Primary } else { Appearance::Secondary }, @@ -144,6 +152,7 @@ pub fn DebugLogger(cx: Scope) -> Element { } }, Button { + aria_label: "web-inspector-button".into(), text: "Web Inspector".into(), icon: Icon::ArrowTopRightOnSquare, appearance: Appearance::Secondary, diff --git a/ui/src/components/settings/mod.rs b/ui/src/components/settings/mod.rs index 71eea94001c..1c2ca94e997 100644 --- a/ui/src/components/settings/mod.rs +++ b/ui/src/components/settings/mod.rs @@ -9,6 +9,7 @@ pub mod sub_pages; pub struct SectionProps<'a> { section_label: String, section_description: String, + aria_label: Option, #[props(default)] no_border: bool, children: Element<'a>, @@ -16,6 +17,7 @@ pub struct SectionProps<'a> { #[allow(non_snake_case)] pub fn SettingSection<'a>(cx: Scope<'a, SectionProps<'a>>) -> Element<'a> { + let aria_label = cx.props.aria_label.clone().unwrap_or_default(); let no_border = cx .props .no_border @@ -25,7 +27,7 @@ pub fn SettingSection<'a>(cx: Scope<'a, SectionProps<'a>>) -> Element<'a> { cx.render(rsx!( div { class: "settings-section disable-select {no_border}", - aria_label: "settings-section", + aria_label: "{aria_label}", div { class: "settings-info", aria_label: "settings-info", @@ -49,14 +51,16 @@ pub fn SettingSection<'a>(cx: Scope<'a, SectionProps<'a>>) -> Element<'a> { #[derive(Props)] pub struct SectionSimpleProps<'a> { + aria_label: Option, children: Element<'a>, } #[allow(non_snake_case)] pub fn SettingSectionSimple<'a>(cx: Scope<'a, SectionSimpleProps<'a>>) -> Element<'a> { + let aria_label = cx.props.aria_label.clone().unwrap_or_default(); cx.render(rsx!( div { class: "settings-section simple disable-select", - aria_label: "settings-section", + aria_label: "{aria_label}", cx.props.children.is_some().then(|| rsx!( div { class: "settings-control", diff --git a/ui/src/components/settings/sub_pages/about.rs b/ui/src/components/settings/sub_pages/about.rs index b52be913b7a..abeef9daaf8 100644 --- a/ui/src/components/settings/sub_pages/about.rs +++ b/ui/src/components/settings/sub_pages/about.rs @@ -171,6 +171,7 @@ pub fn AboutPage(cx: Scope) -> Element { div { id: "settings-about", SettingSection { + aria_label: "about-info-section".into(), section_label: get_local_text("settings-about.info"), section_description: app_name.into(), }, @@ -187,6 +188,7 @@ pub fn AboutPage(cx: Scope) -> Element { } }, SettingSection { + aria_label: "about-version-section".into(), section_label: get_local_text("settings-about.version"), section_description: version.into(), div { @@ -195,6 +197,7 @@ pub fn AboutPage(cx: Scope) -> Element { }, } SettingSection { + aria_label: "open-website-section".into(), section_label: get_local_text("settings-about.open-website"), section_description: get_local_text("settings-about.open-website-description"), Button { @@ -208,6 +211,7 @@ pub fn AboutPage(cx: Scope) -> Element { } }, SettingSection { + aria_label: "open-codebase-section".into(), section_label: get_local_text("settings-about.open-codebase"), section_description: get_local_text("settings-about.open-codebase-description"), Button { @@ -221,6 +225,7 @@ pub fn AboutPage(cx: Scope) -> Element { } }, SettingSection { + aria_label: "made-in-section".into(), section_label: get_local_text("settings-about.made-in"), section_description: get_local_text("settings-about.team"), div { diff --git a/ui/src/components/settings/sub_pages/accessibility.rs b/ui/src/components/settings/sub_pages/accessibility.rs index 7aa824007bb..82d2dec8bb7 100644 --- a/ui/src/components/settings/sub_pages/accessibility.rs +++ b/ui/src/components/settings/sub_pages/accessibility.rs @@ -19,6 +19,7 @@ pub fn AccessibilitySettings(cx: Scope) -> Element { div { class: format_args!("{}", if state.read().configuration.general.dyslexia_support {"open-dyslexic-activated"} else {"open-dyslexic"}), SettingSection { + aria_label: "open-dyslexic-section".into(), section_label: get_local_text("settings-accessibility.dyslexia"), section_description: get_local_text("settings-accessibility.dyslexia-description"), Switch { diff --git a/ui/src/components/settings/sub_pages/audio.rs b/ui/src/components/settings/sub_pages/audio.rs index c1af921877b..a894f087dda 100644 --- a/ui/src/components/settings/sub_pages/audio.rs +++ b/ui/src/components/settings/sub_pages/audio.rs @@ -248,6 +248,7 @@ pub fn AudioSettings(cx: Scope) -> Element { id: "settings-audio", aria_label: "settings-audio", SettingSection { + aria_label: "input-device-section".into(), section_label: get_local_text("settings-audio.input-device"), section_description: get_local_text("settings-audio.input-device-description"), Select { @@ -271,6 +272,7 @@ pub fn AudioSettings(cx: Scope) -> Element { // } // } SettingSectionSimple { + aria_label: "test-device-input-section".into(), Button { text: get_local_text("settings-audio.device-test"), disabled: false, @@ -283,6 +285,7 @@ pub fn AudioSettings(cx: Scope) -> Element { } }, SettingSection { + aria_label: "output-device-section".into(), section_label: get_local_text("settings-audio.output-device"), section_description: get_local_text("settings-audio.output-device-description"), Select { @@ -306,6 +309,7 @@ pub fn AudioSettings(cx: Scope) -> Element { // } // } SettingSectionSimple { + aria_label: "test-device-output-section".into(), Button { text: get_local_text("settings-audio.device-test"), disabled: false, @@ -344,6 +348,7 @@ pub fn AudioSettings(cx: Scope) -> Element { //} SettingSection { + aria_label: "echo-cancellation-section".into(), section_label: get_local_text("settings-audio.echo-cancellation"), section_description: get_local_text("settings-audio.echo-cancellation-description"), Switch { @@ -361,6 +366,7 @@ pub fn AudioSettings(cx: Scope) -> Element { }, SettingSection { + aria_label: "interface-sounds-section".into(), section_label: get_local_text("settings-audio.interface-sounds"), section_description: get_local_text("settings-audio.interface-sounds-description"), Switch { @@ -374,6 +380,7 @@ pub fn AudioSettings(cx: Scope) -> Element { } }, SettingSection { + aria_label: "media-sounds-section".into(), section_label: get_local_text("settings-audio.media-sounds"), section_description: get_local_text("settings-audio.media-sounds-description"), Switch { @@ -387,6 +394,7 @@ pub fn AudioSettings(cx: Scope) -> Element { } }, SettingSection { + aria_label: "message-sounds-section".into(), section_label: get_local_text("settings-audio.message-sounds"), section_description: get_local_text("settings-audio.message-sounds-description"), Switch { @@ -400,6 +408,7 @@ pub fn AudioSettings(cx: Scope) -> Element { } }, SettingSection { + aria_label: "call-timer-section".into(), section_label: get_local_text("settings-audio.call-timer"), section_description: get_local_text("settings-audio.call-timer-description"), Switch {} diff --git a/ui/src/components/settings/sub_pages/developer.rs b/ui/src/components/settings/sub_pages/developer.rs index 063365b67c1..6a3afb77474 100644 --- a/ui/src/components/settings/sub_pages/developer.rs +++ b/ui/src/components/settings/sub_pages/developer.rs @@ -61,6 +61,7 @@ pub fn DeveloperSettings(cx: Scope) -> Element { id: "settings-developer", aria_label: "settings-developer", SettingSection { + aria_label: "experimental-features-section".into(), section_label: get_local_text("settings-developer.experimental-features"), section_description: get_local_text("settings-developer.experimental-features-description"), Switch { @@ -71,6 +72,7 @@ pub fn DeveloperSettings(cx: Scope) -> Element { } }, SettingSection { + aria_label: "developer-mode-section".into(), section_label: get_local_text("settings-developer.developer-mode"), section_description: get_local_text("settings-developer.developer-mode-description"), Switch { @@ -85,6 +87,7 @@ pub fn DeveloperSettings(cx: Scope) -> Element { } }, SettingSection { + aria_label: "test-notification-section".into(), section_label: get_local_text("settings-developer.test-notification"), section_description: get_local_text("settings-developer.test-notification-description"), Button { @@ -107,6 +110,7 @@ pub fn DeveloperSettings(cx: Scope) -> Element { } }, SettingSection { + aria_label: "open-cache-section".into(), section_label: get_local_text("settings-developer.open-cache"), section_description: get_local_text("settings-developer.open-cache-description"), Button { @@ -120,6 +124,7 @@ pub fn DeveloperSettings(cx: Scope) -> Element { } }, SettingSection { + aria_label: "compress-download-cache-section".into(), section_label: get_local_text("settings-developer.compress-download-cache"), section_description: get_local_text("settings-developer.compress-download-cache-description"), Button { @@ -135,6 +140,7 @@ pub fn DeveloperSettings(cx: Scope) -> Element { } }, SettingSection { + aria_label: "print-state-section".into(), section_label: get_local_text("settings-developer.print-state"), section_description: get_local_text("settings-developer.print-state-description"), Button { @@ -148,6 +154,7 @@ pub fn DeveloperSettings(cx: Scope) -> Element { } }, SettingSection { + aria_label: "clear-cache-section".into(), section_label: get_local_text("settings-developer.clear-cache"), section_description: get_local_text("settings-developer.clear-cache-description"), Button { @@ -161,6 +168,7 @@ pub fn DeveloperSettings(cx: Scope) -> Element { } } SettingSection { + aria_label: "save-logs-section".into(), section_label: get_local_text("settings-developer.save-logs-to-file"), section_description: get_local_text("settings-developer.save-logs-to-file-description"), Switch { diff --git a/ui/src/components/settings/sub_pages/files.rs b/ui/src/components/settings/sub_pages/files.rs index 269183f06f5..212713e32e5 100644 --- a/ui/src/components/settings/sub_pages/files.rs +++ b/ui/src/components/settings/sub_pages/files.rs @@ -15,6 +15,7 @@ pub fn FilesSettings(cx: Scope) -> Element { id: "settings-files", aria_label: "settings-files", SettingSection { + aria_label: "local-sync-section".into(), section_label: get_local_text("settings-files.local-sync"), section_description: get_local_text("settings-files.local-sync-description"), Switch { diff --git a/ui/src/components/settings/sub_pages/general.rs b/ui/src/components/settings/sub_pages/general.rs index 6b62f099439..fb66c3017d0 100644 --- a/ui/src/components/settings/sub_pages/general.rs +++ b/ui/src/components/settings/sub_pages/general.rs @@ -66,6 +66,7 @@ pub fn GeneralSettings(cx: Scope) -> Element { } },*/ SettingSection { + aria_label: "app-language-section".into(), section_label: get_local_text("settings-general.app-language"), section_description: get_local_text("settings-general.change-language"), Select { @@ -78,6 +79,7 @@ pub fn GeneralSettings(cx: Scope) -> Element { } }, SettingSection { + aria_label: "font-section".into(), section_label: get_local_text("settings-general.font"), section_description: get_local_text("settings-general.font-description"), Select { @@ -108,6 +110,7 @@ pub fn GeneralSettings(cx: Scope) -> Element { }, }, SettingSection { + aria_label: "font-scaling-section".into(), section_label: get_local_text("settings-general.font-scaling"), section_description: get_local_text("settings-general.font-scaling-description"), SlideSelector { @@ -120,6 +123,7 @@ pub fn GeneralSettings(cx: Scope) -> Element { } }, SettingSection { + aria_label: "theme-section".into(), section_label: get_local_text("settings-general.theme"), section_description: get_local_text("settings-general.theme-description"), no_border: true, @@ -169,6 +173,7 @@ pub fn GeneralSettings(cx: Scope) -> Element { }, }, SettingSectionSimple { + aria_label: "color-section".into(), div { class: "color-swatches", Button { diff --git a/ui/src/components/settings/sub_pages/keybinds.rs b/ui/src/components/settings/sub_pages/keybinds.rs index 2bace058148..783b9d06ed5 100644 --- a/ui/src/components/settings/sub_pages/keybinds.rs +++ b/ui/src/components/settings/sub_pages/keybinds.rs @@ -253,6 +253,7 @@ pub fn KeybindSettings(cx: Scope) -> Element { } }, SettingSection { + aria_label: "reset-keybinds-section".into(), section_label: get_local_text("settings-keybinds.reset-keybinds"), section_description: get_local_text("settings-keybinds.reset-keybinds-description"), Button { diff --git a/ui/src/components/settings/sub_pages/licenses.rs b/ui/src/components/settings/sub_pages/licenses.rs index 044d74fba46..095a9d3ed86 100644 --- a/ui/src/components/settings/sub_pages/licenses.rs +++ b/ui/src/components/settings/sub_pages/licenses.rs @@ -16,9 +16,11 @@ pub fn Licenses(cx: Scope) -> Element { id: "settings-licenses", aria_label: "settings-licenses", SettingSection { + aria_label: "licenses-section".into(), section_label: "Uplink".into(), section_description: "Both code and icons are under the MIT license.".into(), Button { + aria_label: "licenses-button".into(), text: "License Description".into(), appearance: Appearance::Secondary, icon: Icon::DocumentText, diff --git a/ui/src/components/settings/sub_pages/messages.rs b/ui/src/components/settings/sub_pages/messages.rs index aa64fdd86e5..ac4bae39dbb 100644 --- a/ui/src/components/settings/sub_pages/messages.rs +++ b/ui/src/components/settings/sub_pages/messages.rs @@ -17,6 +17,7 @@ pub fn Messages(cx: Scope) -> Element { id: "settings-messages", aria_label: "settings-messages", SettingSection { + aria_label: "emoji-conversion-section".into(), section_label: get_local_text("settings-messages.emoji-conversion"), section_description: get_local_text("settings-messages.emoji-conversion-description"), Switch { @@ -27,6 +28,7 @@ pub fn Messages(cx: Scope) -> Element { } }, SettingSection { + aria_label: "markdown-support-section".into(), section_label: get_local_text("settings-messages.markdown-support"), section_description: get_local_text("settings-messages.markdown-support-description"), Switch { diff --git a/ui/src/components/settings/sub_pages/notifications.rs b/ui/src/components/settings/sub_pages/notifications.rs index 4c9f9b61187..ebbbc384a89 100644 --- a/ui/src/components/settings/sub_pages/notifications.rs +++ b/ui/src/components/settings/sub_pages/notifications.rs @@ -30,6 +30,7 @@ pub fn NotificationSettings(cx: Scope) -> Element { } },*/ SettingSection { + aria_label: "enabled-notifications-section".into(), section_label: get_local_text("settings-notifications.enabled"), section_description: get_local_text("settings-notifications.enabled-description"), Switch { @@ -45,6 +46,7 @@ pub fn NotificationSettings(cx: Scope) -> Element { div { class: format_args!("{}", if state.read().configuration.notifications.enabled { "enabled" } else { "disabled" }), SettingSection { + aria_label: "friends-notifications-section".into(), section_label: get_local_text("friends"), section_description: get_local_text("settings-notifications.friends-description"), Switch { @@ -59,6 +61,7 @@ pub fn NotificationSettings(cx: Scope) -> Element { } }, SettingSection { + aria_label: "messages-notifications-section".into(), section_label: get_local_text("messages"), section_description: get_local_text("settings-notifications.messages-description"), Switch { @@ -73,6 +76,7 @@ pub fn NotificationSettings(cx: Scope) -> Element { } }, SettingSection { + aria_label: "settings-notifications-section".into(), section_label: get_local_text("settings"), section_description: get_local_text("settings-notifications.settings-description"), Switch { diff --git a/ui/src/components/settings/sub_pages/profile/mod.rs b/ui/src/components/settings/sub_pages/profile/mod.rs index 6c45ef5292d..6c53c731b4e 100644 --- a/ui/src/components/settings/sub_pages/profile/mod.rs +++ b/ui/src/components/settings/sub_pages/profile/mod.rs @@ -2,6 +2,7 @@ use std::path::PathBuf; use arboard::Clipboard; use common::get_images_dir; +use common::icons::Icon as IconElement; use common::language::get_local_text; use common::state::{Action, Identity, State, ToastNotification}; use common::warp_runner::{MultiPassCmd, TesseractCmd, WarpCmd}; @@ -12,6 +13,7 @@ use futures::channel::oneshot; use futures::StreamExt; use kit::components::context_menu::{ContextItem, ContextMenu}; use kit::components::indicator::{Indicator, Platform, Status}; +use kit::elements::checkbox::Checkbox; use kit::elements::select::FancySelect; use kit::elements::tooltip::Tooltip; use kit::elements::Appearance; @@ -20,6 +22,7 @@ use kit::elements::{ input::{Input, Options, Validation}, label::Label, }; +use kit::layout::modal::Modal; use mime::*; use rfd::FileDialog; use warp::multipass::identity::IdentityStatus; @@ -44,6 +47,8 @@ enum ChanCmd { pub fn ProfileSettings(cx: Scope) -> Element { log::trace!("rendering ProfileSettings"); let state = use_shared_state::(cx)?; + let first_render = use_state(cx, || true); + let identity = state.read().get_own_identity(); let user_status = identity.status_message().unwrap_or_default(); let online_status = identity.identity_status(); @@ -68,8 +73,9 @@ pub fn ProfileSettings(cx: Scope) -> Element { image.eq("\0") || image.is_empty() || identity.contains_default_picture(); let no_banner_picture = banner.eq("\0") || banner.is_empty(); + let show_remove_seed = use_state(cx, || false); let seed_phrase: &UseState> = use_state(cx, || None); - let seed_words_ch = use_coroutine(cx, |mut rx: UnboundedReceiver<()>| { + let seed_words_ch: &Coroutine<()> = use_coroutine(cx, |mut rx: UnboundedReceiver<()>| { to_owned![seed_phrase]; async move { let warp_cmd_tx = WARP_CMD_CH.tx.clone(); @@ -104,6 +110,80 @@ pub fn ProfileSettings(cx: Scope) -> Element { } }); + let phrase_exists: &UseState = use_state(cx, || false); + let seed_phrase_exists = use_coroutine(cx, |mut rx: UnboundedReceiver<()>| { + to_owned![phrase_exists]; + async move { + let warp_cmd_tx = WARP_CMD_CH.tx.clone(); + while rx.next().await.is_some() { + // only one command so far + let (tx, rx) = oneshot::channel(); + if let Err(e) = + warp_cmd_tx.send(WarpCmd::Tesseract(TesseractCmd::CheckMnemonicExist { + rsp: tx, + })) + { + log::error!("error sending warp command: {e}"); + continue; + } + + let res = match rx.await { + Ok(r) => r, + Err(e) => { + log::error!("error receiving warp command: {e}"); + continue; + } + }; + + match res { + Ok(does_exist) => { + phrase_exists.set(does_exist); + } + Err(e) => { + log::error!("failed to check for seed words: {e}"); + continue; + } + } + } + } + }); + + let remove_seed_words_ch = use_coroutine(cx, |mut rx: UnboundedReceiver<()>| { + to_owned![phrase_exists, show_remove_seed]; + async move { + let warp_cmd_tx = WARP_CMD_CH.tx.clone(); + while rx.next().await.is_some() { + // only one command so far + let (tx, rx) = oneshot::channel(); + if let Err(e) = + warp_cmd_tx.send(WarpCmd::Tesseract(TesseractCmd::DeleteMnemonic { rsp: tx })) + { + log::error!("error sending warp command: {e}"); + continue; + } + + let res = match rx.await { + Ok(r) => r, + Err(e) => { + log::error!("error receiving warp command: {e}"); + continue; + } + }; + + match res { + Ok(_) => { + show_remove_seed.set(false); + phrase_exists.set(false); + } + Err(e) => { + log::error!("failed to remove seed words: {e}"); + continue; + } + } + } + } + }); + if let Some(ident) = should_update.get() { log::trace!("Updating ProfileSettings"); state.write().set_own_identity(ident.clone()); @@ -233,6 +313,14 @@ pub fn ProfileSettings(cx: Scope) -> Element { .unwrap_or_default(); let change_banner_text = get_local_text("settings-profile.change-banner"); + + let store_phrase = use_state(cx, || true); + + if *first_render.get() { + seed_phrase_exists.send(()); + first_render.set(false); + } + cx.render(rsx!( div { id: "settings-profile", @@ -482,6 +570,7 @@ pub fn ProfileSettings(cx: Scope) -> Element { } }, SettingSection { + aria_label: "online-status-section".into(), section_label: get_local_text("settings-profile.online-status"), section_description: get_local_text("settings-profile.online-status-description"), FancySelect { @@ -494,48 +583,123 @@ pub fn ProfileSettings(cx: Scope) -> Element { } }, }, - SettingSection { - section_label: get_local_text("settings-profile.recovery-seed"), - section_description: get_local_text("settings-profile.recovery-seed-description"), - Button { - text: if seed_phrase.as_ref().is_none() { get_local_text("settings-profile.reveal-recovery-seed") } else { get_local_text("settings-profile.hide-recovery-seed") }, - aria_label: "reveal-recovery-seed-button".into(), - appearance: Appearance::Danger, - icon: if seed_phrase.as_ref().is_none() { Icon::Eye } else { Icon::EyeSlash }, - onpress: move |_| { - if seed_phrase.is_some() { - seed_phrase.set(None); - } else { - seed_words_ch.send(()); + if *phrase_exists.get() {rsx!( + SettingSection { + aria_label: "recovery-seed-section".into(), + section_label: get_local_text("settings-profile.recovery-seed"), + section_description: get_local_text("settings-profile.recovery-seed-description"), + Button { + text: if seed_phrase.as_ref().is_none() { get_local_text("settings-profile.reveal-recovery-seed") } else { get_local_text("settings-profile.hide-recovery-seed") }, + aria_label: "reveal-recovery-seed-button".into(), + appearance: Appearance::Danger, + icon: if seed_phrase.as_ref().is_none() { Icon::Eye } else { Icon::EyeSlash }, + onpress: move |_| { + if seed_phrase.is_some() { + seed_phrase.set(None); + } else { + seed_words_ch.send(()); + } } } } - } - if let Some(phrase) = seed_phrase.as_ref() { - let words = phrase.split_whitespace().collect::>(); - render!( - SettingSectionSimple { - div { - class: "seed-words", - words.chunks_exact(2).enumerate().map(|(idx, vals)| rsx! { - div { - class: "row", - div { - class: "col", - span { class: "num", ((idx * 2) + 1).to_string() }, - span { class: "val", vals.first().cloned().unwrap_or_default() } - }, + if let Some(phrase) = seed_phrase.as_ref() { + let words = phrase.split_whitespace().collect::>(); + render!( + SettingSectionSimple { + aria_label: "seed-words-section".into(), + div { + class: "seed-words", + words.chunks_exact(2).enumerate().map(|(idx, vals)| rsx! { div { - class: "col", - span { class: "num", ((idx * 2) + 2).to_string() }, - span { class: "val", vals.get(1).cloned().unwrap_or_default() } + class: "row", + div { + class: "col", + span { + aria_label: "seed-word-number-{((idx * 2) + 1).to_string()}", + class: "num", ((idx * 2) + 1).to_string() + }, + span { + aria_label: "seed-word-value-{((idx * 2) + 1).to_string()}", + class: "val", vals.first().cloned().unwrap_or_default() + } + }, + div { + class: "col", + span { + aria_label: "seed-word-number-{((idx * 2) + 2).to_string()}", + class: "num", ((idx * 2) + 2).to_string() + }, + span { + aria_label: "seed-word-value-{((idx * 2) + 2).to_string()}", + class: "val", vals.get(1).cloned().unwrap_or_default() + } + } + } + }) + } + } + ) + }, + SettingSectionSimple { + Checkbox { + disabled: false, + is_checked: *store_phrase.get(), + height: "15px".into(), + width: "15px".into(), + on_click: move |_| { + show_remove_seed.set(true); + }, + }, + label { + get_local_text("settings-profile.store-on-account") + } + }, + show_remove_seed.then(|| rsx!( + Modal { + open: *show_remove_seed.clone(), + onclose: move |_| show_remove_seed.set(false), + transparent: false, + close_on_click_inside_modal: false, + div { + class: "remove-phrase-container", + div { + class: "warning-symbol", + IconElement { + icon: Icon::ExclamationTriangle + } + }, + Label { + text: get_local_text("settings-profile.remove-recovery-seed"), + aria_label: "remove-phrase-label".into(), + }, + p { + get_local_text("settings-profile.remove-recovery-seed-description") + }, + div { + class: "button-group", + Button { + text: get_local_text("uplink.remove"), + aria_label: "remove-seed-phrase-btn".into(), + appearance: Appearance::Danger, + icon: Icon::Trash, + onpress: move |_| { + remove_seed_words_ch.send(()); + } + }, + Button { + text: get_local_text("uplink.cancel"), + aria_label: "cancel-remove-seed-phrase-btn".into(), + icon: Icon::NoSymbol, + appearance: Appearance::Secondary, + onpress: move |_| { + show_remove_seed.set(false); } } - }) + } } } - ) - }, + )), + )} if open_crop_image_modal_for_banner_picture.get().0 { rsx!(CropRectImageModal { large_thumbnail: open_crop_image_modal_for_banner_picture.1.clone(), diff --git a/ui/src/components/settings/sub_pages/profile/style.scss b/ui/src/components/settings/sub_pages/profile/style.scss index 37ab4d40add..358d89f8acd 100644 --- a/ui/src/components/settings/sub_pages/profile/style.scss +++ b/ui/src/components/settings/sub_pages/profile/style.scss @@ -1,6 +1,30 @@ #settings-profile { align-items: flex-start; + .remove-phrase-container { + padding: var(--padding); + width: calc(var(--width-sidebar) * 2); + display: inline-flex; + gap: var(--gap); + align-items: center; + justify-items: center; + text-align: center; + flex-direction: column; + + .button-group { + display: inline-flex; + margin-top: var(--padding); + gap: var(--gap); + } + + .warning-symbol svg { + width: var(--height-input); + height: var(--height-input); + fill: transparent; + stroke: var(--warning); + } + } + .profile-header { background: var(--secondary); height: calc(var(--width-sidebar) / 2); @@ -8,7 +32,6 @@ position: relative; margin-bottom: calc((var(--width-sidebar) / 6.3) / 2 + var(--gap)); - #profile-banner-context-menu { width: 100%; height: 100%; diff --git a/ui/src/extension_browser/mod.rs b/ui/src/extension_browser/mod.rs index 0cfcc0eb642..b438be2c6e3 100644 --- a/ui/src/extension_browser/mod.rs +++ b/ui/src/extension_browser/mod.rs @@ -22,6 +22,7 @@ pub fn Settings(cx: Scope) -> Element { div { class: "extensions-settings", SettingSection { + aria_label: "open-extensions-section".into(), section_label: get_local_text("settings-extensions.open-extensions-folder"), section_description: get_local_text("settings-extensions.open-folder-description"), Button { @@ -34,6 +35,7 @@ pub fn Settings(cx: Scope) -> Element { }, }, SettingSection { + aria_label: "auto-enable-section".into(), section_label: get_local_text("settings-extensions.auto-enable"), section_description: get_local_text("settings-extensions.auto-enable-description"), Switch { diff --git a/ui/src/layouts/log_in/copy_seed_words.rs b/ui/src/layouts/log_in/copy_seed_words.rs index a15f8a7bd5d..ae362aa5cc2 100644 --- a/ui/src/layouts/log_in/copy_seed_words.rs +++ b/ui/src/layouts/log_in/copy_seed_words.rs @@ -67,14 +67,25 @@ fn SeedWords(cx: Scope, page: UseState, words: Vec) -> Elemen div { class: "col", - span { class: "num", ((idx * 2) + 1).to_string() }, - span { class: "val", vals.get(0).cloned().unwrap_or_default() } + span { + aria_label: "seed-word-number-{((idx * 2) + 1).to_string()}", + class: "num", ((idx * 2) + 1).to_string() + }, + span { + aria_label: "seed-word-value-{((idx * 2) + 1).to_string()}", + class: "val", vals.get(0).cloned().unwrap_or_default() + } }, div { class: "col", - - span { class: "num", ((idx * 2) + 2).to_string() }, - span { class: "val", vals.get(1).cloned().unwrap_or_default() } + span { + aria_label: "seed-word-number-{((idx * 2) + 2).to_string()}", + class: "num", ((idx * 2) + 2).to_string() + }, + span { + aria_label: "seed-word-value-{((idx * 2) + 2).to_string()}", + class: "val", vals.get(1).cloned().unwrap_or_default() + } } } }) @@ -89,6 +100,7 @@ fn SeedWords(cx: Scope, page: UseState, words: Vec) -> Elemen appearance: Appearance::Secondary }, Button { + aria_label: "i-saved-it-button".into(), text: get_local_text("copy-seed-words.finished"), onpress: move |_| { page.set(AuthPages::EnterUserName); diff --git a/ui/src/layouts/log_in/create_or_recover.rs b/ui/src/layouts/log_in/create_or_recover.rs index 7d29649fdd7..95019d94430 100644 --- a/ui/src/layouts/log_in/create_or_recover.rs +++ b/ui/src/layouts/log_in/create_or_recover.rs @@ -30,17 +30,20 @@ pub fn Layout(cx: Scope, page: UseState) -> Element { } div { class: "instructions", + aria_label: "create-or-recover-instructions", get_local_text("create-or-recover.instructions") }, div { class: "button-container", Button { + aria_label: "create-button".into(), text: get_local_text("create-or-recover.create"), onpress: move |_| { page.set(AuthPages::CopySeedWords); } }, Button { + aria_label: "recover-button".into(), text: get_local_text("create-or-recover.recover"), onpress: move |_| { page.set(AuthPages::EnterSeedWords); diff --git a/ui/src/layouts/log_in/enter_seed_words.rs b/ui/src/layouts/log_in/enter_seed_words.rs index f844d547191..19a2257f57a 100644 --- a/ui/src/layouts/log_in/enter_seed_words.rs +++ b/ui/src/layouts/log_in/enter_seed_words.rs @@ -90,9 +90,11 @@ pub fn Layout(cx: Scope, pin: UseRef, page: UseState) -> Elem }, div { class: "instructions", + aria_label: "instructions", get_local_text("enter-seed-words.instructions") }, input::Input { + aria_label: "recovery-seed-input".into(), placeholder: get_local_text("enter-seed-words.placeholder"), onchange: move |(x, is_valid)| { if is_valid { @@ -111,6 +113,7 @@ pub fn Layout(cx: Scope, pin: UseRef, page: UseState) -> Elem appearance: Appearance::Secondary }, Button { + aria_label: "recover-account-button".into(), text: get_local_text("enter-seed-words.submit"), disabled: *loading.get(), onpress: move |_| { diff --git a/ui/src/layouts/log_in/enter_username.rs b/ui/src/layouts/log_in/enter_username.rs index 86e0a6824eb..18874aeae2c 100644 --- a/ui/src/layouts/log_in/enter_username.rs +++ b/ui/src/layouts/log_in/enter_username.rs @@ -116,6 +116,7 @@ pub fn Layout( }, div { class: "instructions", + aria_label: "instructions", get_local_text("auth.enter-username-subtext") }, Input {