diff --git a/assets/l10n/intl_ar.arb b/assets/l10n/intl_ar.arb index 3e85c0e77..931d2a75c 100644 --- a/assets/l10n/intl_ar.arb +++ b/assets/l10n/intl_ar.arb @@ -1335,8 +1335,6 @@ }, "homeserver": "الخادم", "@homeserver": {}, - "enterASpacepName": "أدخل اسم الفضاء", - "@enterASpacepName": {}, "enterAnEmailAddress": "أدخل عنوان بريد إلكتروني", "@enterAnEmailAddress": { "type": "text", @@ -2382,8 +2380,6 @@ "@setChatDescription": {}, "directChat": "محادثة مباشرة", "@directChat": {}, - "requests": "الطلبات", - "@requests": {}, "inviteGroupChat": "📨 دعوة الدردشة الجماعية", "@inviteGroupChat": {}, "invitePrivateChat": "📨 دعوة دردشة خاصة", diff --git a/assets/l10n/intl_bn.arb b/assets/l10n/intl_bn.arb index de7659ac8..65457e12b 100644 --- a/assets/l10n/intl_bn.arb +++ b/assets/l10n/intl_bn.arb @@ -152,8 +152,6 @@ }, "unsupportedAndroidVersion": "", "@unsupportedAndroidVersion": {}, - "enterASpacepName": "", - "@enterASpacepName": {}, "device": "", "@device": { "type": "text", @@ -366,8 +364,6 @@ "type": "text", "placeholders": {} }, - "requests": "", - "@requests": {}, "askSSSSSign": "", "@askSSSSSign": { "type": "text", diff --git a/assets/l10n/intl_bo.arb b/assets/l10n/intl_bo.arb index 824cfdf19..3c0f6ca8e 100644 --- a/assets/l10n/intl_bo.arb +++ b/assets/l10n/intl_bo.arb @@ -129,8 +129,6 @@ }, "unsupportedAndroidVersion": "", "@unsupportedAndroidVersion": {}, - "enterASpacepName": "", - "@enterASpacepName": {}, "device": "", "@device": { "type": "text", @@ -353,8 +351,6 @@ "type": "text", "placeholders": {} }, - "requests": "", - "@requests": {}, "askSSSSSign": "", "@askSSSSSign": { "type": "text", diff --git a/assets/l10n/intl_ca.arb b/assets/l10n/intl_ca.arb index af18cf9c4..2267eef8a 100644 --- a/assets/l10n/intl_ca.arb +++ b/assets/l10n/intl_ca.arb @@ -1633,8 +1633,6 @@ "type": "text", "placeholders": {} }, - "enterASpacepName": "Introduïu un nom d’espai", - "@enterASpacepName": {}, "addAccount": "Afegeix un compte", "@addAccount": {}, "noEncryptionForPublicRooms": "Només podreu activar el xifratge quan la sala ja no sigui accessible públicament.", @@ -1948,8 +1946,6 @@ }, "banUserDescription": "", "@banUserDescription": {}, - "requests": "", - "@requests": {}, "widgetEtherpad": "", "@widgetEtherpad": {}, "removeDevicesDescription": "", diff --git a/assets/l10n/intl_cs.arb b/assets/l10n/intl_cs.arb index 736fc3759..ef33fdb61 100644 --- a/assets/l10n/intl_cs.arb +++ b/assets/l10n/intl_cs.arb @@ -716,8 +716,6 @@ "type": "text", "placeholders": {} }, - "enterASpacepName": "Zadejte název prostoru", - "@enterASpacepName": {}, "enterYourHomeserver": "Zadejte svůj domovský server", "@enterYourHomeserver": { "type": "text", @@ -2356,8 +2354,6 @@ "count": {} } }, - "requests": "Žádosti", - "@requests": {}, "reportErrorDescription": "", "@reportErrorDescription": {}, "banUserDescription": "", diff --git a/assets/l10n/intl_de.arb b/assets/l10n/intl_de.arb index 9256a9a93..dcd6b6abe 100644 --- a/assets/l10n/intl_de.arb +++ b/assets/l10n/intl_de.arb @@ -711,8 +711,6 @@ "type": "text", "placeholders": {} }, - "enterASpacepName": "Namen für den Space eingeben", - "@enterASpacepName": {}, "enterYourHomeserver": "Gib Deinen Homeserver ein", "@enterYourHomeserver": { "type": "text", @@ -2382,8 +2380,6 @@ "@addChatDescription": {}, "setChatDescription": "Chatbeschreibung festlegen", "@setChatDescription": {}, - "requests": "Anfragen", - "@requests": {}, "inviteGroupChat": "📨 Einladungen zum Gruppenchat", "@inviteGroupChat": {}, "invitePrivateChat": "📨 Einladungen zum privaten Chat", diff --git a/assets/l10n/intl_el.arb b/assets/l10n/intl_el.arb index 824cfdf19..3c0f6ca8e 100644 --- a/assets/l10n/intl_el.arb +++ b/assets/l10n/intl_el.arb @@ -129,8 +129,6 @@ }, "unsupportedAndroidVersion": "", "@unsupportedAndroidVersion": {}, - "enterASpacepName": "", - "@enterASpacepName": {}, "device": "", "@device": { "type": "text", @@ -353,8 +351,6 @@ "type": "text", "placeholders": {} }, - "requests": "", - "@requests": {}, "askSSSSSign": "", "@askSSSSSign": { "type": "text", diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index bf2383064..48f46ba1a 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -805,8 +805,6 @@ "type": "text", "placeholders": {} }, - "enterASpacepName": "Enter a space name", - "@enterASpacepName": {}, "homeserver": "Homeserver", "@homeserver": {}, "enterYourHomeserver": "Enter your homeserver", @@ -2339,7 +2337,6 @@ "setTheme": "Set theme:", "setColorTheme": "Set color theme:", "invite": "Invite", - "requests": "Requests", "inviteGroupChat": "📨 Invite group chat", "invitePrivateChat": "📨 Invite private chat", "invalidInput": "Invalid input!", @@ -2388,5 +2385,7 @@ "passwordIsWrong": "Your entered password is wrong", "publicLink": "Public link", "joinSpace": "Join space", - "publicSpaces": "Public spaces" + "publicSpaces": "Public spaces", + "addChatOrSubSpace": "Add chat or sub space", + "subspace": "Subspace" } \ No newline at end of file diff --git a/assets/l10n/intl_eo.arb b/assets/l10n/intl_eo.arb index 220aa57a5..9093140d4 100644 --- a/assets/l10n/intl_eo.arb +++ b/assets/l10n/intl_eo.arb @@ -705,8 +705,6 @@ "type": "text", "placeholders": {} }, - "enterASpacepName": "Enigi nomon de aro", - "@enterASpacepName": {}, "enterYourHomeserver": "Enigu vian hejmservilon", "@enterYourHomeserver": { "type": "text", @@ -1978,8 +1976,6 @@ }, "banUserDescription": "", "@banUserDescription": {}, - "requests": "", - "@requests": {}, "widgetEtherpad": "", "@widgetEtherpad": {}, "removeDevicesDescription": "", diff --git a/assets/l10n/intl_es.arb b/assets/l10n/intl_es.arb index 690c29543..d53fc93e2 100644 --- a/assets/l10n/intl_es.arb +++ b/assets/l10n/intl_es.arb @@ -1615,8 +1615,6 @@ "type": "text", "placeholders": {} }, - "enterASpacepName": "Ingrese nombre de espacio", - "@enterASpacepName": {}, "ignore": "Ignorar", "@ignore": { "type": "text", @@ -2124,8 +2122,6 @@ "@user": {}, "banUserDescription": "", "@banUserDescription": {}, - "requests": "", - "@requests": {}, "removeDevicesDescription": "", "@removeDevicesDescription": {}, "separateChatTypes": "Separar chats directos de grupos", diff --git a/assets/l10n/intl_et.arb b/assets/l10n/intl_et.arb index 98571c015..faa77e27d 100644 --- a/assets/l10n/intl_et.arb +++ b/assets/l10n/intl_et.arb @@ -716,8 +716,6 @@ "type": "text", "placeholders": {} }, - "enterASpacepName": "Sisesta kogukonna nimi", - "@enterASpacepName": {}, "enterYourHomeserver": "Sisesta oma koduserveri aadress", "@enterYourHomeserver": { "type": "text", @@ -2382,8 +2380,6 @@ "reason": {} } }, - "requests": "Päringud", - "@requests": {}, "inviteGroupChat": "📨 Kutsu vestlusrühma", "@inviteGroupChat": {}, "invitePrivateChat": "📨 Kutsu omavahelisele vestlusele", diff --git a/assets/l10n/intl_eu.arb b/assets/l10n/intl_eu.arb index 9d3c91186..de6e81694 100644 --- a/assets/l10n/intl_eu.arb +++ b/assets/l10n/intl_eu.arb @@ -1281,8 +1281,6 @@ "type": "text", "placeholders": {} }, - "enterASpacepName": "Sartu gunerako izena", - "@enterASpacepName": {}, "homeserver": "Zerbitzaria", "@homeserver": {}, "errorObtainingLocation": "Errorea kokapena lortzerakoan: {error}", @@ -2331,8 +2329,6 @@ "@sendTypingNotifications": {}, "setColorTheme": "Ezarri kolore-gaia:", "@setColorTheme": {}, - "requests": "Eskaerak", - "@requests": {}, "tryAgain": "Saiatu berriro", "@tryAgain": {}, "messagesStyle": "Mezuak:", diff --git a/assets/l10n/intl_fa.arb b/assets/l10n/intl_fa.arb index 655cd4ce4..6dbbab0f9 100644 --- a/assets/l10n/intl_fa.arb +++ b/assets/l10n/intl_fa.arb @@ -985,8 +985,6 @@ "type": "text", "placeholders": {} }, - "enterASpacepName": "یک نام برای فضا وارد کنید", - "@enterASpacepName": {}, "errorObtainingLocation": "خطا هنگام بدست آوردن مکان: {error}", "@errorObtainingLocation": { "type": "text", @@ -2311,8 +2309,6 @@ "@setColorTheme": {}, "banUserDescription": "", "@banUserDescription": {}, - "requests": "", - "@requests": {}, "removeDevicesDescription": "", "@removeDevicesDescription": {}, "tryAgain": "", diff --git a/assets/l10n/intl_fi.arb b/assets/l10n/intl_fi.arb index 7fefaa180..45011e051 100644 --- a/assets/l10n/intl_fi.arb +++ b/assets/l10n/intl_fi.arb @@ -1083,8 +1083,6 @@ "type": "text", "placeholders": {} }, - "enterASpacepName": "Nimeä tila", - "@enterASpacepName": {}, "inoffensive": "Loukkaamatonta", "@inoffensive": { "type": "text", @@ -2308,8 +2306,6 @@ "@pleaseTryAgainLaterOrChooseDifferentServer": {}, "setColorTheme": "Aseta väriteema:", "@setColorTheme": {}, - "requests": "Pyynnöt", - "@requests": {}, "tryAgain": "Yritä uudelleen", "@tryAgain": {}, "messagesStyle": "Viestit:", diff --git a/assets/l10n/intl_fr.arb b/assets/l10n/intl_fr.arb index 5c8792721..c5f060d04 100644 --- a/assets/l10n/intl_fr.arb +++ b/assets/l10n/intl_fr.arb @@ -720,8 +720,6 @@ "type": "text", "placeholders": {} }, - "enterASpacepName": "Entrer un nom d'espace", - "@enterASpacepName": {}, "enterYourHomeserver": "Renseignez votre serveur d'accueil", "@enterYourHomeserver": { "type": "text", @@ -2318,8 +2316,6 @@ "@setColorTheme": {}, "banUserDescription": "", "@banUserDescription": {}, - "requests": "", - "@requests": {}, "removeDevicesDescription": "", "@removeDevicesDescription": {}, "tryAgain": "", diff --git a/assets/l10n/intl_ga.arb b/assets/l10n/intl_ga.arb index 4935eae2d..27860e815 100644 --- a/assets/l10n/intl_ga.arb +++ b/assets/l10n/intl_ga.arb @@ -1389,8 +1389,6 @@ "error": {} } }, - "enterASpacepName": "Cuir isteach ainm spáis", - "@enterASpacepName": {}, "enterAnEmailAddress": "Cuir isteach seoladh ríomhphoist", "@enterAnEmailAddress": { "type": "text", @@ -2018,8 +2016,6 @@ }, "banUserDescription": "", "@banUserDescription": {}, - "requests": "", - "@requests": {}, "widgetEtherpad": "", "@widgetEtherpad": {}, "removeDevicesDescription": "", diff --git a/assets/l10n/intl_gl.arb b/assets/l10n/intl_gl.arb index 4c02e629a..de502336c 100644 --- a/assets/l10n/intl_gl.arb +++ b/assets/l10n/intl_gl.arb @@ -716,8 +716,6 @@ "type": "text", "placeholders": {} }, - "enterASpacepName": "Escribe o nome para o espazo", - "@enterASpacepName": {}, "enterYourHomeserver": "Escribe o teu servidor de inicio", "@enterYourHomeserver": { "type": "text", @@ -2382,8 +2380,6 @@ "@directChat": {}, "setChatDescription": "Escribir descrición da conversa", "@setChatDescription": {}, - "requests": "Solicitudes", - "@requests": {}, "inviteGroupChat": "📨 Convidar a conversa en grupo", "@inviteGroupChat": {}, "invitePrivateChat": "📨 Convidar a conversa privada", diff --git a/assets/l10n/intl_he.arb b/assets/l10n/intl_he.arb index 149910ad3..986b9ac4f 100644 --- a/assets/l10n/intl_he.arb +++ b/assets/l10n/intl_he.arb @@ -545,8 +545,6 @@ "type": "text", "placeholders": {} }, - "enterASpacepName": "הזן שם חלל", - "@enterASpacepName": {}, "enterYourHomeserver": "הזן את שרת הבית שלך", "@enterYourHomeserver": { "type": "text", @@ -1486,8 +1484,6 @@ }, "banUserDescription": "", "@banUserDescription": {}, - "requests": "", - "@requests": {}, "widgetEtherpad": "", "@widgetEtherpad": {}, "waitingPartnerAcceptRequest": "", diff --git a/assets/l10n/intl_hi.arb b/assets/l10n/intl_hi.arb index 86f432ada..a4a7e3ea8 100644 --- a/assets/l10n/intl_hi.arb +++ b/assets/l10n/intl_hi.arb @@ -129,8 +129,6 @@ }, "unsupportedAndroidVersion": "", "@unsupportedAndroidVersion": {}, - "enterASpacepName": "", - "@enterASpacepName": {}, "device": "", "@device": { "type": "text", @@ -353,8 +351,6 @@ "type": "text", "placeholders": {} }, - "requests": "", - "@requests": {}, "askSSSSSign": "", "@askSSSSSign": { "type": "text", diff --git a/assets/l10n/intl_hr.arb b/assets/l10n/intl_hr.arb index 050af776b..c064e5355 100644 --- a/assets/l10n/intl_hr.arb +++ b/assets/l10n/intl_hr.arb @@ -706,8 +706,6 @@ "type": "text", "placeholders": {} }, - "enterASpacepName": "Upiši ime prostora", - "@enterASpacepName": {}, "enterYourHomeserver": "Upiši svoj domaći poslužitelj", "@enterYourHomeserver": { "type": "text", @@ -2331,8 +2329,6 @@ "@sendTypingNotifications": {}, "setColorTheme": "Postavi boju teme:", "@setColorTheme": {}, - "requests": "Zahtjevi", - "@requests": {}, "tryAgain": "Pokušaj ponovo", "@tryAgain": {}, "messagesStyle": "Poruke:", diff --git a/assets/l10n/intl_hu.arb b/assets/l10n/intl_hu.arb index fb68ddbba..a744b2885 100644 --- a/assets/l10n/intl_hu.arb +++ b/assets/l10n/intl_hu.arb @@ -1454,8 +1454,6 @@ "type": "text", "placeholders": {} }, - "enterASpacepName": "Add meg a tér nevét", - "@enterASpacepName": {}, "extremeOffensive": "Extrém sértő", "@extremeOffensive": { "type": "text", @@ -1949,8 +1947,6 @@ }, "banUserDescription": "", "@banUserDescription": {}, - "requests": "", - "@requests": {}, "widgetEtherpad": "", "@widgetEtherpad": {}, "removeDevicesDescription": "", diff --git a/assets/l10n/intl_id.arb b/assets/l10n/intl_id.arb index 36d3d7d47..da5f53fff 100644 --- a/assets/l10n/intl_id.arb +++ b/assets/l10n/intl_id.arb @@ -1691,8 +1691,6 @@ }, "homeserver": "Homeserver", "@homeserver": {}, - "enterASpacepName": "Masukkan nama space", - "@enterASpacepName": {}, "enableEncryption": "Aktifkan enkripsi", "@enableEncryption": { "type": "text", @@ -2381,8 +2379,6 @@ "@setColorTheme": {}, "invite": "Undang", "@invite": {}, - "requests": "Permintaan", - "@requests": {}, "inviteGroupChat": "📨 Undang percakapan grup", "@inviteGroupChat": {}, "invitePrivateChat": "📨 Undang percakapan privat", diff --git a/assets/l10n/intl_ie.arb b/assets/l10n/intl_ie.arb index b1d81b6e0..dab4d66be 100644 --- a/assets/l10n/intl_ie.arb +++ b/assets/l10n/intl_ie.arb @@ -1192,8 +1192,6 @@ }, "unsupportedAndroidVersion": "", "@unsupportedAndroidVersion": {}, - "enterASpacepName": "", - "@enterASpacepName": {}, "youAreNoLongerParticipatingInThisChat": "", "@youAreNoLongerParticipatingInThisChat": { "type": "text", @@ -1316,8 +1314,6 @@ }, "banUserDescription": "", "@banUserDescription": {}, - "requests": "", - "@requests": {}, "askSSSSSign": "", "@askSSSSSign": { "type": "text", diff --git a/assets/l10n/intl_it.arb b/assets/l10n/intl_it.arb index 91d035ed9..e704e1dd4 100644 --- a/assets/l10n/intl_it.arb +++ b/assets/l10n/intl_it.arb @@ -1864,8 +1864,6 @@ "@chatHasBeenAddedToThisSpace": {}, "unsupportedAndroidVersion": "Versione di Android non supportata", "@unsupportedAndroidVersion": {}, - "enterASpacepName": "Inserisci un nome per lo spazio", - "@enterASpacepName": {}, "widgetJitsi": "Jitsi Meet", "@widgetJitsi": {}, "messageType": "Tipo del Messaggio", @@ -1916,8 +1914,6 @@ }, "banUserDescription": "L'utente sarà bannato dalla chat e non sarà in grado di rientrare finché non verrà sbannato.", "@banUserDescription": {}, - "requests": "Richieste", - "@requests": {}, "widgetEtherpad": "Nota di testo", "@widgetEtherpad": {}, "removeDevicesDescription": "Sarai disconnesso da questo dispositivo e non potrai più ricevere messaggi.", diff --git a/assets/l10n/intl_ja.arb b/assets/l10n/intl_ja.arb index 360932461..5ff0604fb 100644 --- a/assets/l10n/intl_ja.arb +++ b/assets/l10n/intl_ja.arb @@ -1856,8 +1856,6 @@ "@youRejectedTheInvitation": {}, "screenSharingDetail": "FuffyChatで画面を共有しています", "@screenSharingDetail": {}, - "enterASpacepName": "スペース名を入力してください", - "@enterASpacepName": {}, "homeserver": "ホームサーバー", "@homeserver": {}, "scanQrCode": "QRコードをスキャン", @@ -2244,8 +2242,6 @@ }, "banUserDescription": "", "@banUserDescription": {}, - "requests": "", - "@requests": {}, "widgetEtherpad": "", "@widgetEtherpad": {}, "removeDevicesDescription": "", diff --git a/assets/l10n/intl_ko.arb b/assets/l10n/intl_ko.arb index 71d6152f2..5e12f5e6d 100644 --- a/assets/l10n/intl_ko.arb +++ b/assets/l10n/intl_ko.arb @@ -166,8 +166,6 @@ }, "homeserver": "홈서버", "@homeserver": {}, - "enterASpacepName": "스페이스 이름 입력", - "@enterASpacepName": {}, "enterAnEmailAddress": "이메일 주소 입력", "@enterAnEmailAddress": { "type": "text", @@ -2107,8 +2105,6 @@ }, "banUserDescription": "", "@banUserDescription": {}, - "requests": "", - "@requests": {}, "widgetEtherpad": "", "@widgetEtherpad": {}, "removeDevicesDescription": "", diff --git a/assets/l10n/intl_lt.arb b/assets/l10n/intl_lt.arb index 75d904e46..ade686680 100644 --- a/assets/l10n/intl_lt.arb +++ b/assets/l10n/intl_lt.arb @@ -1196,8 +1196,6 @@ "type": "text", "placeholders": {} }, - "enterASpacepName": "Įveskite erdvės vardą", - "@enterASpacepName": {}, "send": "Siųsti", "@send": { "type": "text", @@ -2246,8 +2244,6 @@ "@setColorTheme": {}, "banUserDescription": "", "@banUserDescription": {}, - "requests": "", - "@requests": {}, "removeDevicesDescription": "", "@removeDevicesDescription": {}, "tryAgain": "", diff --git a/assets/l10n/intl_lv.arb b/assets/l10n/intl_lv.arb index 824cfdf19..3c0f6ca8e 100644 --- a/assets/l10n/intl_lv.arb +++ b/assets/l10n/intl_lv.arb @@ -129,8 +129,6 @@ }, "unsupportedAndroidVersion": "", "@unsupportedAndroidVersion": {}, - "enterASpacepName": "", - "@enterASpacepName": {}, "device": "", "@device": { "type": "text", @@ -353,8 +351,6 @@ "type": "text", "placeholders": {} }, - "requests": "", - "@requests": {}, "askSSSSSign": "", "@askSSSSSign": { "type": "text", diff --git a/assets/l10n/intl_nb.arb b/assets/l10n/intl_nb.arb index 5d39422d9..3f8404cca 100644 --- a/assets/l10n/intl_nb.arb +++ b/assets/l10n/intl_nb.arb @@ -1706,8 +1706,6 @@ }, "unsupportedAndroidVersion": "", "@unsupportedAndroidVersion": {}, - "enterASpacepName": "", - "@enterASpacepName": {}, "commandHint_html": "", "@commandHint_html": { "type": "text", @@ -1773,8 +1771,6 @@ }, "banUserDescription": "", "@banUserDescription": {}, - "requests": "", - "@requests": {}, "widgetEtherpad": "", "@widgetEtherpad": {}, "removeDevicesDescription": "", diff --git a/assets/l10n/intl_nl.arb b/assets/l10n/intl_nl.arb index 36b04de28..d04560716 100644 --- a/assets/l10n/intl_nl.arb +++ b/assets/l10n/intl_nl.arb @@ -719,8 +719,6 @@ "type": "text", "placeholders": {} }, - "enterASpacepName": "Vul een spacenaam in", - "@enterASpacepName": {}, "enterYourHomeserver": "Vul je homeserver in", "@enterYourHomeserver": { "type": "text", @@ -2381,8 +2379,6 @@ "@setColorTheme": {}, "invite": "Uitnodigen", "@invite": {}, - "requests": "Verzoeken", - "@requests": {}, "inviteGroupChat": "📨 Groeps-chat uitnodiging", "@inviteGroupChat": {}, "invitePrivateChat": "📨 Privé-chat uitnodiging", diff --git a/assets/l10n/intl_pl.arb b/assets/l10n/intl_pl.arb index 1917d2fba..4a327e243 100644 --- a/assets/l10n/intl_pl.arb +++ b/assets/l10n/intl_pl.arb @@ -1614,8 +1614,6 @@ "type": "text", "placeholders": {} }, - "enterASpacepName": "Podaj nazwę przestrzeni", - "@enterASpacepName": {}, "homeserver": "Adres serwera", "@homeserver": {}, "locationDisabledNotice": "Usługi lokalizacji są wyłączone. Proszę włącz je aby móc udostępnić swoją lokalizację.", @@ -2304,8 +2302,6 @@ "@reportErrorDescription": {}, "setColorTheme": "Ustal styl kolorów:", "@setColorTheme": {}, - "requests": "Żądania", - "@requests": {}, "tryAgain": "Spróbuj ponownie", "@tryAgain": {}, "messagesStyle": "Wiadomości:", diff --git a/assets/l10n/intl_pt.arb b/assets/l10n/intl_pt.arb index 07135a456..e8951902d 100644 --- a/assets/l10n/intl_pt.arb +++ b/assets/l10n/intl_pt.arb @@ -237,8 +237,6 @@ }, "unsupportedAndroidVersion": "", "@unsupportedAndroidVersion": {}, - "enterASpacepName": "", - "@enterASpacepName": {}, "device": "", "@device": { "type": "text", @@ -451,8 +449,6 @@ "type": "text", "placeholders": {} }, - "requests": "", - "@requests": {}, "askSSSSSign": "", "@askSSSSSign": { "type": "text", diff --git a/assets/l10n/intl_pt_BR.arb b/assets/l10n/intl_pt_BR.arb index f2ea62619..01574eff5 100644 --- a/assets/l10n/intl_pt_BR.arb +++ b/assets/l10n/intl_pt_BR.arb @@ -715,8 +715,6 @@ "type": "text", "placeholders": {} }, - "enterASpacepName": "Insira um nome pro espaço", - "@enterASpacepName": {}, "enterYourHomeserver": "Insira um servidor matriz", "@enterYourHomeserver": { "type": "text", @@ -2281,8 +2279,6 @@ "@setColorTheme": {}, "banUserDescription": "", "@banUserDescription": {}, - "requests": "", - "@requests": {}, "removeDevicesDescription": "", "@removeDevicesDescription": {}, "tryAgain": "", diff --git a/assets/l10n/intl_pt_PT.arb b/assets/l10n/intl_pt_PT.arb index a9b868dd5..5e82360ba 100644 --- a/assets/l10n/intl_pt_PT.arb +++ b/assets/l10n/intl_pt_PT.arb @@ -674,8 +674,6 @@ "type": "text", "placeholders": {} }, - "enterASpacepName": "Insere o nome do espaço", - "@enterASpacepName": {}, "homeserver": "Servidor", "@homeserver": {}, "enterYourHomeserver": "Insere o teu servidor", @@ -1703,8 +1701,6 @@ }, "banUserDescription": "", "@banUserDescription": {}, - "requests": "", - "@requests": {}, "widgetEtherpad": "", "@widgetEtherpad": {}, "waitingPartnerAcceptRequest": "", diff --git a/assets/l10n/intl_ro.arb b/assets/l10n/intl_ro.arb index ecdcde148..a95cf3a5d 100644 --- a/assets/l10n/intl_ro.arb +++ b/assets/l10n/intl_ro.arb @@ -1884,8 +1884,6 @@ "type": "text", "placeholders": {} }, - "enterASpacepName": "Introduceți nume pentru spațiu", - "@enterASpacepName": {}, "homeserver": "Homeserver", "@homeserver": {}, "errorObtainingLocation": "Obținerea locației a eșuat: {error}", @@ -2311,8 +2309,6 @@ "@setColorTheme": {}, "banUserDescription": "", "@banUserDescription": {}, - "requests": "", - "@requests": {}, "removeDevicesDescription": "", "@removeDevicesDescription": {}, "tryAgain": "", diff --git a/assets/l10n/intl_ru.arb b/assets/l10n/intl_ru.arb index 0b691125d..64db92d75 100644 --- a/assets/l10n/intl_ru.arb +++ b/assets/l10n/intl_ru.arb @@ -716,8 +716,6 @@ "type": "text", "placeholders": {} }, - "enterASpacepName": "Введите название пространства", - "@enterASpacepName": {}, "enterYourHomeserver": "Введите адрес вашего сервера Matrix", "@enterYourHomeserver": { "type": "text", @@ -2382,8 +2380,6 @@ "@setColorTheme": {}, "invite": "Пригласить", "@invite": {}, - "requests": "Запросы", - "@requests": {}, "invitePrivateChat": "📨 Пригласить в приватный чат", "@invitePrivateChat": {}, "inviteGroupChat": "📨 Пригласить в групповой чат", diff --git a/assets/l10n/intl_sk.arb b/assets/l10n/intl_sk.arb index 3afa93c3f..37d69a0f3 100644 --- a/assets/l10n/intl_sk.arb +++ b/assets/l10n/intl_sk.arb @@ -1362,8 +1362,6 @@ }, "unsupportedAndroidVersion": "", "@unsupportedAndroidVersion": {}, - "enterASpacepName": "", - "@enterASpacepName": {}, "commandHint_html": "", "@commandHint_html": { "type": "text", @@ -1434,8 +1432,6 @@ }, "banUserDescription": "", "@banUserDescription": {}, - "requests": "", - "@requests": {}, "widgetEtherpad": "", "@widgetEtherpad": {}, "removeDevicesDescription": "", diff --git a/assets/l10n/intl_sl.arb b/assets/l10n/intl_sl.arb index c65513eae..4c4406b61 100644 --- a/assets/l10n/intl_sl.arb +++ b/assets/l10n/intl_sl.arb @@ -670,8 +670,6 @@ }, "unsupportedAndroidVersion": "", "@unsupportedAndroidVersion": {}, - "enterASpacepName": "", - "@enterASpacepName": {}, "device": "", "@device": { "type": "text", @@ -857,8 +855,6 @@ "type": "text", "placeholders": {} }, - "requests": "", - "@requests": {}, "widgetEtherpad": "", "@widgetEtherpad": {}, "waitingPartnerAcceptRequest": "", diff --git a/assets/l10n/intl_sr.arb b/assets/l10n/intl_sr.arb index 143e36c1f..21d671a65 100644 --- a/assets/l10n/intl_sr.arb +++ b/assets/l10n/intl_sr.arb @@ -1840,8 +1840,6 @@ "@chatHasBeenAddedToThisSpace": {}, "unsupportedAndroidVersion": "", "@unsupportedAndroidVersion": {}, - "enterASpacepName": "", - "@enterASpacepName": {}, "widgetJitsi": "", "@widgetJitsi": {}, "messageType": "", @@ -1892,8 +1890,6 @@ }, "banUserDescription": "", "@banUserDescription": {}, - "requests": "", - "@requests": {}, "widgetEtherpad": "", "@widgetEtherpad": {}, "removeDevicesDescription": "", diff --git a/assets/l10n/intl_sv.arb b/assets/l10n/intl_sv.arb index 06bd37242..982a2562a 100644 --- a/assets/l10n/intl_sv.arb +++ b/assets/l10n/intl_sv.arb @@ -1730,8 +1730,6 @@ "error": {} } }, - "enterASpacepName": "Ange utrymmets namn", - "@enterASpacepName": {}, "editRoomAliases": "Redigera rum alias", "@editRoomAliases": { "type": "text", @@ -2301,8 +2299,6 @@ "@setColorTheme": {}, "banUserDescription": "", "@banUserDescription": {}, - "requests": "", - "@requests": {}, "removeDevicesDescription": "", "@removeDevicesDescription": {}, "tryAgain": "", diff --git a/assets/l10n/intl_ta.arb b/assets/l10n/intl_ta.arb index 3eee97927..4869050c4 100644 --- a/assets/l10n/intl_ta.arb +++ b/assets/l10n/intl_ta.arb @@ -147,8 +147,6 @@ }, "unsupportedAndroidVersion": "", "@unsupportedAndroidVersion": {}, - "enterASpacepName": "", - "@enterASpacepName": {}, "device": "", "@device": { "type": "text", @@ -361,8 +359,6 @@ "type": "text", "placeholders": {} }, - "requests": "", - "@requests": {}, "askSSSSSign": "", "@askSSSSSign": { "type": "text", diff --git a/assets/l10n/intl_th.arb b/assets/l10n/intl_th.arb index 8250c9623..f7431aff5 100644 --- a/assets/l10n/intl_th.arb +++ b/assets/l10n/intl_th.arb @@ -339,8 +339,6 @@ }, "unsupportedAndroidVersion": "", "@unsupportedAndroidVersion": {}, - "enterASpacepName": "", - "@enterASpacepName": {}, "device": "", "@device": { "type": "text", @@ -556,8 +554,6 @@ "type": "text", "placeholders": {} }, - "requests": "", - "@requests": {}, "widgetEtherpad": "", "@widgetEtherpad": {}, "waitingPartnerAcceptRequest": "", diff --git a/assets/l10n/intl_tr.arb b/assets/l10n/intl_tr.arb index efacef54c..a0a55817a 100644 --- a/assets/l10n/intl_tr.arb +++ b/assets/l10n/intl_tr.arb @@ -720,8 +720,6 @@ "type": "text", "placeholders": {} }, - "enterASpacepName": "Bir alan adı girin", - "@enterASpacepName": {}, "enterYourHomeserver": "Ana sunucunuzu girin", "@enterYourHomeserver": { "type": "text", @@ -2382,8 +2380,6 @@ "@chatDescriptionHasBeenChanged": {}, "directChat": "Doğrudan sohbet", "@directChat": {}, - "requests": "İstek", - "@requests": {}, "inviteGroupChat": "📨 Grup sohbetine davet et", "@inviteGroupChat": {}, "invitePrivateChat": "📨 Gizli sohbete davet et", diff --git a/assets/l10n/intl_uk.arb b/assets/l10n/intl_uk.arb index 4979a176f..5a5bb31bd 100644 --- a/assets/l10n/intl_uk.arb +++ b/assets/l10n/intl_uk.arb @@ -1317,8 +1317,6 @@ "type": "text", "placeholders": {} }, - "enterASpacepName": "Введіть назву простору", - "@enterASpacepName": {}, "joinRoom": "Приєднатися до кімнати", "@joinRoom": { "type": "text", @@ -2382,8 +2380,6 @@ "@redactMessageDescription": {}, "setChatDescription": "Налаштувати опис бесіди", "@setChatDescription": {}, - "requests": "Запити", - "@requests": {}, "inviteGroupChat": "📨 Запросити до групової бесіди", "@inviteGroupChat": {}, "invitePrivateChat": "📨 Запросити до приватної бесіди", diff --git a/assets/l10n/intl_vi.arb b/assets/l10n/intl_vi.arb index 731a42562..904aa9e9e 100644 --- a/assets/l10n/intl_vi.arb +++ b/assets/l10n/intl_vi.arb @@ -552,8 +552,6 @@ }, "unsupportedAndroidVersion": "", "@unsupportedAndroidVersion": {}, - "enterASpacepName": "", - "@enterASpacepName": {}, "commandHint_html": "", "@commandHint_html": { "type": "text", @@ -719,8 +717,6 @@ "type": "text", "placeholders": {} }, - "requests": "", - "@requests": {}, "askSSSSSign": "", "@askSSSSSign": { "type": "text", diff --git a/assets/l10n/intl_zh.arb b/assets/l10n/intl_zh.arb index a520bd84b..26af8d88c 100644 --- a/assets/l10n/intl_zh.arb +++ b/assets/l10n/intl_zh.arb @@ -1881,8 +1881,6 @@ "error": {} } }, - "enterASpacepName": "输入空间名称", - "@enterASpacepName": {}, "createNewSpace": "创建新空间", "@createNewSpace": { "type": "text", @@ -2382,8 +2380,6 @@ "reason": {} } }, - "requests": "请求", - "@requests": {}, "inviteGroupChat": "📨 邀请至群聊", "@inviteGroupChat": {}, "invitePrivateChat": "📨 邀请至私聊", diff --git a/assets/l10n/intl_zh_Hant.arb b/assets/l10n/intl_zh_Hant.arb index dd9fd50bc..a4d2aba32 100644 --- a/assets/l10n/intl_zh_Hant.arb +++ b/assets/l10n/intl_zh_Hant.arb @@ -1825,8 +1825,6 @@ }, "unsupportedAndroidVersion": "", "@unsupportedAndroidVersion": {}, - "enterASpacepName": "", - "@enterASpacepName": {}, "commandHint_html": "", "@commandHint_html": { "type": "text", @@ -1882,8 +1880,6 @@ }, "banUserDescription": "", "@banUserDescription": {}, - "requests": "", - "@requests": {}, "widgetEtherpad": "", "@widgetEtherpad": {}, "removeDevicesDescription": "", diff --git a/lib/pages/chat_list/chat_list.dart b/lib/pages/chat_list/chat_list.dart index 2835f4504..87eb025e8 100644 --- a/lib/pages/chat_list/chat_list.dart +++ b/lib/pages/chat_list/chat_list.dart @@ -95,6 +95,13 @@ class ChatListController extends State }); } + void createNewSpace() async { + final spaceId = await context.push('/rooms/newspace'); + if (spaceId != null) { + setActiveSpace(spaceId); + } + } + int get selectedIndex { switch (activeFilter) { case ActiveFilter.allChats: diff --git a/lib/pages/chat_list/chat_list_body.dart b/lib/pages/chat_list/chat_list_body.dart index 82034a78b..e7ba126c3 100644 --- a/lib/pages/chat_list/chat_list_body.dart +++ b/lib/pages/chat_list/chat_list_body.dart @@ -66,8 +66,7 @@ class ChatListViewBody extends StatelessWidget { .where((s) => s.hasRoomUpdate) .rateLimit(const Duration(seconds: 1)), builder: (context, _) { - if (controller.activeFilter == ActiveFilter.spaces && - !controller.isSearchMode) { + if (controller.activeFilter == ActiveFilter.spaces) { return SpaceView( controller, scrollController: controller.scrollController, diff --git a/lib/pages/chat_list/chat_list_view.dart b/lib/pages/chat_list/chat_list_view.dart index 40c8858a0..96e2a4675 100644 --- a/lib/pages/chat_list/chat_list_view.dart +++ b/lib/pages/chat_list/chat_list_view.dart @@ -212,6 +212,7 @@ class ChatListView extends StatelessWidget { activeFilter: controller.activeFilter, roomsIsEmpty: false, scrolledToTop: controller.scrolledToTop, + createNewSpace: controller.createNewSpace, ) : const SizedBox.shrink(), ), diff --git a/lib/pages/chat_list/client_chooser_button.dart b/lib/pages/chat_list/client_chooser_button.dart index a23f44b58..ad0c35397 100644 --- a/lib/pages/chat_list/client_chooser_button.dart +++ b/lib/pages/chat_list/client_chooser_button.dart @@ -264,7 +264,7 @@ class ClientChooserButton extends StatelessWidget { context.go('/rooms/newgroup'); break; case SettingsAction.newSpace: - context.go('/rooms/newspace'); + controller.createNewSpace(); break; case SettingsAction.invite: FluffyShare.shareInviteLink(context); diff --git a/lib/pages/chat_list/space_view.dart b/lib/pages/chat_list/space_view.dart index d478159f3..c07b95b3e 100644 --- a/lib/pages/chat_list/space_view.dart +++ b/lib/pages/chat_list/space_view.dart @@ -5,6 +5,7 @@ import 'package:collection/collection.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:go_router/go_router.dart'; +import 'package:matrix/matrix.dart' as sdk; import 'package:matrix/matrix.dart'; import 'package:fluffychat/pages/chat_list/chat_list.dart'; @@ -30,23 +31,57 @@ class SpaceView extends StatefulWidget { } class _SpaceViewState extends State { - static final Map> _requests = {}; + static final Map _lastResponse = {}; String? prevBatch; + Object? error; + bool loading = false; + + @override + void initState() { + loadHierarchy(); + super.initState(); + } void _refresh() { + _lastResponse.remove(widget.controller.activeSpaceId); + loadHierarchy(); + } + + Future loadHierarchy([String? prevBatch]) async { + final activeSpaceId = widget.controller.activeSpaceId!; + setState(() { - _requests.remove(widget.controller.activeSpaceId); + error = null; + loading = true; }); - } - Future getFuture(String activeSpaceId) => - _requests[activeSpaceId] ??= Matrix.of(context).client.getSpaceHierarchy( + try { + final response = await Matrix.of(context).client.getSpaceHierarchy( activeSpaceId, maxDepth: 1, from: prevBatch, ); + if (prevBatch != null) { + response.rooms.insertAll(0, _lastResponse[activeSpaceId]?.rooms ?? []); + } + setState(() { + _lastResponse[activeSpaceId] = response; + }); + return _lastResponse[activeSpaceId]!; + } catch (e) { + setState(() { + error = e; + }); + rethrow; + } finally { + setState(() { + loading = false; + }); + } + } + void _onJoinSpaceChild(SpaceRoomsChunk spaceChild) async { final client = Matrix.of(context).client; final space = client.getRoomById(widget.controller.activeSpaceId!); @@ -140,6 +175,91 @@ class _SpaceViewState extends State { } } + void _addChatOrSubSpace() async { + final roomType = await showConfirmationDialog( + context: context, + title: L10n.of(context)!.addChatOrSubSpace, + actions: [ + AlertDialogAction( + key: AddRoomType.subspace, + label: L10n.of(context)!.createNewSpace, + ), + AlertDialogAction( + key: AddRoomType.chat, + label: L10n.of(context)!.createGroup, + ), + ], + ); + if (roomType == null) return; + + final names = await showTextInputDialog( + context: context, + title: roomType == AddRoomType.subspace + ? L10n.of(context)!.createNewSpace + : L10n.of(context)!.createGroup, + textFields: [ + DialogTextField( + hintText: roomType == AddRoomType.subspace + ? L10n.of(context)!.spaceName + : L10n.of(context)!.groupName, + minLines: 1, + maxLines: 1, + maxLength: 64, + validator: (text) { + if (text == null || text.isEmpty) { + return L10n.of(context)!.pleaseChoose; + } + return null; + }, + ), + DialogTextField( + hintText: L10n.of(context)!.chatDescription, + minLines: 4, + maxLines: 8, + maxLength: 255, + ), + ], + okLabel: L10n.of(context)!.create, + cancelLabel: L10n.of(context)!.cancel, + ); + if (names == null) return; + final client = Matrix.of(context).client; + final result = await showFutureLoadingDialog( + context: context, + future: () async { + late final String roomId; + final activeSpace = client.getRoomById( + widget.controller.activeSpaceId!, + )!; + + if (roomType == AddRoomType.subspace) { + roomId = await client.createSpace( + name: names.first, + topic: names.last.isEmpty ? null : names.last, + visibility: activeSpace.joinRules == JoinRules.public + ? sdk.Visibility.public + : sdk.Visibility.private, + ); + } else { + roomId = await client.createGroupChat( + groupName: names.first, + initialState: names.length > 1 && names.last.isNotEmpty + ? [ + sdk.StateEvent( + type: sdk.EventTypes.RoomTopic, + content: {'topic': names.last}, + ), + ] + : null, + ); + } + await activeSpace.setSpaceChild(roomId); + }, + ); + if (result.error != null) return; + _refresh(); + } + @override Widget build(BuildContext context) { final client = Matrix.of(context).client; @@ -195,93 +315,93 @@ class _SpaceViewState extends State { ], ); } - return FutureBuilder( - future: getFuture(activeSpaceId), - builder: (context, snapshot) { - final response = snapshot.data; - final error = snapshot.error; - if (error != null) { - return Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.all(16.0), - child: Text(error.toLocalizedString(context)), + + final parentSpace = allSpaces.firstWhereOrNull( + (space) => + space.spaceChildren.any((child) => child.roomId == activeSpaceId), + ); + return PopScope( + canPop: parentSpace == null, + onPopInvoked: (pop) async { + if (pop) return; + if (parentSpace != null) { + widget.controller.setActiveSpace(parentSpace.id); + } + }, + child: CustomScrollView( + controller: widget.scrollController, + slivers: [ + ChatListHeader(controller: widget.controller), + SliverAppBar( + titleSpacing: 0, + title: ListTile( + leading: BackButton( + onPressed: () => + widget.controller.setActiveSpace(parentSpace?.id), ), - IconButton( - onPressed: _refresh, - icon: const Icon(Icons.refresh_outlined), + title: Text( + parentSpace == null + ? L10n.of(context)!.allSpaces + : parentSpace.getLocalizedDisplayname( + MatrixLocals(L10n.of(context)!), + ), ), - ], - ); - } - if (response == null) { - return CustomScrollView( - slivers: [ - ChatListHeader(controller: widget.controller), - const SliverFillRemaining( - child: Center( - child: CircularProgressIndicator.adaptive(), - ), + trailing: IconButton( + icon: loading + ? const CircularProgressIndicator.adaptive(strokeWidth: 2) + : const Icon(Icons.refresh_outlined), + onPressed: loading ? null : _refresh, ), - ], - ); - } - final parentSpace = allSpaces.firstWhereOrNull( - (space) => - space.spaceChildren.any((child) => child.roomId == activeSpaceId), - ); - final spaceChildren = response.rooms; - final canLoadMore = response.nextBatch != null; - return PopScope( - canPop: parentSpace == null, - onPopInvoked: (pop) async { - if (pop) return; - if (parentSpace != null) { - widget.controller.setActiveSpace(parentSpace.id); - } - }, - child: CustomScrollView( - controller: widget.scrollController, - slivers: [ - ChatListHeader(controller: widget.controller), - SliverList( + ), + ), + Builder( + builder: (context) { + final response = _lastResponse[activeSpaceId]; + final error = this.error; + if (error != null) { + return SliverFillRemaining( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.all(16.0), + child: Text(error.toLocalizedString(context)), + ), + IconButton( + onPressed: _refresh, + icon: const Icon(Icons.refresh_outlined), + ), + ], + ), + ); + } + if (response == null) { + return SliverFillRemaining( + child: Center( + child: Text(L10n.of(context)!.loadingPleaseWait), + ), + ); + } + final spaceChildren = response.rooms; + final canLoadMore = response.nextBatch != null; + return SliverList( delegate: SliverChildBuilderDelegate( (context, i) { - if (i == 0) { - return ListTile( - leading: BackButton( - onPressed: () => - widget.controller.setActiveSpace(parentSpace?.id), - ), - title: Text( - parentSpace == null - ? L10n.of(context)!.allSpaces - : parentSpace.getLocalizedDisplayname( - MatrixLocals(L10n.of(context)!), - ), - ), - trailing: IconButton( - icon: snapshot.connectionState != ConnectionState.done - ? const CircularProgressIndicator.adaptive() - : const Icon(Icons.refresh_outlined), - onPressed: - snapshot.connectionState != ConnectionState.done - ? null - : _refresh, - ), - ); - } - i--; if (canLoadMore && i == spaceChildren.length) { - return ListTile( - title: Text(L10n.of(context)!.loadMore), - trailing: const Icon(Icons.chevron_right_outlined), - onTap: () { - prevBatch = response.nextBatch; - _refresh(); - }, + return Padding( + padding: const EdgeInsets.all(16.0), + child: OutlinedButton.icon( + label: loading + ? const LinearProgressIndicator() + : Text(L10n.of(context)!.loadMore), + icon: const Icon(Icons.chevron_right_outlined), + onPressed: loading + ? null + : () { + loadHierarchy(response.nextBatch); + }, + ), ); } final spaceChild = spaceChildren[i]; @@ -299,85 +419,114 @@ class _SpaceViewState extends State { ? null : spaceChild.topic; if (spaceChild.roomId == activeSpaceId) { - return SearchTitle( - title: spaceChild.name ?? - spaceChild.canonicalAlias ?? - 'Space', - icon: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10.0), - child: Avatar( - size: 24, - mxContent: spaceChild.avatarUrl, - name: spaceChild.name, - fontSize: 9, - ), - ), - color: Theme.of(context) - .colorScheme - .secondaryContainer - .withAlpha(128), - trailing: const Padding( - padding: EdgeInsets.symmetric(horizontal: 16.0), - child: Icon(Icons.edit_outlined), - ), - onTap: () => _onJoinSpaceChild(spaceChild), - ); - } - return ListTile( - leading: Avatar( - mxContent: spaceChild.avatarUrl, - name: spaceChild.name, - ), - title: Row( + return Column( + mainAxisSize: MainAxisSize.min, children: [ - Expanded( - child: Text( - spaceChild.name ?? - spaceChild.canonicalAlias ?? - L10n.of(context)!.chat, - maxLines: 1, - style: - const TextStyle(fontWeight: FontWeight.bold), + SearchTitle( + title: spaceChild.name ?? + spaceChild.canonicalAlias ?? + 'Space', + icon: Padding( + padding: + const EdgeInsets.symmetric(horizontal: 10.0), + child: Avatar( + size: 24, + mxContent: spaceChild.avatarUrl, + name: spaceChild.name, + fontSize: 9, + ), ), + color: Theme.of(context) + .colorScheme + .secondaryContainer + .withAlpha(128), + trailing: const Padding( + padding: EdgeInsets.symmetric(horizontal: 16.0), + child: Icon(Icons.edit_outlined), + ), + onTap: () => _onJoinSpaceChild(spaceChild), ), - if (!isSpace) ...[ - const Icon( - Icons.people_outline, - size: 16, + Material( + child: ListTile( + leading: const CircleAvatar( + child: Icon(Icons.group_add_outlined), + ), + title: Text(L10n.of(context)!.addChatOrSubSpace), + trailing: + const Icon(Icons.chevron_right_outlined), + onTap: _addChatOrSubSpace, ), - const SizedBox(width: 4), - Text( - spaceChild.numJoinedMembers.toString(), - style: const TextStyle(fontSize: 14), + ), + ], + ); + } + final name = spaceChild.name ?? + spaceChild.canonicalAlias ?? + L10n.of(context)!.chat; + if (widget.controller.isSearchMode && + !name.toLowerCase().contains( + widget.controller.searchController.text, + )) { + return const SizedBox.shrink(); + } + return Material( + child: ListTile( + leading: Avatar( + mxContent: spaceChild.avatarUrl, + name: spaceChild.name, + ), + title: Row( + children: [ + Expanded( + child: Text( + name, + maxLines: 1, + style: const TextStyle( + fontWeight: FontWeight.bold, + ), + ), ), + if (!isSpace) ...[ + const Icon( + Icons.people_outline, + size: 16, + ), + const SizedBox(width: 4), + Text( + spaceChild.numJoinedMembers.toString(), + style: const TextStyle(fontSize: 14), + ), + ], ], - ], - ), - onTap: () => _onJoinSpaceChild(spaceChild), - onLongPress: () => - _onSpaceChildContextMenu(spaceChild, room), - subtitle: Text( - topic ?? - (isSpace - ? L10n.of(context)!.enterSpace - : L10n.of(context)!.enterRoom), - maxLines: 1, - style: TextStyle( - color: Theme.of(context).colorScheme.onBackground, ), + onTap: () => room?.isSpace == true + ? widget.controller.setActiveSpace(room!.id) + : _onSpaceChildContextMenu(spaceChild, room), + onLongPress: () => + _onSpaceChildContextMenu(spaceChild, room), + subtitle: Text( + topic ?? + (isSpace + ? L10n.of(context)!.enterSpace + : L10n.of(context)!.enterRoom), + maxLines: 1, + style: TextStyle( + color: Theme.of(context).colorScheme.onBackground, + ), + ), + trailing: isSpace + ? const Icon(Icons.chevron_right_outlined) + : null, ), - trailing: isSpace - ? const Icon(Icons.chevron_right_outlined) - : null, ); }, - childCount: spaceChildren.length + 1 + (canLoadMore ? 1 : 0), + childCount: spaceChildren.length + (canLoadMore ? 1 : 0), ), - ), - ], + ); + }, ), - ); - }, + ], + ), ); } } @@ -387,3 +536,5 @@ enum SpaceChildContextAction { leave, removeFromSpace, } + +enum AddRoomType { chat, subspace } diff --git a/lib/pages/chat_list/start_chat_fab.dart b/lib/pages/chat_list/start_chat_fab.dart index 192161477..c6a74c0fd 100644 --- a/lib/pages/chat_list/start_chat_fab.dart +++ b/lib/pages/chat_list/start_chat_fab.dart @@ -10,15 +10,17 @@ class StartChatFloatingActionButton extends StatelessWidget { final ActiveFilter activeFilter; final ValueNotifier scrolledToTop; final bool roomsIsEmpty; + final void Function() createNewSpace; const StartChatFloatingActionButton({ super.key, required this.activeFilter, required this.scrolledToTop, required this.roomsIsEmpty, + required this.createNewSpace, }); - void _onPressed(BuildContext context) { + void _onPressed(BuildContext context) async { switch (activeFilter) { case ActiveFilter.allChats: case ActiveFilter.messages: @@ -28,7 +30,7 @@ class StartChatFloatingActionButton extends StatelessWidget { context.go('/rooms/newgroup'); break; case ActiveFilter.spaces: - context.go('/rooms/newspace'); + createNewSpace(); break; } } diff --git a/lib/pages/new_space/new_space.dart b/lib/pages/new_space/new_space.dart index bd523941a..a5a55c8b1 100644 --- a/lib/pages/new_space/new_space.dart +++ b/lib/pages/new_space/new_space.dart @@ -1,11 +1,15 @@ +import 'dart:typed_data'; + import 'package:flutter/material.dart'; -import 'package:future_loading_dialog/future_loading_dialog.dart'; +import 'package:file_picker/file_picker.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:go_router/go_router.dart'; import 'package:matrix/matrix.dart' as sdk; import 'package:matrix/matrix.dart'; import 'package:fluffychat/pages/new_space/new_space_view.dart'; +import 'package:fluffychat/utils/localized_exception_extension.dart'; import 'package:fluffychat/widgets/matrix.dart'; class NewSpace extends StatefulWidget { @@ -16,30 +20,82 @@ class NewSpace extends StatefulWidget { } class NewSpaceController extends State { - TextEditingController controller = TextEditingController(); + TextEditingController nameController = TextEditingController(); + TextEditingController topicController = TextEditingController(); bool publicGroup = false; + bool loading = false; + String? nameError; + String? topicError; + + Uint8List? avatar; + + Uri? avatarUrl; + + void selectPhoto() async { + final photo = await FilePicker.platform.pickFiles( + type: FileType.image, + allowMultiple: false, + withData: true, + ); + + setState(() { + avatarUrl = null; + avatar = photo?.files.singleOrNull?.bytes; + }); + } void setPublicGroup(bool b) => setState(() => publicGroup = b); void submitAction([_]) async { - final matrix = Matrix.of(context); - final roomID = await showFutureLoadingDialog( - context: context, - future: () => matrix.client.createRoom( + final client = Matrix.of(context).client; + setState(() { + nameError = topicError = null; + }); + if (nameController.text.isEmpty) { + setState(() { + nameError = L10n.of(context)!.pleaseChoose; + }); + return; + } + setState(() { + loading = true; + }); + try { + final avatar = this.avatar; + avatarUrl ??= avatar == null ? null : await client.uploadContent(avatar); + + final spaceId = await client.createRoom( preset: publicGroup ? sdk.CreateRoomPreset.publicChat : sdk.CreateRoomPreset.privateChat, creationContent: {'type': RoomCreationTypes.mSpace}, visibility: publicGroup ? sdk.Visibility.public : null, - roomAliasName: publicGroup && controller.text.isNotEmpty - ? controller.text.trim().toLowerCase().replaceAll(' ', '_') + roomAliasName: publicGroup + ? nameController.text.trim().toLowerCase().replaceAll(' ', '_') : null, - name: controller.text.isNotEmpty ? controller.text : null, - ), - ); - if (roomID.error == null) { - context.go('/rooms/${roomID.result!}'); + name: nameController.text.trim(), + topic: topicController.text.isEmpty ? null : topicController.text, + powerLevelContentOverride: {'events_default': 100}, + initialState: [ + if (avatar != null) + sdk.StateEvent( + type: sdk.EventTypes.RoomAvatar, + content: {'url': avatarUrl.toString()}, + ), + ], + ); + if (!mounted) return; + context.pop(spaceId); + } catch (e) { + setState(() { + topicError = e.toLocalizedString(context); + }); + } finally { + setState(() { + loading = false; + }); } + // TODO: Go to spaces } @override diff --git a/lib/pages/new_space/new_space_view.dart b/lib/pages/new_space/new_space_view.dart index 02c2571e3..eb464855e 100644 --- a/lib/pages/new_space/new_space_view.dart +++ b/lib/pages/new_space/new_space_view.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:fluffychat/widgets/avatar.dart'; import 'package:fluffychat/widgets/layouts/max_width_body.dart'; import 'new_space.dart'; @@ -12,6 +13,7 @@ class NewSpaceView extends StatelessWidget { @override Widget build(BuildContext context) { + final avatar = controller.avatar; return Scaffold( appBar: AppBar( title: Text(L10n.of(context)!.createNewSpace), @@ -20,40 +22,103 @@ class NewSpaceView extends StatelessWidget { child: Column( mainAxisSize: MainAxisSize.min, children: [ + ListTile( + trailing: const Padding( + padding: EdgeInsets.symmetric(horizontal: 16.0), + child: Icon(Icons.info_outlined), + ), + subtitle: Text(L10n.of(context)!.newSpaceDescription), + ), + const SizedBox(height: 16), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + InkWell( + borderRadius: BorderRadius.circular(90), + onTap: controller.loading ? null : controller.selectPhoto, + child: CircleAvatar( + radius: Avatar.defaultSize / 2, + child: avatar == null + ? const Icon(Icons.camera_alt_outlined) + : ClipRRect( + borderRadius: BorderRadius.circular(90), + child: Image.memory( + avatar, + width: Avatar.defaultSize, + height: Avatar.defaultSize, + fit: BoxFit.cover, + ), + ), + ), + ), + const SizedBox(width: 16), + Expanded( + child: TextField( + controller: controller.nameController, + autocorrect: false, + readOnly: controller.loading, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.people_outlined), + hintText: L10n.of(context)!.spaceName, + errorText: controller.nameError, + ), + ), + ), + ], + ), + ), + const SizedBox(height: 16), Padding( - padding: const EdgeInsets.all(12.0), + padding: const EdgeInsets.symmetric(horizontal: 16.0), child: TextField( - controller: controller.controller, - autofocus: true, - autocorrect: false, - textInputAction: TextInputAction.go, - onSubmitted: controller.submitAction, + controller: controller.topicController, + minLines: 4, + maxLines: 4, + maxLength: 255, + readOnly: controller.loading, decoration: InputDecoration( - labelText: L10n.of(context)!.spaceName, - prefixIcon: const Icon(Icons.people_outlined), - hintText: L10n.of(context)!.enterASpacepName, + hintText: L10n.of(context)!.addChatDescription, + errorText: controller.topicError, ), ), ), + const SizedBox(height: 16), SwitchListTile.adaptive( title: Text(L10n.of(context)!.spaceIsPublic), value: controller.publicGroup, onChanged: controller.setPublicGroup, ), - ListTile( - trailing: const Padding( - padding: EdgeInsets.symmetric(horizontal: 16.0), - child: Icon(Icons.info_outlined), + Padding( + padding: const EdgeInsets.all(16.0), + child: SizedBox( + width: double.infinity, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + foregroundColor: Theme.of(context).colorScheme.onPrimary, + backgroundColor: Theme.of(context).colorScheme.primary, + ), + onPressed: + controller.loading ? null : controller.submitAction, + child: controller.loading + ? const LinearProgressIndicator() + : Row( + children: [ + Expanded( + child: Text( + L10n.of(context)!.createNewSpace, + ), + ), + Icon(Icons.adaptive.arrow_forward_outlined), + ], + ), + ), ), - subtitle: Text(L10n.of(context)!.newSpaceDescription), ), ], ), ), - floatingActionButton: FloatingActionButton( - onPressed: controller.submitAction, - child: const Icon(Icons.arrow_forward_outlined), - ), ); } }