diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index cd56105..57a3b15 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,5 +1,5 @@ build: - image: node:20 + image: node:20.8.1 stage: build before_script: # - ./update_version.sh diff --git a/public/sw.js b/public/sw.js index 6ea561a..51c9f2d 100644 --- a/public/sw.js +++ b/public/sw.js @@ -1,3 +1,5 @@ +var periodicSyncNewMsgReminderText; + // Notification click event listener self.addEventListener("notificationclick", (e) => { e.notification.close(); @@ -19,6 +21,10 @@ self.addEventListener("notificationclick", (e) => { ); }); +self.addEventListener("message", (event) => { + periodicSyncNewMsgReminderText = event.data; +}); + async function checkNewMessages() { const cachedCredentials = await caches.open('cachedCredentials'); // Todo... @@ -28,7 +34,8 @@ async function checkNewMessages() { // see browser compatibility: https://developer.mozilla.org/en-US/docs/Web/API/Web_Periodic_Background_Synchronization_API#browser_compatibility self.addEventListener('periodicsync', (event) => { if (event.tag === 'check-new-messages') { - self.registration.showNotification("Notification via periodicSync"); + let notificationTitle = periodicSyncNewMsgReminderText || "You may have new messages"; + self.registration.showNotification(notificationTitle); event.waitUntil(checkNewMessages()); } diff --git a/src/App.vue b/src/App.vue index fde972f..32b5f2b 100644 --- a/src/App.vue +++ b/src/App.vue @@ -49,7 +49,7 @@ export default { this.setDefaultLanguage(); }, mounted() { - registerServiceWorker(); + registerServiceWorker(this.$t('notification.periodicSync_new_msg_reminder')); /** if ( window.location.protocol == "http" && diff --git a/src/assets/css/_variables.scss b/src/assets/css/_variables.scss index ea510aa..88fa7b5 100644 --- a/src/assets/css/_variables.scss +++ b/src/assets/css/_variables.scss @@ -18,4 +18,6 @@ $voice-recording-color: red; $voice-recorded-color: #3ae17d; $poll-hilite-color: #6360f0; $poll-hilite-color-bg: #d6d5fc; -$alert-bg-color: #FF3300; \ No newline at end of file +$alert-bg-color: #FF3300; + +$min-touch-target: 48px; \ No newline at end of file diff --git a/src/assets/css/chat.scss b/src/assets/css/chat.scss index 4938df9..0636372 100644 --- a/src/assets/css/chat.scss +++ b/src/assets/css/chat.scss @@ -286,7 +286,7 @@ body { .input-area-button { margin: 0; padding: 0; - min-width: 48px; + min-width: $min-touch-target; &.input-more-icon { svg { @@ -430,6 +430,10 @@ body { display: inline-block; position: relative; max-width: 70%; + + @media #{map-get($display-breakpoints, 'sm-and-down')} { + min-height: $min-touch-target; + } } &.from-admin .bubble { background-color: rgba($admin-bg,0.8); @@ -520,6 +524,10 @@ body { display: inline-block; position: relative; max-width: 70%; + + @media #{map-get($display-breakpoints, 'sm-and-down')} { + min-height: $min-touch-target; + } } .audio-bubble { background-color: rgba(#e5e5e5,0.8); @@ -1409,7 +1417,7 @@ body { bottom: 68px; left: 8px; right: 8px; - height: 48px; + height: $min-touch-target; background: rgba(0, 0, 0, 0.69); border: 1px solid #000000; border-radius: 5px; diff --git a/src/assets/css/components/_poll.scss b/src/assets/css/components/_poll.scss index 89374a2..8e39b64 100644 --- a/src/assets/css/components/_poll.scss +++ b/src/assets/css/components/_poll.scss @@ -37,7 +37,7 @@ border-radius: 4px; padding: 15px 14px; margin: 0px; - height: 48px; + height: $min-touch-target; &:hover { cursor: pointer; } @@ -225,7 +225,7 @@ .add-answer-button { border-radius: 4px; - height: 48px; + height: $min-touch-target; width: 100%; overflow: hidden; border: 1px solid #242424; diff --git a/src/assets/css/filedrop.scss b/src/assets/css/filedrop.scss index f4cccd1..b66c5dd 100644 --- a/src/assets/css/filedrop.scss +++ b/src/assets/css/filedrop.scss @@ -1,4 +1,4 @@ -$large-button-height: 48px; +$large-button-height: $min-touch-target; $small-button-height: 36px; .file-drop-root { @@ -295,11 +295,11 @@ $small-button-height: 36px; position: relative; padding: 8px; .v-image { - width: 48px; - height: 48px; + width: $min-touch-target; + height: $min-touch-target; border-radius: 8px; object-fit: cover; - flex: 0 0 48px; + flex: 0 0 $min-touch-target; margin-right: 8px; } margin-bottom: 8px; diff --git a/src/assets/heart.png b/src/assets/heart.png new file mode 100644 index 0000000..8d357d1 Binary files /dev/null and b/src/assets/heart.png differ diff --git a/src/assets/translations/de.json b/src/assets/translations/de.json index 1bf5e4b..7aebea4 100644 --- a/src/assets/translations/de.json +++ b/src/assets/translations/de.json @@ -19,7 +19,11 @@ "loading": "{appName} wird geladen", "done": "Fertig", "user_kick_and_ban": "Hinauswerfen", - "direct_chat": "Privater Chat" + "direct_chat": "Privater Chat", + "delete_now": "Jetzt löschen", + "user_make_admin": "Admin erstellen", + "user_revoke_moderator": "Moderator widerrufen", + "user_make_moderator": "Moderator erstellen" }, "message": { "you": "Du", @@ -68,7 +72,18 @@ "someone": "Jemand", "file": "Datei", "files": "Dateien", - "download_all": "Alle herunterladen" + "download_all": "Alle herunterladen", + "outgoing_message_deleted_text": "Du hast diese Nachricht gelöscht.", + "upload_file_too_large": "Datei ist zu groß zum Hochladen!", + "user_was_kicked": "{user} wurde aus dem Chat geworfen.", + "user_was_kicked_by_you": "Du hast {user} aus dem Chat geworfen.", + "user_was_kicked_you": "Du wurdest aus dem Chat geworfen.", + "incoming_message_deleted_text": "Diese Nachricht wurde gelöscht.", + "sent_media": "{count} Medienelemente gesendet.", + "user_was_banned_by_you": "Du hast {user} aus dem Chat geworfen und gesperrt.", + "user_was_banned_you": "Du wurdest aus dem Chat rausgeschmissen und gesperrt.", + "user_was_banned": "{user} wurde aus dem Chat geworfen und gesperrt.", + "preparing_to_upload": "Vorbereitungen zum Hochladen..." }, "room": { "leave": "Verlassen", @@ -89,7 +104,9 @@ "room_history_is": "Der Raumverlauf ist {type}.", "room_history_joined": "Die Teilnehmer können nur die Nachrichten sehen, die nach ihrem Beitritt gesendet wurden.", "got_it": "Verstanden", - "encrypted": "Die Nachrichten werden Ende-zu-Ende verschlüsselt." + "encrypted": "Die Nachrichten werden Ende-zu-Ende verschlüsselt.", + "change": "Ändern", + "direct_private_chat": "Direktnachricht" }, "new_room": { "join_permissions": "Beitrittsberechtigungen", @@ -130,7 +147,10 @@ "invalid_message": "Benutzername oder Passwort falsch", "send_verification": "Sende Bestätigungs-E-Mail", "resend_verification": "Bestätigungsmail erneut senden", - "accept_terms": "Akzeptiere." + "accept_terms": "Akzeptiere.", + "token_not_valid": "Ungültiges Token", + "email_not_valid": "E-Mail-Adresse ist nicht gültig", + "send_token": "Token senden" }, "profile": { "title": "Mein Profil", @@ -146,7 +166,8 @@ "set_language": "Stelle deine Sprache ein", "language_description": "Convene ist in vielen Sprachen verfügbar.", "tell_us": "Teile uns mit.", - "notification_label": "Benachrichtigung" + "notification_label": "Benachrichtigung", + "display_name_required": "Anzeigename ist erforderlich" }, "profile_info_popup": { "you_are": "Du bist", @@ -154,7 +175,7 @@ "edit_profile": "Profil bearbeiten", "logout": "Abmelden", "powered_by": "Dieser Raum wird von {product} betrieben. Erfahre mehr unter {productLink} oder erstelle einen weiteren Raum!", - "new_room": "+ neuer Raum", + "new_room": "Neuer Raum", "identity_temporary": "{displayName}", "want_more": "Willst du mehr?" }, @@ -168,7 +189,9 @@ "title": "Willkommen in {roomName}", "enter_room": "Raum betreten", "remember_me": "Mich merken", - "choose_name": "Wähle einen zu nutzenden Namen" + "choose_name": "Wähle einen zu nutzenden Namen", + "join_user": "Chat starten", + "enter_room_user": "Chat starten" }, "invite": { "title": "Freunde hinzufügen", @@ -228,7 +251,19 @@ "message_retention_1_week": "1 Woche", "message_retention_1_day": "1 Tag", "message_retention_8_hours": "8 Stunden", - "message_retention_1_hour": "1 Stunde" + "message_retention_1_hour": "1 Stunde", + "read_only_room": "Schreibgeschützt", + "moderation": "Moderation", + "experimental_features": "Experimentelle Funktionen", + "file_mode": "Dateimodus", + "message_retention_4_week": "4 Wochen", + "make_public": "Öffentlich machen", + "direct_link": "Mein Direktlink", + "voice_mode": "Sprachmodus", + "download_chat": "Chat herunterladen", + "message_retention": "Nachrichtenverlauf", + "message_retention_none": "Aus", + "room_type": "Raumart" }, "room_info_sheet": { "this_room": "Dieser Raum", @@ -278,7 +313,9 @@ "poll_status_open_not_voted": "Umfrage ist offen – stimme ab, um die Ergebnisse zu sehen", "close_poll": "Umfrage schließen", "answer_label_n": "Antwort", - "view_results": "Ergebnisse ansehen" + "view_results": "Ergebnisse ansehen", + "answer_label_1": "Antwort*", + "please_complete": "Bitte vervollständigen" }, "export": { "fetched_n_of_total_events": "{count} von {total} Ereignissen geladen", @@ -294,10 +331,15 @@ "add_reaction": "Reaktion hinzufügen", "show_less": "Weniger anzeigen", "time": { - "recently": "im Moment" + "recently": "im Moment", + "hours": "vor 1 Stunde | vor {n} Stunden", + "days": "vor 1 Tag | vor {n} Tagen", + "minutes": "vor 1 Minute | vor {n} Minuten" }, "notify": "Benachrichtigung", - "close": "schlieen" + "close": "schlieen", + "click_to_remove": "Zum Entfernen klicken", + "password_hint": "Mindestens 12 Zeichen, davon mindestens eine Ziffer, ein Großbuchstabe und ein Kleinbuchstabe" }, "emoji": { "categories": { @@ -306,7 +348,8 @@ "flags": "Kennzeichnungen", "objects": "Objekte", "symbols": "Symbole", - "places": "Orte" + "places": "Orte", + "frequently": "Häufig genutzt" }, "search": "Suche ..." }, @@ -314,15 +357,25 @@ "sending": "Sende", "sending_progress": "Senden…", "close": "Schließen", - "files": "Dateien" + "files": "Dateien", + "files_sent": "1 Datei gesendet! | {count} Dateien gesendet!", + "choose_files": "Dateien auswählen", + "send_more_files": "Weitere Dateien senden" }, "notification": { "dialog": { "enable": "Aktiviere" - } + }, + "title": "Neue Nachricht erhalten" }, "getlink": { "next": "Nächster", - "continue": "Fortfahren" + "continue": "Fortfahren", + "hello": "Hallo {user},\nhier ist dein Direktlink", + "share_qr": "QR teilen", + "qr_image_copied": "Bild in die Zwischenablage kopiert" + }, + "createchannel": { + "name_required": "Kanalname ist erforderlich" } } diff --git a/src/assets/translations/en.json b/src/assets/translations/en.json index 67baacf..7e4424a 100644 --- a/src/assets/translations/en.json +++ b/src/assets/translations/en.json @@ -109,7 +109,8 @@ "files": "Files", "images": "Images", "send_attachements_dialog_title": "Do you want to send following attachments ?", - "download_all": "Download all" + "download_all": "Download all", + "failed_to_render": "Failed to render event" }, "room": { "invitations": "You have no invitations | You have 1 invitation | You have {count} invitations", @@ -140,6 +141,7 @@ "direct_private_chat": "Direct Message", "join_channel": "All set! Invite people to join you: {link}", "info_retention": "🕓 Messages sent within {time} are viewable by anyone with the link.", + "info_retention_user": "🕓 Messages older than {time} will be deleted from the history.", "change": "Change" }, "new_room": { @@ -406,7 +408,8 @@ "enable": "Enable" }, "blocked_message": "Notification is blocked. Go to your device or browser settings to enable Notification", - "not_supported": "Notification is not yet supported in Mobile" + "not_supported": "Notification is not yet supported in Mobile", + "periodicSync_new_msg_reminder": "You may have new messages" }, "emoji": { "search": "Search...", diff --git a/src/assets/translations/es.json b/src/assets/translations/es.json index 78aa6bc..757de59 100644 --- a/src/assets/translations/es.json +++ b/src/assets/translations/es.json @@ -26,13 +26,13 @@ "room_type_default": "Por Defecto", "copy_link": "Copiar enlace", "direct_link": "Mi enlace directo", - "read_only_room": "Sala de sólo lectura", + "read_only_room": "Solo lectura", "voice_mode": "Por voz", "make_public_warning": "Advertencia: El historial completo de mensajes será visible para los nuevos participantes", "room_type": "Genero de la sala", "experimental_features": "Funciones experimentales", "file_mode_info": "Cambia la interfaz del chat al modo \"soltar archivos\"", - "read_only_room_info": "Sólo los administradores y moderadores pueden escribir en la sala", + "read_only_room_info": "Solo los administradores y moderadores pueden enviar mensajes a la sala.", "file_mode": "Modo del archivo", "direct_link_desc": "¡Ya está listo para compartir! Se abrirá una nueva sala privada cada vez que alguien abra el enlace.", "download_chat": "Descargar el chat", @@ -49,7 +49,8 @@ "shared_room_number": "Compartes {count} salas con {name}", "shared_room_number_more": "Compartes más de {count} y salas con {name}", "message_retention": "Historial de mensajes", - "message_retention_info": "Los mensajes enviados dentro de este plazo pueden ser vistos por cualquiera que tenga el enlace." + "message_retention_info": "Los mensajes enviados dentro de este plazo pueden ser vistos por cualquiera que tenga el enlace.", + "moderation": "Moderado" }, "purge_room": { "button": "Borrar", @@ -173,7 +174,11 @@ "room_history_joined": "La gente sólo puede ver los mensajes enviados después de unirse.", "no_past_messages": "¡Bienvenido! Por su seguridad, los mensajes anteriores no están disponibles.", "direct_info": "Hola, {you}. Estás en un chat privado con {user}.", - "direct_private_chat": "Mensaje directo" + "direct_private_chat": "Mensaje directo", + "change": "Cambiar", + "join_channel": "¡Listo! Invita a la gente a unirse a: {link}", + "info_retention": "🕓 Los mensajes enviados dentro de {time} pueden ser vistos por cualquiera que tenga el enlace.", + "info_retention_user": "🕓 Los mensajes anteriores a {time} serán eliminados del historial." }, "room": { "leave": "Salir", @@ -253,7 +258,8 @@ "time_ago": "Hoy | Ayer | Hace {count} días", "upload_exceeded_file_limit": "Se ha superado el tamaño máximo para el archivo ({configFormattedUploadSize}). ", "someone": "Alguien", - "sent_media": "Enviados {count} elementos multimedia." + "sent_media": "Enviados {count} elementos multimedia.", + "failed_to_render": "No se pudo representar el evento" }, "menu": { "login": "Iniciar sesión", @@ -411,7 +417,8 @@ }, "title": "Nuevo mensaje recibido", "blocked_message": "La notificación está bloqueada. Vaya a la configuración de su dispositivo o navegador para habilitar la Notificación", - "not_supported": "La notificación aún no es compatible con dispositivos móviles" + "not_supported": "La notificación aún no es compatible con dispositivos móviles", + "periodicSync_new_msg_reminder": "Es posible que tengas nuevos mensajes" }, "export": { "fetched_n_of_total_events": "{count} de {total} eventos recuperados", @@ -422,5 +429,13 @@ }, "logout": { "confirm_text": "¿Seguro que quieres cerrar la sesión?" + }, + "createchannel": { + "title": "Crear un canal", + "info": "Difunde noticias o conocimientos en cualquier formato: vídeo, podcast, texto, imágenes o PDF.", + "channel_name": "Nombre de tu canal", + "channel_topic": "Descríbelo", + "name_required": "El nombre del canal es obligatorio", + "error_channel": "Error al crear el canal" } } diff --git a/src/assets/translations/fi.json b/src/assets/translations/fi.json index f930350..4f09ce2 100644 --- a/src/assets/translations/fi.json +++ b/src/assets/translations/fi.json @@ -64,7 +64,8 @@ "password": "Anna salasana", "password_required": "Salasana vaaditaan", "create_room": "Rekisteröidy ja luo huone", - "accept_terms": "Hyväksy" + "accept_terms": "Hyväksy", + "token_not_valid": "Virheellinen koodi" }, "join": { "title": "Tervetuloa huoneen {roomName}", @@ -106,7 +107,8 @@ "reply_poll": "Kysely", "file": "Tiedosto", "someone": "Joku", - "images": "Kuvat" + "images": "Kuvat", + "room_joinrule_public": "julkinen" }, "room": { "leave": "Poistu", @@ -118,7 +120,8 @@ "info": "Tervetuloa! Seuraavassa on muutamia asioita, jotka sinun on hyvä tietää huoneestasi:", "info_permissions": "Voit muuttaa liittymisoikeuksia milloin tahansa huoneen asetuksissa.", "encrypted": "Viestit ovat päästä päähän salattuja.", - "got_it": "Selvä" + "got_it": "Selvä", + "change": "Vaihda" }, "profile": { "temporary_identity": "Tämä identiteetti on väliaikainen. Aseta salasana käyttääksesi sitä uudelleen", @@ -170,7 +173,8 @@ "message_retention_none": "Pois päältä", "message_retention_1_day": "1 päivä", "message_retention_8_hours": "8 tuntia", - "message_retention_1_hour": "1 tunti" + "message_retention_1_hour": "1 tunti", + "read_only_room": "Lue Ainoastaan" }, "power_level": { "restricted": "rajoitettu", diff --git a/src/assets/translations/fr.json b/src/assets/translations/fr.json index 7c44359..3d3fac1 100644 --- a/src/assets/translations/fr.json +++ b/src/assets/translations/fr.json @@ -85,7 +85,8 @@ "join_invite": "Seules les personnes que vous invitez peuvent s’y joindre.", "info_permissions": "Vous pouvez modifier les « autorisations de participation » à tout moment dans les paramètres du salon.", "room_history_joined": "Les personnes ne peuvent voir que les messages envoyés après leur adhésion.", - "got_it": "Compris" + "got_it": "Compris", + "change": "Changer" }, "new_room": { "next": "Suivant", @@ -220,7 +221,8 @@ "message_retention_1_week": "1 semaine", "message_retention_1_day": "1 jour", "message_retention_8_hours": "8 heures", - "message_retention_1_hour": "1 heure" + "message_retention_1_hour": "1 heure", + "read_only_room": "Lecture seule" }, "room_info_sheet": { "this_room": "Ce salon", diff --git a/src/assets/translations/it.json b/src/assets/translations/it.json index 0fda653..c08b927 100644 --- a/src/assets/translations/it.json +++ b/src/assets/translations/it.json @@ -84,7 +84,8 @@ "join_invite": "Solo le persone che inviti possono partecipare.", "info_permissions": "Puoi cambiare i «permessi di adesione» in qualsiasi momento nelle impostazioni della stanza.", "got_it": "Capito", - "room_history_joined": "Le persone possono vedere solo i messaggi inviati dopo la loro adesione." + "room_history_joined": "Le persone possono vedere solo i messaggi inviati dopo la loro adesione.", + "change": "Cambia" }, "new_room": { "next": "Successivo", @@ -216,7 +217,8 @@ "message_retention_none": "Off", "message_retention_1_day": "1 giorno", "message_retention_8_hours": "8 ore", - "message_retention_1_hour": "1 ora" + "message_retention_1_hour": "1 ora", + "read_only_room": "Sola lettura" }, "voice_recorder": { "failed_to_record": "Impossibile registrare l’audio", diff --git a/src/assets/translations/nb_NO.json b/src/assets/translations/nb_NO.json index 9bfb2aa..f734c0e 100644 --- a/src/assets/translations/nb_NO.json +++ b/src/assets/translations/nb_NO.json @@ -80,7 +80,8 @@ "message_retention_1_week": "1 uke", "message_retention_1_day": "1 dag", "message_retention_8_hours": "åtte timer", - "message_retention_1_hour": "Én time" + "message_retention_1_hour": "Én time", + "read_only_room": "Skrivebeskyttet" }, "goodbye": { "view_other_rooms": "Vis andre rom", @@ -137,7 +138,8 @@ "room_history_is": "Romhistorikken er {type}.", "encrypted": "Meldinger er ende-til-ende -kryptert.", "got_it": "Skjønner", - "join_invite": "Kun folk du inviterer kan ta del." + "join_invite": "Kun folk du inviterer kan ta del.", + "change": "Endre" }, "room": { "room_list_rooms": "Rom", diff --git a/src/assets/translations/pt_BR.json b/src/assets/translations/pt_BR.json index b1ae3d4..6e39e1a 100644 --- a/src/assets/translations/pt_BR.json +++ b/src/assets/translations/pt_BR.json @@ -122,7 +122,8 @@ "upload_exceeded_file_limit": "O tamanho máximo do arquivo ({configFormattedUploadSize}) foi excedido. ", "preparing_to_upload": "Preparando para enviar...", "someone": "Alguém", - "sent_media": "Enviou {count} itens de mídia." + "sent_media": "Enviou {count} itens de mídia.", + "failed_to_render": "Houve uma falha ao renderizar o evento" }, "room": { "members": "sem membros | 1 membro | {count} membros", @@ -150,7 +151,11 @@ "got_it": "Entendi", "no_past_messages": "Bem-vindo! Para a sua segurança, as mensagens anteriores não estão disponíveis.", "direct_info": "Olá {you}. Você está num chat privado com {user}.", - "direct_private_chat": "Mensagem direta" + "direct_private_chat": "Mensagem direta", + "change": "Mudança", + "join_channel": "Tudo pronto! Convide pessoas para se juntarem a você: {link}", + "info_retention": "🕓 As mensagens enviadas dentro de {time} podem ser visualizadas por qualquer pessoa com o link.", + "info_retention_user": "As mensagens mais antigas que {time} serão excluídas do histórico." }, "new_room": { "new_room": "Nova sala", @@ -295,11 +300,11 @@ "voice_mode": "Modo de voz", "user_admin": "Administrador", "voice_mode_info": "Alterna a interface de chat para um modo de 'ouvir e gravar'", - "read_only_room": "Sala somente leitura", + "read_only_room": "Somente leitura", "user_moderator": "Moderador", "experimental_features": "Recursos experimentais", "download_chat": "Baixar o chat", - "read_only_room_info": "Apenas administradores e moderadores podem postar na sala", + "read_only_room_info": "Apenas os administradores e os moderadores podem postar na sala.", "copy_link": "Copiar o link", "make_public": "Tornar público", "room_type": "Tipo de sala", @@ -319,7 +324,8 @@ "message_retention_info": "As mensagens enviadas dentro desse período podem ser visualizadas por qualquer pessoa que tenha o link.", "message_retention_4_week": "4 semanas", "shared_room_number": "Você compartilha {count} quartos com {name}", - "shared_room_number_more": "Você compartilha mais de {count} quartos com {name}" + "shared_room_number_more": "Você compartilha mais de {count} quartos com {name}", + "moderation": "Moderação" }, "room_info_sheet": { "this_room": "Esta sala", @@ -408,7 +414,8 @@ "enable": "Ativar" }, "blocked_message": "A notificação está bloqueada. Vá para as configurações do dispositivo ou do navegador para ativar a notificação", - "not_supported": "A notificação ainda não é suportada no mobile" + "not_supported": "A notificação ainda não é suportada no mobile", + "periodicSync_new_msg_reminder": "Talvez você tenha novas mensagens" }, "getlink": { "title": "Obter um link direto", @@ -422,5 +429,13 @@ "username": "Insira um nome (ex: waku)", "different_link": "Obter um link diferente", "next": "Próximo" + }, + "createchannel": { + "channel_topic": "Descreva-o", + "name_required": "O nome do canal é obrigatório", + "info": "Transmita notícias ou conhecimento em qualquer formato: vídeo, podcast, texto, imagens ou PDFs.", + "error_channel": "Houve uma falha ao criar o canal", + "title": "Criar um canal", + "channel_name": "Dê um nome ao seu canal" } } diff --git a/src/assets/translations/ro.json b/src/assets/translations/ro.json index 07cc552..348ef91 100644 --- a/src/assets/translations/ro.json +++ b/src/assets/translations/ro.json @@ -63,7 +63,8 @@ "room_type_default": "Predefinit", "message_retention_none": "Dezactivat", "message_retention_1_day": "1 zi", - "message_retention_1_hour": "O oră" + "message_retention_1_hour": "O oră", + "message_retention_8_hours": "8 ore" }, "goodbye": { "view_other_rooms": "Vezi alte camere", @@ -181,7 +182,8 @@ "room_history_joined": "Oamenii pot vedea doar mesajele trimise după ce se înscriu.", "room_history_is": "Istoricul camerei este {type}.", "encrypted": "Mesajele sunt criptate de la un capăt la altul.", - "info": "Bine ați venit! Iată câteva lucruri pe care trebuie să le știți despre camera dumneavoastră:" + "info": "Bine ați venit! Iată câteva lucruri pe care trebuie să le știți despre camera dumneavoastră:", + "change": "Schimbă" }, "room": { "room_list_rooms": "Camere", diff --git a/src/assets/translations/ru.json b/src/assets/translations/ru.json new file mode 100644 index 0000000..363aaef --- /dev/null +++ b/src/assets/translations/ru.json @@ -0,0 +1,441 @@ +{ + "login": { + "invalid_message": "Неверное имя пользователя или пароль", + "title": "Имя пользователя", + "password": "Введите пароль", + "login": "Имя пользователя", + "resend_verification": "Отправить электронное письмо-подтверждение снова", + "token_not_valid": "Недействительный токен", + "accept_terms": "Принять", + "username": "Имя пользователя (например: marta)", + "username_required": "Имя пользователя обязательно", + "password_required": "Требуется пароль", + "create_room": "Регистрация и создание комнаты", + "no_supported_flow": "Приложение не может войти на указанный сервер", + "email_not_valid": "Адрес электронной почты недействителен", + "or": "ИЛИ", + "email": "Вам необходимо подтвердить свой адрес электронной почты", + "send_verification": "Отправить письмо с подтверждением", + "send_token": "Отправить токен", + "terms": "Домашний сервер требует, чтобы вы ознакомились со следующими правилами и приняли их:", + "sent_verification": "На адрес {email} отправлено письмо. Пожалуйста, используйте свой обычный почтовый клиент для проверки адреса.", + "registration_token": "Пожалуйста, введите регистрационный токен" + }, + "room_info": { + "copy_link": "Копировать ссылку", + "message_retention_1_day": "1 день", + "message_retention_8_hours": "8 часов", + "message_retention_1_hour": "1 час", + "hide_all": "Скрыть", + "leave_room": "Оставить", + "user_admin": "Администратор", + "user_moderator": "Модератор", + "room_type_default": "По умолчанию", + "members": "Элементов", + "read_only_room": "Только чтение", + "message_retention_none": "Выключить", + "message_retention_2_week": "2 недели", + "message_retention_1_week": "1 неделя", + "join_public": "У кого-нибудь есть ссылка", + "copy_invite_link": "Скопируйте ссылку на приглашение", + "scan_code": "Сканировать, чтобы присоединиться к комнате", + "message_retention": "История сообщений", + "message_retention_info": "Сообщения, отправленные в течение этого срока, могут просматривать все, у кого есть ссылка.", + "direct_link": "Моя прямая ссылка", + "title": "Детали комнаты", + "created_by": "Создано {user}", + "permissions": "Разрешения на присоединение", + "join_invite": "Только добавленные люди", + "link_copied": "Ссылка скопирована!", + "purge": "Удалить комнату", + "user": "{user}", + "user_you": "{user} (вы)", + "show_all": "Показать все >", + "export_room": "Экспорт чата", + "moderation": "Модерация", + "room_type": "Тип комнаты", + "voice_mode": "Голосовой режим", + "voice_mode_info": "Переключает интерфейс чата в режим \"слушать и записывать\"", + "file_mode": "Файловый режим", + "download_chat": "Скачать чат", + "read_only_room_info": "Отправлять сообщения в комнату могут только администраторы и модераторы.", + "message_retention_4_week": "4 недели", + "make_public_warning": "предупреждение: Полная история сообщений будет видна новым участникам", + "shared_room_number": "Вы делите {count} комнат с {name}", + "file_mode_info": "Переключает интерфейс чата в режим \"сброса файлов\"", + "make_public": "Сделать публичным", + "direct_link_desc": "Он готов к обмену! Каждый раз, когда кто-то открывает ссылку, будет открываться новая прямая комната.", + "version_info": "Работает под управлением Guardian Project. Версия: {version}", + "shared_room_number_more": "Вы делите более {count} комнат с {name}", + "experimental_features": "Экспериментальная функция" + }, + "file_mode": { + "sending": "Отправляем", + "sending_progress": "Отправка...", + "close": "Закрыть", + "files": "Файлы", + "files_sent": "Отправлен 1 файл! | {count} отправленных файлов!", + "any_file_format_accepted": "Принимаются файлы любого формата", + "send_more_files": "Отправить больше файлов", + "secure_file_send": "безопасная отправка файлов", + "add_a_message": "Добавить сообщение", + "files_sent_with_note": "1 файл отправлен с примечанием! | {count} файлов, отправленных с примечанием!", + "choose_files": "Выбрать файл" + }, + "global": { + "save": "Сохранить", + "show_less": "Показать меньше", + "show_more": "Показать больше", + "time": { + "recently": "только что", + "minutes": "1 минуту назад | {n} минут назад", + "hours": "1 час назад | {n} часов назад", + "days": "1 день назад | {n} дней назад" + }, + "notify": "Оповестить", + "password_didnot_match": "Пароль не совпадает", + "password_hint": "Минимум 12 символов, содержащих как минимум одну цифру, одну заглавную и одну строчную буквы", + "add_reaction": "Добавить реакцию", + "click_to_remove": "Нажмите, чтобы удалить", + "close": "закрыть" + }, + "message": { + "download_all": "Скачать все", + "someone": "Кто-то", + "file_prefix": "Файл: ", + "edited": "(отредактировано)", + "reply_image": "Изображение", + "reply_video": "Видео", + "reply_poll": "Опрос", + "seen_by": "Увиденное", + "file": "Файл", + "files": "Файлы", + "images": "Изображения", + "you": "Вы", + "user_aliased_room": "{user} создал псевдоним {alias} для комнаты", + "user_changed_display_name": "{user} изменил отображаемое имя на {displayName}", + "user_changed_avatar": "{user} изменил аватар", + "user_changed_room_avatar": "{user} изменил аватар комнаты", + "user_was_invited": "{user} был приглашен в чат...", + "user_was_kicked": "{user} был удален из чата.", + "user_was_banned": "{user} был удален и заблокирован в чате.", + "user_was_banned_you": "Вы были удалены из чата и заблокированы.", + "user_joined": "{user} присоединился к чату", + "user_left": "{user} покинул чат", + "user_said": "{user} сказал:", + "sent_media": "Отправлено {count} медиаэлементов.", + "preparing_to_upload": "Подготовка к загрузке...", + "upload_file_too_large": "Файл слишком велик для загрузки!", + "upload_progress": "Загружено {count}", + "upload_progress_with_total": "Загружено {count} из {total}", + "user_changed_room_history": "{user} сделал историю номера {type}", + "room_history_world_readable": "читаемый всеми", + "room_history_shared": "читаемый всеми участниками в комнате", + "user_changed_join_rules": "{user} сделал комнату {type}", + "room_joinrule_invite": "только по приглашению", + "user_changed_room_topic": "{user} изменил тему комнаты на {topic}", + "unread_messages": "Непрочитанные сообщения", + "user_is_typing": "{user} набирает", + "users_are_typing": "{count} членов набирают", + "room_powerlevel_change": "{user} изменил уровень мощности {changes}", + "user_powerlevel_change_from_to": "{user} из {powerOld} в {powerNew}", + "user_changed_guest_access_closed": "{user} запретил гостям входить в комнату", + "user_changed_guest_access_open": "{user} разрешил гостям присоединиться к комнате", + "reply_audio_message": "Аудиосообщение", + "outgoing_message_deleted_text": "Вы удалили это сообщение.", + "incoming_message_deleted_text": "Это сообщение было удалено.", + "user_created_room": "{user} создал комнату", + "user_encrypted_room": "{user} сделал комнату зашифрованной", + "user_was_kicked_by_you": "Вы выгнали {user} из чата.", + "user_was_kicked_you": "Вы были удалены из чата.", + "user_was_banned_by_you": "Вы выгнали и забанили {user} из чата.", + "download_progress": "{percentage}% скачанных", + "upload_exceeded_file_limit": "Превышен максимальный размер файла ({configFormattedUploadSize}). ", + "room_history_invited": "доступны для чтения членам клуба с того момента, когда они были приглашены", + "room_history_joined": "доступны для чтения членам клуба с момента их присоединения", + "room_joinrule_public": "публичный", + "user_changed_room_name": "{user} изменил название комнаты на {name}", + "replying_to": "Отвечая на {user}", + "your_message": "Ваше сообщение...", + "scale_image": "Масштаб изображения", + "time_ago": "Сегодня | Вчера | {count} дней назад", + "not_allowed_to_send": "Только администраторы и модераторы могут отправлять сообщения в комнату", + "reaction_count_more": "{reactionCount} больше", + "seen_by_count": "Видели ни один участник | Видел 1 участник | Видели {count} участников", + "send_attachements_dialog_title": "Вы хотите отправить следующие вложения?", + "failed_to_render": "Не удалось отрендерить событие" + }, + "new_room": { + "create": "Создание", + "next": "Вперёд", + "options": "Параметры", + "new_room": "Новая комната", + "name_room": "Название комнаты", + "join_permissions_info": "Эти разрешения определяют, как люди могут присоединиться к комнате и как легко пригласить других. Они могут быть изменены в любое время.", + "set_join_permissions": "Установка разрешений на присоединение", + "room_topic": "Добавьте описание, если хотите", + "join_permissions": "Разрешения на присоединение", + "get_link": "Получить ссылку", + "add_people": "Добавить людей", + "link_copied": "Ссылка скопирована!", + "colon_not_allowed": "Двоеточие запрещено", + "public_info": "У кого-нибудь есть ссылка", + "public_description": "Получите ссылку, чтобы поделиться", + "invite_info": "Добавлены только люди", + "invite_description": "Выберите из списка или выполните поиск по идентификатору счета", + "status_creating": "Создание комнаты", + "status_avatar_total": "Загрузка аватара: {count} из {total}", + "status_avatar": "Загрузка аватара: {count}", + "room_name_limit_error_msg": "Разрешено не более 50 символов" + }, + "room_info_sheet": { + "view_details": "Подробнее", + "this_room": "Эта комната" + }, + "power_level": { + "default": "по умолчанию", + "admin": "администратор", + "moderator": "модератор", + "custom": "пользовательский ({level})", + "restricted": "Ограничено" + }, + "emoji": { + "categories": { + "places": "Места", + "activity": "Активность", + "flags": "Метки", + "objects": "Объекты", + "nature": "Природа", + "symbols": "Символы", + "foods": "Продукция", + "peoples": "Люди", + "frequently": "Часто используемое" + }, + "search": "Найти..." + }, + "menu": { + "direct_chat": "Личный чат", + "reply": "Ответная", + "edit": "Редактировать", + "delete": "Удалить", + "download": "Загрузить", + "ok": "Ок", + "send": "Отправить", + "login": "Имя пользователя", + "logout": "Выйти из системы", + "undo": "Отменить", + "done": "Готово", + "cancel": "Отмена", + "join": "Присоединяйтесь к", + "ignore": "Игнорировать", + "user_kick_and_ban": "Выгнать", + "start_private_chat": "Прямое сообщение с этим пользователем", + "back": "НАЗАД", + "new_room": "Новая комната", + "delete_now": "Удалить сейчас", + "loading": "Загрузка {appName}", + "user_revoke_moderator": "Отозвать модератора", + "user_make_moderator": "Сделать модератором", + "user_make_admin": "Сделать администратором" + }, + "room": { + "leave": "Оставить", + "room_list_invites": "Приглашения", + "room_list_rooms": "Комнаты", + "unseen_messages": "У вас нет непросмотренных сообщений | У вас 1 непросмотренное сообщение | У вас {count} непросмотренных сообщений", + "members": "нет членов | 1 член | {count} членов", + "purge_set_room_state": "Установка состояния комнаты", + "purge_removing_members": "Удаление членов ({count} из {total})", + "purge_failed": "Не удалось очистить комнату!", + "room_name_required": "Название комнаты обязательно", + "room_topic_required": "Описание номера обязательно", + "invitations": "У вас нет приглашений | У вас есть 1 приглашение | У вас есть {count} приглашений", + "purge_redacting_events": "Сокращение событий ({count} из {total})", + "room_list_new_messages": "{count} новых сообщений" + }, + "room_welcome": { + "got_it": "Есть", + "change": "Изменить", + "encrypted": "Сообщения шифруются из конца в конец.", + "room_history_is": "История комнаты - {type}.", + "join_invite": "Присоединиться могут только те, кого вы пригласили.", + "no_past_messages": "Добро пожаловать! Для вашей безопасности прошлые сообщения недоступны.", + "direct_info": "Привет, {you}. Вы находитесь в приватном чате с {user}.", + "join_channel": "Все готово! Пригласите людей присоединиться к вам: {link}", + "info_retention": "🕓 Сообщения, отправленные в течение {time}, могут просматривать все, у кого есть ссылка.", + "room_history_joined": "Люди могут видеть сообщения, отправленные только после того, как они присоединились.", + "join_public": "Любой желающий может присоединиться, открыв эту ссылку: {link}.", + "info_permissions": "Вы можете в любой момент изменить \"разрешение на присоединение\" в настройках комнаты.", + "info": "Добро пожаловать! Вот несколько вещей, которые нужно знать о вашей комнате:", + "direct_private_chat": "Личное сообщение", + "info_retention_user": "🕓 Сообщения старше {time} будут удалены из истории." + }, + "device_list": { + "blocked": "Заблокированный", + "verified": "Проверенные", + "not_verified": "Не проверенные" + }, + "getlink": { + "next": "Вперёд", + "continue": "Продолжить", + "hello": "Здравствуйте {user},\nВот ваша прямая ссылка", + "scan_title": "Отсканируйте этот код, чтобы начать прямой разговор", + "different_link": "Получите другую ссылку", + "share_qr": "Поделиться QR", + "qr_image_copied": "Изображение копируется в буфер обмена", + "title": "Получить прямую ссылку", + "info": "Прямые ссылки дают людям возможность безопасно общаться с вами. Для начала выберите экранное имя, которое будет отображаться при входе в чат с вами.", + "ready_to_share": "Он готов к обмену! Каждый раз, когда кто-то открывает ссылку, будет открываться новая прямая комната.", + "username": "Введите имя экрана (например: waku)" + }, + "profile": { + "password_old": "Старый пароль", + "password_new": "Новый пароль", + "password_repeat": "Повторите новый пароль", + "display_name": "Отображаемое имя", + "notification_label": "Уведомления", + "set_password": "Задать пароль", + "change_password": "Изменить пароль", + "select_language": "Язык", + "title": "Мой профиль", + "temporary_identity": "Этот идентификатор является временным. Установите пароль, чтобы использовать ее снова", + "change_name": "Изменить имя", + "set_language": "Установите свой язык", + "language_description": "Convene доступен на многих языках.", + "dont_see_yours": "Не видите своего?", + "tell_us": "Расскажите нам.", + "display_name_required": "Отображаемое имя обязательно" + }, + "join": { + "user_name_label": "Имя пользователя", + "remember_me": "Запомнить меня", + "join": "Присоединиться к комнате", + "enter_room": "Войти в комнату", + "joining_as": "Вы присоединяетесь как:", + "join_user": "Начать общение", + "you_have_been_banned": "Вам запрещено посещать эту комнату.", + "title": "Добро пожаловать, вы приглашены присоединиться", + "title_user": "Добро пожаловать, вас пригласили пообщаться с", + "enter_room_user": "Начать общение", + "status_joining": "Присоединяюсь к комнате...", + "join_failed": "Не удалось присоединиться к комнате.", + "choose_name": "Выберите имя для использования", + "status_logging_in": "Вход…" + }, + "leave": { + "title_invite": "Вы уверены, что хотите выйти?", + "leave": "Оставить", + "go_back": "Назад", + "text_invite": "Эта комната заперта. Вы не сможете войти в нее без специального разрешения.", + "create_account": "создать аккаунт", + "title_public": "До свидания, {user}", + "text_public": "Вы всегда можете присоединиться к этой комнате снова, если знаете ссылку.", + "text_public_lastroom": "Если вы хотите присоединиться к этой комнате снова, вы можете присоединиться под новым именем. Чтобы сохранить {user}, {action}." + }, + "purge_room": { + "button": "Удалить", + "n_seconds": "{seconds} секунды", + "title": "Удалить комнату?", + "info": "Все пользователи и сообщения будут удалены. Это действие нельзя отменить.", + "self_destruct": "Ваша комната самоуничтожится в считанные секунды.", + "deleting": "Удаление комнаты:", + "notified": "Мы уведомили членов клуба.", + "room_deletion_notice": "Время прощаться! Эта комната была удалена {user}. Она самоуничтожится через несколько секунд." + }, + "poll_create": { + "poll_submit": "Отправить", + "create": "Опубликовать", + "answer_label_n": "Ответ", + "title": "Создать новый опрос", + "answer_label_1": "Ответ*", + "tip_title": "СОВЕТ ПРОФЕССИОНАЛА", + "creating": "Создайте опрос", + "poll_disclosed": "Открыто - текущие результаты отображаются постоянно.", + "poll_undisclosed": "Закрыто - пользователи увидят результаты, когда опрос будет закрыт.", + "add_answer": "Добавить ответ", + "failed": "Не удалось создать опрос, повторите попытку позже.", + "question_label": "Задайте свой вопрос*", + "please_complete": "Пожалуйста, заполните", + "create_poll_menu_option": "Создать опрос", + "poll_status_closed": "Опрос закрыт", + "poll_status_disclosed": "Результаты будут показаны после закрытия опроса.", + "poll_status_open": "Опрос открыт", + "poll_status_open_not_voted": "Опрос открыт - проголосуйте, чтобы увидеть результаты", + "view_results": "Посмотреть результаты", + "close_poll": "Закрытый опрос", + "question_required": "Вам нужно ввести вопрос!", + "answer_required": "Ответ не может быть пустым. Пожалуйста, введите текст или удалите этот вариант.", + "tip_text": "Участники увидят результаты опроса после того, как ответят. Закройте опрос, когда закончите, чтобы показать результаты всем присутствующим в комнате.", + "num_answered": "{count} ответов", + "results_shared": "Результаты переданы в зал." + }, + "profile_info_popup": { + "edit_profile": "Редактировать профиль", + "logout": "Выйти из системы", + "you_are": "Вы", + "identity": "{displayName}", + "identity_temporary": "{displayName}", + "want_more": "Хотите больше?", + "powered_by": "В этой комнате используется {product}. Узнайте больше на {productLink} или создайте другую комнату!", + "new_room": "Новая комната" + }, + "invite": { + "title": "Добавить друзей", + "done": "Готово", + "send_invites_to": "Присылайте приглашения по адресу", + "status_error": "Не удалось пригласить одного или нескольких друзей!", + "status_inviting": "Приглашение друга {index} из {count}" + }, + "voice_recorder": { + "not_supported_title": "Не поддерживается", + "not_supported_text": "К сожалению, этот браузер не поддерживает запись звука.", + "swipe_to_cancel": "Проведите пальцем, чтобы отменить", + "release_to_cancel": "Отпустить, чтобы отменить", + "failed_to_record": "Не удалось записать звук" + }, + "fallbacks": { + "download_name": "Загрузить", + "original_text": "<Оригинальный текст>", + "audio_file": "Аудиофайлы", + "video_file": "Видеофайлы" + }, + "notification": { + "dialog": { + "enable": "Включить", + "body": "Никогда больше не пропустите ни одного сообщения или важного разговора! Получайте уведомления, когда кто-то отправляет вам сообщение или отвечает в вашем чате.", + "title": "Оставайтесь на связи с уведомлениями в чате!" + }, + "blocked_message": "Уведомление заблокировано. Перейдите в настройки устройства или браузера, чтобы включить уведомление", + "not_supported": "Уведомления пока не поддерживаются в мобильной версии", + "title": "Получено новое сообщение", + "periodicSync_new_msg_reminder": "У вас могут появиться новые сообщения" + }, + "language_display_name": "Русский", + "project": { + "name": "Созыв", + "tag_line": "Просто подключите" + }, + "logout": { + "confirm_text": "Вы уверены, что хотите выйти из системы?" + }, + "goodbye": { + "room_deleted": "Комната удалена.", + "close_tab": "Закрыть вкладку браузера", + "view_other_rooms": "Посмотреть другие комнаты" + }, + "createchannel": { + "title": "Создать канал", + "info": "Транслируйте новости или знания в любом формате - видео, подкаст, текст, картинки или PDF-файлы.", + "channel_name": "Назовите свой канал", + "channel_topic": "Опишите его", + "name_required": "Имя канала обязательно", + "error_channel": "Не удалось создать канал" + }, + "export": { + "fetched_n_events": "Найдено {count} событий", + "fetched_n_of_total_events": "Получено {count} из {total} событий", + "export_filename": "Экспортированный чат {date}", + "processed_n_of_total_events": "Обработка носителей для {count} из {total} событий", + "exported_date": "Экспортировано в {date}" + } +} diff --git a/src/assets/translations/si.json b/src/assets/translations/si.json index da64fdd..f1d44ed 100644 --- a/src/assets/translations/si.json +++ b/src/assets/translations/si.json @@ -113,5 +113,8 @@ "dialog": { "enable": "සක්‍රිය කරන්න" } + }, + "room_welcome": { + "change": "වෙනස් කරන්න" } } diff --git a/src/assets/translations/zh_Hans.json b/src/assets/translations/zh_Hans.json index 7f53100..135e33e 100644 --- a/src/assets/translations/zh_Hans.json +++ b/src/assets/translations/zh_Hans.json @@ -30,7 +30,7 @@ "voice_mode": "语音模块", "voice_mode_info": "将聊天界面切换到“收听和录音”模式", "download_chat": "下载聊天", - "read_only_room": "只读聊天室", + "read_only_room": "只读", "read_only_room_info": "只允许管理员和版主发送到聊天室", "export_room": "导出聊天", "user_moderator": "版主", @@ -47,7 +47,9 @@ "message_retention_none": "关闭", "message_retention_1_day": "1 天", "message_retention_8_hours": "8 小时", - "message_retention_1_hour": "1 小时" + "message_retention_1_hour": "1 小时", + "message_retention_2_week": "2周", + "message_retention_1_week": "1周" }, "leave": { "leave": "离开", @@ -292,7 +294,8 @@ "encrypted": "信息是端到端加密的。", "no_past_messages": "欢迎! 为了您的安全,过去的信息不提供。", "direct_info": "你好,{you}.正在与 {user} 进行私人聊天。", - "direct_private_chat": "私信" + "direct_private_chat": "私信", + "change": "更改" }, "profile_info_popup": { "new_room": "新的聊天室", diff --git a/src/components/Chat.vue b/src/components/Chat.vue index 0446698..133caa5 100644 --- a/src/components/Chat.vue +++ b/src/components/Chat.vue @@ -54,39 +54,45 @@ + + +
{{ dayForEvent(event) }}
-
- - - - -
{{ $t('message.unread_messages') }}
-
+ +
+ + + + +
{{ $t('message.unread_messages') }}
+
+
@@ -109,7 +115,7 @@
{{ replyToEvent.getContent().body | latestReply }}
-
{{ replyToThreadMessage }}
+
{{ replyToThreadMessage }}
{{ $t("message.reply_image") }}
{{ $t("message.reply_audio_message") }}
{{ $t("message.reply_video") }}
@@ -209,7 +215,7 @@ + accept="image/*,audio/*,video/*,.mp3,.mp4,.wav,.m4a,.pdf,application/pdf,.apk,application/vnd.android.package-archive,.ipa,.zip,application/zip,application/x-zip-compressed,multipart/x-zip" class="d-none" multiple/>
@@ -251,7 +257,7 @@ + v-model="currentImageInput.useScaled" :disabled="currentImageInput && currentImageInput.sendInfo !== undefined" />
@@ -277,7 +283,7 @@ {{ $t("menu.cancel") }} {{ $t("menu.send") }} + v-if="currentSendShowSendButton" :disabled="currentSendShowSendButton && sendingStatus != sendStatuses.INITIAL">{{ $t("menu.send") }} @@ -327,6 +333,11 @@ + + +
+
+
@@ -342,6 +353,7 @@ import RoomInfoBottomSheet from "./RoomInfoBottomSheet"; import WelcomeHeaderRoom from "./welcome_headers/WelcomeHeaderRoom"; import WelcomeHeaderDirectChat from "./welcome_headers/WelcomeHeaderDirectChat"; import WelcomeHeaderChannel from "./welcome_headers/WelcomeHeaderChannel"; +import WelcomeHeaderChannelUser from "./welcome_headers/WelcomeHeaderChannelUser"; import NoHistoryRoomWelcomeHeader from "./NoHistoryRoomWelcomeHeader.vue"; import MessageOperationsBottomSheet from "./MessageOperationsBottomSheet"; import StickerPickerBottomSheet from "./StickerPickerBottomSheet"; @@ -356,6 +368,7 @@ import FileDropLayout from "./file_mode/FileDropLayout"; import roomTypeMixin from "./roomTypeMixin"; import roomMembersMixin from "./roomMembersMixin"; import PurgeRoomDialog from "../components/PurgeRoomDialog"; +import MessageErrorHandler from "./MessageErrorHandler"; const sizeOf = require("image-size"); const dataUriToBuffer = require("data-uri-to-buffer"); @@ -409,6 +422,8 @@ export default { FileDropLayout, UserProfileDialog, PurgeRoomDialog, + WelcomeHeaderChannelUser, + MessageErrorHandler }, data() { @@ -493,6 +508,11 @@ export default { retentionTimer: null, showProfileDialog: false, showPurgeConfirmation: false, + heartAnimation: false, + heartPosition: { + top: 0, + left: 0 + } }; }, @@ -533,6 +553,9 @@ export default { }, computed: { + heartEmoji() { + return this.$refs.emojiPicker.mapEmojis["Symbols"].find(({ aliases }) => aliases.includes('heart')).data; + }, compActiveMember() { const currentUserId= this.selectedEvent?.sender.userId || this.$matrix.currentUserId return this.joinedAndInvitedMembers.find(({userId}) => userId === currentUserId) @@ -764,6 +787,12 @@ export default { .filter((e) => util.downloadableTypes().includes(e.getContent().msgtype)).length}); } return ""; + }, + hearAnimationPosition() { + return { + '--top': this.heartPosition.top, + '--left': this.heartPosition.left + }; } }, @@ -869,13 +898,10 @@ export default { methods: { /** - * Set initialLoadDone to 'true'. First process all events, setting threadParent and replyEvent if needed. + * Set initialLoadDone to 'true'. This will process all events, setting threadParent and replyEvent if needed (see watcher for "initialLoadDone") */ setInitialLoadDone() { - this.events.filter(event => (event.threadRootId && !event.parentThread)).forEach(event => this.setParentThread(event)); - this.events.filter(event => (event.replyEventId && !event.replyEvent)).forEach(event => this.setReplyToEvent(event)); this.initialLoadDone = true; - console.log("Loading finished!"); }, /** @@ -998,7 +1024,7 @@ export default { }) .catch((err) => { console.log("Error fetching events!", err, this); - if (err.errcode == "M_UNKNOWN" && initialEventId) { + if (initialEventId) { // Try again without initial event! this.onRoomJoined(null); } else { @@ -1146,7 +1172,8 @@ export default { Vue.set(event, "parentThread", parentEvent); } else { // Try to load from server. - this.$matrix.matrixClient.getEventTimeline(this.timelineSet, event.threadRootId).then((tl) => { + this.$matrix.matrixClient.getEventTimeline(this.timelineSet, event.threadRootId) + .then((tl) => { if (tl) { const parentEvent = tl.getEvents().find((e) => e.getId() === event.threadRootId); if (parentEvent) { @@ -1168,7 +1195,7 @@ export default { } } } - }); + }).catch(e => console.error(e)); } }, @@ -1569,6 +1596,11 @@ export default { this.sendQuickReaction({ reaction: e.emoji, event: e.event }); }, + addQuickHeartReaction(e) { + this.heartPosition = e.position + this.sendQuickReaction({ reaction: this.heartEmoji, event: e.event }, true); + }, + setReplyToImage(event) { util .getThumbnail(this.$matrix.matrixClient, event, this.$config) @@ -1584,7 +1616,7 @@ export default { this.replyToEvent = event; this.$refs.messageInput.focus(); if (event.parentThread || event.isThreadRoot || event.isMxThread) { - this.replyToContentType = 'm.thread'; + this.replyToContentType = util.threadMessageType(); } else { this.replyToContentType = event.getContent().msgtype || 'm.poll'; } @@ -1598,8 +1630,16 @@ export default { }, redact(event) { - this.$matrix.matrixClient - .redactEvent(event.getRoomId(), event.getId()) + let promises = []; + if ((event.isThreadRoot || event.isMxThread) && this.timelineSet) { + // If this is a thread message, make sure to redact all children as well. + const children = this.timelineSet.relations.getAllChildEventsForEvent(event.getId()).filter(e => util.downloadableTypes().includes(e.getContent().msgtype)); + promises = children.map((c) => { + return this.$matrix.matrixClient.redactEvent(c.getRoomId(), c.getId(), undefined, { reason: "redactedMedia"}); + }); + } + promises.push(this.$matrix.matrixClient.redactEvent(event.getRoomId(), event.getId(), undefined, { reason: "redactedThread"})); + Promise.allSettled(promises) .then(() => { console.log("Message redacted"); }) @@ -1652,7 +1692,15 @@ export default { }); }, - sendQuickReaction(e) { + showHeartAnimation() { + const self = this; + this.heartAnimation = true; + setTimeout(() => { + self.heartAnimation = false; + }, 1000) + }, + + sendQuickReaction(e, heartAnimationFlag = false) { let previousReaction = null; // Figure out if we have already sent this emoji, in that case redact it again (toggle) @@ -1679,6 +1727,10 @@ export default { .catch((err) => { console.log("Failed to send quick reaction:", err); }); + + if(heartAnimationFlag) { + this.showHeartAnimation(); + } } }, @@ -1909,4 +1961,32 @@ export default { diff --git a/src/components/CreateChannel.vue b/src/components/CreateChannel.vue index 6e2ffb3..4a42063 100644 --- a/src/components/CreateChannel.vue +++ b/src/components/CreateChannel.vue @@ -145,18 +145,18 @@ export default { preset: "public_chat", initial_state: [ - { - type: "m.room.encryption", - state_key: "", - content: { - algorithm: "m.megolm.v1.aes-sha2", - }, - }, + // { + // type: "m.room.encryption", + // state_key: "", + // content: { + // algorithm: "m.megolm.v1.aes-sha2", + // }, + // }, { type: "m.room.history_visibility", state_key: "", content: { - history_visibility: "joined" + history_visibility: "shared" } }, { diff --git a/src/components/InputControl.vue b/src/components/InputControl.vue index 251bd7e..fb74749 100644 --- a/src/components/InputControl.vue +++ b/src/components/InputControl.vue @@ -73,7 +73,7 @@ export default { width: 100%; display: flex; position: relative; - min-height: 48px; + min-height: $min-touch-target; background: #f5f5f5; border-radius: 4px; diff --git a/src/components/MessageErrorHandler.vue b/src/components/MessageErrorHandler.vue new file mode 100644 index 0000000..7c02bb3 --- /dev/null +++ b/src/components/MessageErrorHandler.vue @@ -0,0 +1,29 @@ + + + + + + \ No newline at end of file diff --git a/src/components/MessageRetentionDialog.vue b/src/components/MessageRetentionDialog.vue index 8ebb7ce..6a37160 100644 --- a/src/components/MessageRetentionDialog.vue +++ b/src/components/MessageRetentionDialog.vue @@ -117,6 +117,6 @@ export default { } .v-radio.flex-row-reverse { - height: 48px; + height: $min-touch-target; } diff --git a/src/components/chatMixin.js b/src/components/chatMixin.js index 0318df9..076b48c 100644 --- a/src/components/chatMixin.js +++ b/src/components/chatMixin.js @@ -125,13 +125,6 @@ export default { }, componentForEvent(event, isForExport = false) { - if (!event.isRelation() && !event.isRedaction() && event.isRedacted()) { - const redaction = event.getRedactionEvent(); - if (redaction && redaction.content && redaction.content.reason === "cancel") { - return null; // Show nothing, it was canceled! - } - } - switch (event.getType()) { case "m.room.member": if (event.getContent().membership == "join") { @@ -161,6 +154,13 @@ export default { case "m.room.message": if (event.getSender() != this.$matrix.currentUserId) { + if (event.isRedacted()) { + // Redacted thread, show as text (and hide all media)! + if (event.getUnsigned().redacted_because.content.reason == "redactedThread") { + return MessageIncomingText; + } + return null; + } if (event.isMxThread) { // Incoming thread, e.g. a file drop! return isForExport ? MessageIncomingThreadExport : MessageIncomingThread; @@ -201,6 +201,13 @@ export default { } return MessageIncomingText; } else { + if (event.isRedacted()) { + // Redacted thread, show as text (and hide all media)! + if (event.getUnsigned().redacted_because.content.reason == "redactedThread") { + return MessageOutgoingText; + } + return null; + } if (event.isMxThread) { // Outgoing thread return isForExport ? MessageOutgoingThreadExport : MessageOutgoingThread; diff --git a/src/components/file_mode/ThumbnailView.vue b/src/components/file_mode/ThumbnailView.vue index 1756151..02f9b77 100644 --- a/src/components/file_mode/ThumbnailView.vue +++ b/src/components/file_mode/ThumbnailView.vue @@ -1,16 +1,16 @@ diff --git a/src/components/messages/MessageIncoming.vue b/src/components/messages/MessageIncoming.vue index 6e945be..eb40a2c 100644 --- a/src/components/messages/MessageIncoming.vue +++ b/src/components/messages/MessageIncoming.vue @@ -14,7 +14,9 @@ }} - + + +
more_vert @@ -28,10 +30,16 @@ diff --git a/src/components/messages/MessageIncomingImage.vue b/src/components/messages/MessageIncomingImage.vue index 732c584..d89d9fc 100644 --- a/src/components/messages/MessageIncomingImage.vue +++ b/src/components/messages/MessageIncomingImage.vue @@ -1,13 +1,12 @@