Merge pull request #3741 from vector-im/release/1.0.15/release

Release 1.0.15
This commit is contained in:
SBiOSoftWhare 2020-10-09 18:32:15 +02:00 committed by GitHub
commit c1afce15b7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
44 changed files with 770 additions and 427 deletions

View file

@ -1,3 +1,34 @@
Changes in 1.0.15 (2020-10-09)
=================================================
✨ Features
*
🙌 Improvements
* Room: Make topic links tappable (#3713).
* Room: Add more to long room topics (#3715).
* Security screens: Update automatically shields when the trust changes.
* Room: Add floating action button to invite members.
* Pasteboard: Use MXKPasteboardManager.pasteboard on copy operations (#3732).
🐛 Bugfix
* Push: Check crypto has keys to decrypt an event before decryption attempt, avoid sync loops on failure.
⚠️ API Changes
*
🗣 Translations
*
🧱 Build
*
Others
*
Improvements:
* Upgrade MatrixKit version ([v0.12.23](https://github.com/matrix-org/matrix-ios-kit/releases/tag/v0.12.23)).
Changes in 1.0.14 (2020-10-02)
=================================================
@ -14,6 +45,7 @@ Changes in 1.0.14 (2020-10-02)
* Fix "Unable to open the link" error when using non-Safari browsers (#3673).
* Biometrics: Handle retry case.
* Room: Remove membership events from room creation modal (#3679).
* PIN: Fix layout on small screens.
⚠️ API Changes
*

10
Podfile
View file

@ -11,7 +11,7 @@ use_frameworks!
# - `{ {kit spec hash} => {sdk spec hash}` to depend on specific pod options (:git => …, :podspec => …) for each repo. Used by Fastfile during CI
#
# Warning: our internal tooling depends on the name of this variable name, so be sure not to change it
$matrixKitVersion = '= 0.12.22'
$matrixKitVersion = '= 0.12.23'
# $matrixKitVersion = :local
# $matrixKitVersion = {'develop' => 'develop'}
@ -74,6 +74,7 @@ abstract_target 'RiotPods' do
pod 'KTCenterFlowLayout', '~> 1.3.1'
pod 'ZXingObjC', '~> 3.6.5'
pod 'FlowCommoniOS', '~> 1.8.7'
pod 'ReadMoreTextView', '~> 3.0.1'
target 'RiotTests' do
inherit! :search_paths
@ -102,7 +103,12 @@ post_install do |installer|
# Because the WebRTC pod (included by the JingleCallStack pod) does not support it.
# Plus the app does not enable it
target.build_configurations.each do |config|
config.build_settings['ENABLE_BITCODE'] = 'NO'
config.build_settings['ENABLE_BITCODE'] = 'NO'
# Force ReadMoreTextView to use Swift 5.2 version (as there is no code changes to perform)
if target.name.include? 'ReadMoreTextView'
config.build_settings['SWIFT_VERSION'] = '5.2'
end
end
end
end

View file

@ -7277,7 +7277,7 @@
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1.0.14;
CURRENT_PROJECT_VERSION = 1.0.15;
DEFINES_MODULE = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
@ -7297,7 +7297,7 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = 1.0.14;
MARKETING_VERSION = 1.0.15;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@ -7336,7 +7336,7 @@
CODE_SIGN_IDENTITY = "iPhone Distribution";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
COPY_PHASE_STRIP = YES;
CURRENT_PROJECT_VERSION = 1.0.14;
CURRENT_PROJECT_VERSION = 1.0.15;
DEFINES_MODULE = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@ -7349,7 +7349,7 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = 1.0.14;
MARKETING_VERSION = 1.0.15;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;

View file

@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "FAB.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "FAB@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "FAB@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View file

@ -1,5 +1,5 @@
/* New message from a specific person, not referencing a room */
"MSG_FROM_USER" = "Missatge de %@";
"MSG_FROM_USER" = "%@ ha enviat un missatge";
/* New message from a specific person in a named room */
"MSG_FROM_USER_IN_ROOM" = "%@ publicat a %@";
/* New message from a specific person, not referencing a room. Content included. */
@ -11,7 +11,7 @@
/* New action message from a specific person in a named room. */
"ACTION_FROM_USER_IN_ROOM" = "%@: * %@ %@";
/* New action message from a specific person, not referencing a room. */
"IMAGE_FROM_USER" = "%@ t'ha enviat una foto %@";
"IMAGE_FROM_USER" = "%@ ha enviat una foto %@";
/* New action message from a specific person in a named room. */
"IMAGE_FROM_USER_IN_ROOM" = "%@ ha publicat una foto %@ a %@";
/* Multiple unread messages in a room */
@ -50,3 +50,14 @@
"SINGLE_UNREAD_IN_ROOM" = "Has rebut un missatge a %@";
/* A single unread message */
"SINGLE_UNREAD" = "Has rebut un missatge";
/* Message title for a specific person in a named room */
"MSG_FROM_USER_IN_ROOM_TITLE" = "%@ a %@";
/* Sticker from a specific person, not referencing a room. */
"STICKER_FROM_USER" = "%@ tha enviat una enganxina";
/* New message indicator on unknown room */
"MESSAGE" = "Missatge";
/* New message indicator from a DM */
"MESSAGE_FROM_X" = "Missatge de %@";
/* New message indicator on a room */
"MESSAGE_IN_X" = "Missatge a %@";
"KEY_VERIFICATION_REQUEST_FROM_USER" = "%@ vol verificar";

View file

@ -552,3 +552,18 @@
// Re-request confirmation dialog
"rerequest_keys_alert_title" = "Sol·licitud enviada";
"rerequest_keys_alert_message" = "Inicia Element en un altre dispositiu que pugui desxifrar el missatge per que pugui enviar les claus a aquest dispositiu.";
// String for App Store
"store_short_description" = "Xat/VoIP segur i descentralitzat";
"close" = "Tanca";
"skip" = "Salta";
"joined" = "Unit";
"switch" = "Canvia";
"more" = "Més";
// Accessibility
"accessibility_checkbox_label" = "casella de selecció";
// MARK: Clients
"client_desktop_name" = "Element Escriptori";
"client_web_name" = "Element Web";
"client_ios_name" = "Element iOS";
"client_android_name" = "Element Android";
"auth_login_single_sign_on" = "Inicia sessió amb inici senzill";

View file

@ -1187,7 +1187,7 @@
"pin_protection_choose_pin_welcome_after_login" = "Willkommen zurück.";
"pin_protection_choose_pin_welcome_after_register" = "Willkommen.";
"pin_protection_not_allowed_pin" = "Aus Sicherheitsgründen ist diese PIN nicht verfügbar. Bitte versuche es mit einer anderen PIN";
"pin_protection_explanatory" = "PINs helfen dein Profil, deine Nachrichten und Kontakte so zu sichern, dass nur du Zugriff auf sie hast.";
"pin_protection_explanatory" = "Das Einrichten einer PIN schützt Daten wie Nachrichten und Kontakten so, dass nur du Zugriff auf sie hast, indem du die PIN beim Starten der App eingibst.";
"searchable_directory_create_new_room" = "Erstelle einen neuen Raum";
"searchable_directory_x_network" = "%@ Netzwerk";
"searchable_directory_search_placeholder" = "Name oder ID";
@ -1210,3 +1210,20 @@
"room_info_list_one_member" = "1 Mitglied";
"room_info_list_several_members" = "%@ Mitglieder";
"room_info_list_section_other" = "Sonstige";
"room_participants_leave_prompt_title_for_dm" = "Verlassen";
"room_participants_filter_room_members_for_dm" = "Mitglieder filtern";
"room_participants_security_information_room_not_encrypted_for_dm" = "Die Nachrichten hier sind nicht Ende-zu-Ende verschlüsselt.";
"room_participants_leave_prompt_msg_for_dm" = "Bist du sicher, dass du die Konversation verlassen möchtest?";
"room_participants_security_information_room_encrypted_for_dm" = "Nachrichten hier sind Ende-zu-Ende verschlüsselt.\n\nDeine Nachrichten sind mit digitalen Schlüsseln gesichert, nur du und der/die Empfänger!n haben die einzigen Schlüssel, um jene zu entsperren.";
"room_details_title_for_dm" = "Details";
"room_details_photo_for_dm" = "Bild";
"room_details_room_name_for_dm" = "Name";
"room_details_access_section_for_dm" = "Wer hat Zugriff hierauf?";
"room_details_access_section_anyone_apart_from_guest_for_dm" = "Alle, die den Link kennen (ausgenommen Gäste)";
"room_details_access_section_anyone_for_dm" = "Alle, die den Link kennen (auch Gäste)";
"room_details_access_section_directory_toggle_for_dm" = "Im Raum-Verzeichnis auflisten";
"room_details_no_local_addresses_for_dm" = "Keine lokalen Adressen vorhanden";
"room_details_advanced_room_id_for_dm" = "ID:";
"room_details_advanced_e2e_encryption_enabled_for_dm" = "Verschlüsselung ist hier aktiviert";
"room_details_advanced_e2e_encryption_disabled_for_dm" = "Verschlüsselung ist hier nicht aktiviert.";
"pin_protection_kick_user_alert_message" = "Zu viele Fehler. Du wurdest ausgeloggt";

View file

@ -62,6 +62,7 @@
"joined" = "Joined";
"switch" = "Switch";
"more" = "More";
"less" = "Less";
// Accessibility
"accessibility_checkbox_label" = "checkbox";

View file

@ -1147,7 +1147,7 @@
"pin_protection_choose_pin_welcome_after_login" = "Tere tulemast tagasi.";
"pin_protection_choose_pin_welcome_after_register" = "Tere tulemast.";
"pin_protection_not_allowed_pin" = "Turvapõhjustel seda PIN-kooi ei saa kasutada. Palun vali mõnu muu PIN-kood";
"pin_protection_explanatory" = "PIN-kood aitab tagada, et vaid sina ise pääsed ligi oma profiilile, sõnumitele ja kontaktidele.";
"pin_protection_explanatory" = "PIN-koodi seadistamine aitab tagada, et vaid sina ise pääsed ligi oma profiilile, sõnumitele ja kontaktidele, kui sisestad PIN-koodi rakenduse käivitamisel.";
"searchable_directory_create_new_room" = "Loo uus jututuba";
"searchable_directory_x_network" = "%@ võrk";
"searchable_directory_search_placeholder" = "Nimi või Matrix'i tunnus";
@ -1170,3 +1170,20 @@
"room_info_list_one_member" = "1 liige";
"room_info_list_several_members" = "%@ liiget";
"room_info_list_section_other" = "Muud";
"room_participants_leave_prompt_title_for_dm" = "Lahku";
"room_participants_leave_prompt_msg_for_dm" = "Kas oled kindel, et soovid lahkuda jututoast?";
"room_participants_filter_room_members_for_dm" = "Filtreeri jututoa liikmeid";
"room_participants_security_information_room_not_encrypted_for_dm" = "See jututuba ei ole läbivalt krüptitud.";
"room_participants_security_information_room_encrypted_for_dm" = "Sõnumid siin jututoas kasutavad läbivat krüptimist. \n \nSinu sõnumid on turvatud ning ainult sinul ja saaja(te)l on unikaalsed võtmed selliste sõnumite lugemiseks.";
"room_details_title_for_dm" = "Jututoa üksikasjad";
"room_details_photo_for_dm" = "Jututoa foto";
"room_details_room_name_for_dm" = "Nimi";
"room_details_access_section_for_dm" = "Kes pääsevad ligi siia jututuppa?";
"room_details_access_section_anyone_apart_from_guest_for_dm" = "Kõik, kes teavad jututoa viidet, välja arvatud külalised";
"room_details_access_section_anyone_for_dm" = "Kõik, kes teavad jututoa viidet, kaasa arvatud külalised";
"room_details_access_section_directory_toggle_for_dm" = "Näita seda jututuba jututubade kataloogis";
"room_details_no_local_addresses_for_dm" = "Sellel jututoal puuduvad kohalikud aadressid";
"room_details_advanced_room_id_for_dm" = "Jututoa tunnus:";
"room_details_advanced_e2e_encryption_enabled_for_dm" = "Krüptimine on selles jututoas kasutusel";
"room_details_advanced_e2e_encryption_disabled_for_dm" = "Krüptimine ei ole selles jututoas kasutusel.";
"pin_protection_kick_user_alert_message" = "Liiga palju vigu PIN-koodi sisestamisel ning sa oled nüüd välja logitud";

View file

@ -353,7 +353,7 @@
"settings_crypto_blacklist_unverified_devices" = "Csak ellenőrzött munkameneteknek titkosít";
"settings_deactivate_my_account" = "Felhasználói fiókom felfüggesztése";
"room_details_people" = "Tagok";
"room_details_files" = "Fájlok";
"room_details_files" = "Feltöltések";
"room_details_settings" = "Beállítások";
"room_details_photo" = "Szoba képe";
"room_details_room_name" = "Szoba neve";
@ -1174,7 +1174,7 @@
"external_link_confirmation_title" = "Ezt a hivatkozást ellenőrizd le még egyszer";
"external_link_confirmation_message" = "%@ hivatkozás egy másik oldalra visz: %@ \n \nFolytatod?";
"major_update_information" = "Izgatottan jelentjük, hogy megváltoztattuk a nevünket! Az alkalmazásod friss és be vagy jelentkezve a fiókodba.";
"pin_protection_choose_pin" = "A biztonság érdekében válassz egy PIN kódot";
"pin_protection_choose_pin" = "A biztonság érdekében adj meg egy PIN kódot";
"pin_protection_confirm_pin" = "Erősítsd meg a PIN kódot";
"pin_protection_confirm_pin_to_disable" = "A PIN letiltásához írd be a PIN kódot";
"pin_protection_enter_pin" = "Add meg a PIN kódot";
@ -1205,3 +1205,48 @@
"biometrics_cant_unlocked_alert_message_retry" = "Újra";
"biometrics_desetup_subtitle" = " ";
"device_verification_self_verify_wait_recover_secrets_checking_availability" = "További hitelesítési lehetőségek keresése …";
"joined" = "Csatlakozott";
"switch" = "Cserél";
"more" = "További";
"room_participants_leave_prompt_title_for_dm" = "Elhagy";
"room_participants_leave_prompt_msg_for_dm" = "Biztos, hogy ki akarsz lépni?";
"room_participants_filter_room_members_for_dm" = "Tagok szűrése";
"room_participants_security_information_room_not_encrypted_for_dm" = "Itt az üzenetek nincsenek végponttól végpontig titkosítva.";
"room_participants_security_information_room_encrypted_for_dm" = "Itt az üzenetek végponttól végpontig titkosítva vannak. \n \nAz üzeneteidet titkosítással vannak biztosítva és csak neked és a címzetteknek van meg a kulcs hozzá.";
"room_details_title_for_dm" = "Részletek";
"room_details_photo_for_dm" = "Fotó";
"room_details_room_name_for_dm" = "Név";
"room_details_access_section_for_dm" = "Ki tud hozzáférni ehhez?";
"room_details_access_section_anyone_apart_from_guest_for_dm" = "Bárki aki ismeri a linket, a vendégeket leszámítva";
"room_details_access_section_anyone_for_dm" = "Bárki aki ismeri a linket, beleszámítva a vendégek";
"room_details_access_section_directory_toggle_for_dm" = "Megjelenik a szobák listájában";
"room_details_no_local_addresses_for_dm" = "Ennek nincs helyi címe";
"room_details_advanced_room_id_for_dm" = "Azon.:";
"room_details_advanced_e2e_encryption_enabled_for_dm" = "A titkosítás bekapcsolva";
"room_details_advanced_e2e_encryption_disabled_for_dm" = "Itt a titkosítás nincs bekapcsolva.";
"pin_protection_choose_pin_welcome_after_login" = "Üdv újra.";
"pin_protection_choose_pin_welcome_after_register" = "Üdv!";
"pin_protection_not_allowed_pin" = "Ez a PIN biztonsági okokból nem használható. Kérlek adj meg egy másik PIN-t";
"pin_protection_explanatory" = "A PIN beállításával védheted az olyan dolgokat, mint pl. üzenetek és névjegyek, hogy csak te férhessél hozzájuk az alkalmazás indulásakor megadott PIN kóddal.";
"pin_protection_kick_user_alert_message" = "Túl sok a hiba, ki lettél jelentkeztetve";
"searchable_directory_create_new_room" = "Új szoba készítése";
"searchable_directory_x_network" = "%@ hálózat";
"searchable_directory_search_placeholder" = "Név vagy azon.";
"create_room_title" = "Új szoba";
"create_room_section_header_name" = "Szoba neve";
"create_room_placeholder_name" = "Név";
"create_room_section_header_topic" = "Szoba témája (nem kötelező)";
"create_room_placeholder_topic" = "Téma";
"create_room_section_header_encryption" = "Szoba titkosítása";
"create_room_enable_encryption" = "Titkosítás engedélyezése";
"create_room_section_footer_encryption" = "A titkosítást ezután nem lehet kikapcsolni.";
"create_room_section_header_type" = "Szoba típusa";
"create_room_type_private" = "Privát szoba";
"create_room_type_public" = "Nyilvános szoba";
"create_room_section_footer_type" = "Emberek csak meghívóval csatlakozhatnak a privát szobához.";
"create_room_show_in_directory" = "A szoba megjelenítése a listában";
"create_room_section_header_address" = "Szoba címe";
"create_room_placeholder_address" = "#testroom:matrix.org";
"room_info_list_one_member" = "1 tag";
"room_info_list_several_members" = "%@ tag";
"room_info_list_section_other" = "Más";

View file

@ -1181,7 +1181,7 @@
"pin_protection_choose_pin_welcome_after_login" = "Bentornato/a.";
"pin_protection_choose_pin_welcome_after_register" = "Benvenuti.";
"pin_protection_not_allowed_pin" = "Per motivi di sicurezza, questo PIN non è disponibile. Provane un altro";
"pin_protection_explanatory" = "I PIN aiutano a tenere sicuri il tuo profilo, i messaggi e i contatti, in modo che solo tu possa vederli.";
"pin_protection_explanatory" = "L'impostazione di un PIN ti permette di proteggere dati come messaggi e contatti, in modo che solo tu possa vederli inserendo il PIN all'apertura dell'app.";
"searchable_directory_create_new_room" = "Crea una nuova stanza";
"searchable_directory_x_network" = "Rete %@";
"searchable_directory_search_placeholder" = "Nome o ID";
@ -1204,3 +1204,20 @@
"room_info_list_one_member" = "1 membro";
"room_info_list_several_members" = "%@ membri";
"room_info_list_section_other" = "Altro";
"room_participants_leave_prompt_title_for_dm" = "Esci";
"room_participants_leave_prompt_msg_for_dm" = "Vuoi veramente uscire?";
"room_participants_filter_room_members_for_dm" = "Filtra membri";
"room_participants_security_information_room_not_encrypted_for_dm" = "I messaggi qui non sono cifrati end-to-end.";
"room_participants_security_information_room_encrypted_for_dm" = "I messaggi qui sono cifrati end-to-end. \n \nI tuoi messaggi sono protetti con lucchetti e solo tu e il destinatario avete le chiavi univoche per sbloccarli.";
"room_details_title_for_dm" = "Dettagli";
"room_details_photo_for_dm" = "Foto";
"room_details_room_name_for_dm" = "Nome";
"room_details_access_section_for_dm" = "Chi può accedervi?";
"room_details_access_section_anyone_apart_from_guest_for_dm" = "Chiunque conosca il link, eccetto gli ospiti";
"room_details_access_section_anyone_for_dm" = "Chiunque conosca il link, compresi gli ospiti";
"room_details_access_section_directory_toggle_for_dm" = "Mostra nell'elenco delle stanze";
"room_details_no_local_addresses_for_dm" = "Non ha indirizzi locali";
"room_details_advanced_room_id_for_dm" = "ID:";
"room_details_advanced_e2e_encryption_enabled_for_dm" = "La crittografia è attiva";
"room_details_advanced_e2e_encryption_disabled_for_dm" = "La crittografia non è attiva.";
"pin_protection_kick_user_alert_message" = "Troppi errori, sei stato disconnesso";

View file

@ -55,3 +55,9 @@
/* Incoming named video conference invite from a specific person */
"VIDEO_CONF_NAMED_FROM_USER" = "Grupowe połączenie wideo z %@: '%@'";
"KEY_VERIFICATION_REQUEST_FROM_USER" = "%@ wymaga weryfikacji";
/* New message indicator on unknown room */
"MESSAGE" = "Wiadomość";
/* New message indicator from a DM */
"MESSAGE_FROM_X" = "Wiadomość od %@";
/* New message indicator on a room */
"MESSAGE_IN_X" = "Wiadomość w %@";

View file

@ -1192,7 +1192,7 @@
"pin_protection_choose_pin_welcome_after_login" = "С возвращением.";
"pin_protection_choose_pin_welcome_after_register" = "Добро пожаловать.";
"pin_protection_not_allowed_pin" = "По соображениям безопасности этот PIN-код недоступен. Пожалуйста, попробуйте другой PIN-код";
"pin_protection_explanatory" = "PIN-коды помогают защитить ваш профиль, сообщения и контакты, поэтому только вы можете получить к ним доступ.";
"pin_protection_explanatory" = "Установка PIN-кода позволяет защитить такие данные, как сообщения и контакты, поэтому только вы можете получить к ним доступ, введя PIN-код в начале приложения.";
"searchable_directory_create_new_room" = "Создать новую комнату";
"searchable_directory_x_network" = "%@ Сеть";
"searchable_directory_search_placeholder" = "Имя или ID";
@ -1231,3 +1231,4 @@
"room_details_advanced_room_id_for_dm" = "ID:";
"room_details_advanced_e2e_encryption_enabled_for_dm" = "Шифрование включено";
"room_details_advanced_e2e_encryption_disabled_for_dm" = "Шифрование не включено.";
"pin_protection_kick_user_alert_message" = "Слишком много ошибок, вы вышли из системы";

View file

@ -1193,7 +1193,7 @@
"pin_protection_choose_pin_welcome_after_login" = "Mirë se u kthyet.";
"pin_protection_choose_pin_welcome_after_register" = "Mirë se vini.";
"pin_protection_not_allowed_pin" = "Për arsye sigurie, ky PIN sështë i passhëm. Ju lutemi, provoni një PIN tjetër";
"pin_protection_explanatory" = "PIN-et ndihmojnë për të mbajtur të siguruar profilin, mesazhet dhe kontaktet tuaja, që kështu të mund ti përdorni.";
"pin_protection_explanatory" = "Ujdisja e një PIN-it ju lejon të mbroni të dhëna të tilla si, mesazhe dhe kontakte, që kështu të mund ti përdorni duke dhënë PIN-in gjatë nisjes së aplikacionit.";
"searchable_directory_create_new_room" = "Krijoni një dhomë të re";
"searchable_directory_x_network" = "Rrjet %@";
"searchable_directory_search_placeholder" = "Emër ose ID";
@ -1216,3 +1216,20 @@
"room_info_list_one_member" = "1 anëtar";
"room_info_list_several_members" = "%@ anëtarë";
"room_info_list_section_other" = "Tjetër";
"room_participants_leave_prompt_title_for_dm" = "Ikni";
"room_participants_leave_prompt_msg_for_dm" = "Jeni i sigurt se doni të ikni?";
"room_participants_filter_room_members_for_dm" = "Filtroni anëtarë";
"room_participants_security_information_room_not_encrypted_for_dm" = "Mesazhet këtu sjanë të fshehtëzuar skaj-më-skaj.";
"room_participants_security_information_room_encrypted_for_dm" = "Mesazhet këtu janë të fshehtëzuar skaj-më-skaj.\n\nMesazhet tuaj janë të siguruar me kyçe dhe vetëm ju dhe marrësi keni kyçet unikë për shkyçjen e tyre.";
"room_details_title_for_dm" = "Hollësi";
"room_details_photo_for_dm" = "Foto";
"room_details_room_name_for_dm" = "Emër";
"room_details_access_section_for_dm" = "Kush mund të përdorë këtë?";
"room_details_access_section_anyone_apart_from_guest_for_dm" = "Cilido që njeh lidhjen, hiq vizitorë";
"room_details_access_section_anyone_for_dm" = "Cilido që njeh lidhjen, përfshi vizitorë";
"room_details_access_section_directory_toggle_for_dm" = "Paraqit çka lista e dhomave";
"room_details_no_local_addresses_for_dm" = "Kjo ska adresa vendore";
"room_details_advanced_room_id_for_dm" = "ID:";
"room_details_advanced_e2e_encryption_enabled_for_dm" = "Këtu fshehtëzimi është i aktivizuar";
"room_details_advanced_e2e_encryption_disabled_for_dm" = "Këtu fshehtëzimi sështë i aktivizuar.";
"pin_protection_kick_user_alert_message" = "Shumë gabime, u bë nxjerrja juaj jashtë";

View file

@ -462,7 +462,7 @@
"identity_server_settings_alert_no_terms_title" = "Identitetsservern har inga användarvillkor";
"identity_server_settings_alert_change_title" = "Byt identitetsserver";
"room_details_people" = "Medlemmar";
"room_details_files" = "Filer";
"room_details_files" = "Uppladdningar";
"room_details_settings" = "Inställningar";
"room_details_room_name" = "Rumsnamn";
"room_details_topic" = "Ämne";
@ -1111,7 +1111,7 @@
"major_update_information" = "Vi är glada att meddela att vi har bytt namn! Din app är uppdaterad och du är inloggad på ditt konto.";
"major_update_learn_more_action" = "Lär dig mer";
"major_update_done_action" = "Förstått";
"pin_protection_choose_pin" = "Väl en PIN-kod för säkerhet";
"pin_protection_choose_pin" = "Skapa en PIN-kod för säkerhet";
"pin_protection_confirm_pin" = "Bekräfta din PIN-kod";
"pin_protection_confirm_pin_to_disable" = "Bekräfta PIN-kod för att inaktivera PIN-kod";
"pin_protection_enter_pin" = "Ange din PIN-kod";
@ -1140,3 +1140,49 @@
"biometrics_cant_unlocked_alert_message_x" = "För att låsa upp, använd %@ eller logga in igen och aktivera %@ igen";
"biometrics_cant_unlocked_alert_message_login" = "Logga in igen";
"biometrics_cant_unlocked_alert_message_retry" = "Försök igen";
"joined" = "Gått med";
"switch" = "Byt";
"more" = "Mer";
"room_participants_leave_prompt_title_for_dm" = "Lämna";
"room_participants_leave_prompt_msg_for_dm" = "Är du säker på att du vill lämna?";
"room_participants_filter_room_members_for_dm" = "Filtrera medlemmar";
"room_participants_security_information_room_not_encrypted_for_dm" = "Meddelanden här är inte totalsträckskrypterade.";
"room_participants_security_information_room_encrypted_for_dm" = "Meddelanden här är totalsträckskrypterade.\n\nDina meddelanden är säkrade med lås och endast du och mottagaren har de unika nycklarna för att låsa upp dem.";
"room_details_title_for_dm" = "Detaljer";
"room_details_photo_for_dm" = "Bild";
"room_details_room_name_for_dm" = "Namn";
"room_details_access_section_for_dm" = "Vem kan komma åt detta?";
"room_details_access_section_anyone_apart_from_guest_for_dm" = "Alla som har länken, förutom gäster";
"room_details_access_section_anyone_for_dm" = "Alla som har länken, inklusive gäster";
"room_details_access_section_directory_toggle_for_dm" = "Lista i rumskatalogen";
"room_details_no_local_addresses_for_dm" = "Detta har inga lokala adresser";
"room_details_advanced_room_id_for_dm" = "ID:";
"room_details_advanced_e2e_encryption_enabled_for_dm" = "Kryptering är aktiverad här";
"room_details_advanced_e2e_encryption_disabled_for_dm" = "Kryptering är inte aktiverad här.";
"device_verification_self_verify_wait_recover_secrets_checking_availability" = "Letar efter andra verifieringsfunktioner…";
"pin_protection_choose_pin_welcome_after_login" = "Välkommen tillbaka.";
"pin_protection_choose_pin_welcome_after_register" = "Välkommen.";
"pin_protection_not_allowed_pin" = "Av säkerhetsskäl är den här PIN-koden inte tillgänglig. Vänligen pröva en annan PIN-kod";
"pin_protection_explanatory" = "Att ställa in en PIN-kod låter dig skydda data som meddelanden och kontakter så att endast du kan komma åt dem genom att slå in koden när du startar appen.";
"pin_protection_kick_user_alert_message" = "För många fel, du har loggats ut";
"searchable_directory_create_new_room" = "Skapa ett nytt rum";
"searchable_directory_x_network" = "%@-nätverk";
"searchable_directory_search_placeholder" = "Namn eller ID";
"create_room_title" = "Nytt rum";
"create_room_section_header_name" = "Rumsnamn";
"create_room_placeholder_name" = "Namn";
"create_room_section_header_topic" = "Rumsämne (valfritt)";
"create_room_placeholder_topic" = "Ämne";
"create_room_section_header_encryption" = "Rumskryptering";
"create_room_enable_encryption" = "Aktivera kryptering";
"create_room_section_footer_encryption" = "Kryptering kan inte inaktiveras igen.";
"create_room_section_header_type" = "Rumstyp";
"create_room_type_private" = "Privat rum";
"create_room_type_public" = "Offentligt rum";
"create_room_section_footer_type" = "Personer kan endast gå med i ett privat rum om de bjuds in.";
"create_room_show_in_directory" = "Visa rummet i katalogen";
"create_room_section_header_address" = "Rumsadress";
"create_room_placeholder_address" = "#testrum:matrix.org";
"room_info_list_one_member" = "1 medlem";
"room_info_list_several_members" = "%@ medlemmar";
"room_info_list_section_other" = "Andra";

View file

@ -1469,6 +1469,28 @@
SOFTWARE.
<br/><br/>
</li>
<li>
<b>ReadMoreTextView</b> (<a href="https://github.com/ilyapuchka/ReadMoreTextView">https://github.com/ilyapuchka/ReadMoreTextView</a>)
<br/><br/>UITextView subclass with "read more"/"read less" capabilities and UITextView extensions to handle touches in characters range.
<br/><br/>It is released under the MIT license.
<br/><br/>Copyright (c) 2015-2016 Ilya Puchka
<br/><br/>Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
<br/><br/>The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
<br/><br/>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
<br/><br/>
</li>
</ul>
</body>
</html>

View file

@ -28,5 +28,37 @@ extension UITableView {
}
return result
}
/// Since UITableView does not manage Auto Layout for header, it'd be appropriate calling this after tableView bounds change
@objc func vc_relayoutHeaderView() {
guard let headerView = tableHeaderView else { return }
let height = ceil(headerView.systemLayoutSizeFitting(CGSize(width: bounds.width, height: 0),
withHorizontalFittingPriority: .required,
verticalFittingPriority: .fittingSizeLevel).height)
// compare heights to avoid infinite loop
if height != headerView.frame.height {
var headerFrame = headerView.frame
headerFrame.size.height = height
headerView.frame = headerFrame
tableHeaderView = headerView
}
}
/// Since UITableView does not manage Auto Layout for footer, it'd be appropriate calling this after tableView bounds change
@objc func vc_relayoutFooterView() {
guard let footerView = tableFooterView else { return }
let height = ceil(footerView.systemLayoutSizeFitting(CGSize(width: bounds.width, height: 0),
withHorizontalFittingPriority: .required,
verticalFittingPriority: .fittingSizeLevel).height)
// compare heights to avoid infinite loop
if height != footerView.frame.height {
var headerFrame = footerView.frame
headerFrame.size.height = height
footerView.frame = headerFrame
tableFooterView = footerView
}
}
}

View file

@ -18,6 +18,12 @@ import UIKit
extension UIViewController {
private enum UIViewControllerConstants {
static let fabButtonSize = CGSize(width: 78, height: 78)
static let fabButtonTrailingMargin: CGFloat = 0
static let fabButtonBottomMargin: CGFloat = 9
}
/// Remove back bar button title when pushing a view controller.
/// This method should be called on the previous controller in UINavigationController stack.
@objc func vc_removeBackTitle() {
@ -61,4 +67,40 @@ extension UIViewController {
func vc_removeFromParent() {
self.vc_removeChildViewController(viewController: self)
}
/// Adds a floating action button to the bottom-right of the page.
/// - Parameters:
/// - image: Image to be showed in fab
/// - target: target of the button
/// - action: action of the button
/// - Returns: The FAB view
@discardableResult
@objc func vc_addFAB(withImage image: UIImage,
target: Any?,
action: Selector?) -> UIImageView {
let fabImageView = UIImageView(image: image)
fabImageView.translatesAutoresizingMaskIntoConstraints = false
fabImageView.backgroundColor = .clear
fabImageView.contentMode = .center
fabImageView.layer.shadowOpacity = 0.3
fabImageView.layer.shadowOffset = CGSize(width: 0, height: 3)
fabImageView.isUserInteractionEnabled = true
self.view.addSubview(fabImageView)
fabImageView.widthAnchor.constraint(equalToConstant: UIViewControllerConstants.fabButtonSize.width).isActive = true
fabImageView.heightAnchor.constraint(equalToConstant: UIViewControllerConstants.fabButtonSize.height).isActive = true
fabImageView.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor,
constant: UIViewControllerConstants.fabButtonTrailingMargin).isActive = true
self.view.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: fabImageView.bottomAnchor,
constant: UIViewControllerConstants.fabButtonBottomMargin).isActive = true
let tapGestureRecognizer = UITapGestureRecognizer(target: target, action: action)
tapGestureRecognizer.numberOfTouchesRequired = 1
tapGestureRecognizer.numberOfTapsRequired = 1
fabImageView.addGestureRecognizer(tapGestureRecognizer)
return fabImageView
}
}

View file

@ -87,6 +87,7 @@ internal enum Asset {
internal static let uploadIcon = ImageAsset(name: "upload_icon")
internal static let voiceCallHangonIcon = ImageAsset(name: "voice_call_hangon_icon")
internal static let voiceCallHangupIcon = ImageAsset(name: "voice_call_hangup_icon")
internal static let addMemberFloatingAction = ImageAsset(name: "add_member_floating_action")
internal static let addParticipant = ImageAsset(name: "add_participant")
internal static let detailsIcon = ImageAsset(name: "details_icon")
internal static let editIcon = ImageAsset(name: "edit_icon")

View file

@ -1910,6 +1910,10 @@ internal enum VectorL10n {
internal static var leave: String {
return VectorL10n.tr("Vector", "leave")
}
/// Less
internal static var less: String {
return VectorL10n.tr("Vector", "less")
}
/// Got it
internal static var majorUpdateDoneAction: String {
return VectorL10n.tr("Vector", "major_update_done_action")

View file

@ -233,7 +233,7 @@ static RageShakeManager* sharedInstance = nil;
UIGraphicsEndImageContext();
// the image is copied in the clipboard
[UIPasteboard generalPasteboard].image = image;
MXKPasteboardManager.shared.pasteboard.image = image;
return image;
}

View file

@ -119,10 +119,6 @@
- (void)cancelEditionMode:(BOOL)forceRefresh;
#pragma mark - Room handling
/**
Add the (+) button at the right bottom corner of the view.
*/
- (void)addPlusButton;
/**
Action triggered when the user taps on the (+) button.

View file

@ -1606,36 +1606,6 @@
#pragma mark - Room handling
- (void)addPlusButton
{
// Add room options button
plusButtonImageView = [[UIImageView alloc] init];
[plusButtonImageView setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view addSubview:plusButtonImageView];
plusButtonImageView.backgroundColor = [UIColor clearColor];
plusButtonImageView.contentMode = UIViewContentModeCenter;
plusButtonImageView.image = [UIImage imageNamed:@"plus_floating_action"];
plusButtonImageView.layer.shadowOpacity = 0.3;
plusButtonImageView.layer.shadowOffset = CGSizeMake(0, 3);
CGFloat side = 78.0f;
[plusButtonImageView.widthAnchor constraintEqualToConstant:side].active = YES;
[plusButtonImageView.heightAnchor constraintEqualToConstant:side].active = YES;
// align to safe area
[plusButtonImageView.trailingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor].active = YES;
[self.view.safeAreaLayoutGuide.bottomAnchor constraintEqualToAnchor:plusButtonImageView.bottomAnchor constant:9].active = YES;
plusButtonImageView.userInteractionEnabled = YES;
// Handle tap gesture
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onPlusButtonPressed)];
[tap setNumberOfTouchesRequired:1];
[tap setNumberOfTapsRequired:1];
[plusButtonImageView addGestureRecognizer:tap];
}
- (void)onPlusButtonPressed
{
__weak typeof(self) weakSelf = self;

View file

@ -102,7 +102,9 @@
self.groupsSearchBar.placeholder = NSLocalizedStringFromTable(@"search_default_placeholder", @"Vector", nil);
// @TODO: Add programmatically the (+) button.
//[self addPlusButton];
// plusButtonImageView = [self vc_addFABWithImage:[UIImage imageNamed:@"plus_floating_action"]
// target:self
// action:@selector(onPlusButtonPressed)];
// Observe user interface theme change.
kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
@ -549,63 +551,6 @@
#pragma mark - Room handling
- (void)addPlusButton
{
// Add room options button
plusButtonImageView = [[UIImageView alloc] init];
[plusButtonImageView setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view addSubview:plusButtonImageView];
plusButtonImageView.backgroundColor = [UIColor clearColor];
plusButtonImageView.contentMode = UIViewContentModeCenter;
plusButtonImageView.image = [UIImage imageNamed:@"plus_floating_action"];
plusButtonImageView.layer.shadowOpacity = 0.3;
plusButtonImageView.layer.shadowOffset = CGSizeMake(0, 3);
CGFloat side = 78.0f;
NSLayoutConstraint* widthConstraint = [NSLayoutConstraint constraintWithItem:plusButtonImageView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1
constant:side];
NSLayoutConstraint* heightConstraint = [NSLayoutConstraint constraintWithItem:plusButtonImageView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1
constant:side];
NSLayoutConstraint* trailingConstraint = [NSLayoutConstraint constraintWithItem:plusButtonImageView
attribute:NSLayoutAttributeTrailing
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeTrailing
multiplier:1
constant:0];
NSLayoutConstraint* bottomConstraint = [NSLayoutConstraint constraintWithItem:self.bottomLayoutGuide
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:plusButtonImageView
attribute:NSLayoutAttributeBottom
multiplier:1
constant:9];
[NSLayoutConstraint activateConstraints:@[widthConstraint, heightConstraint, trailingConstraint, bottomConstraint]];
plusButtonImageView.userInteractionEnabled = YES;
// Handle tap gesture
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onPlusButtonPressed)];
[tap setNumberOfTouchesRequired:1];
[tap setNumberOfTapsRequired:1];
[plusButtonImageView addGestureRecognizer:tap];
}
- (void)onPlusButtonPressed
{
__weak typeof(self) weakSelf = self;

View file

@ -73,7 +73,9 @@
self.recentsTableView.tag = RecentsDataSourceModeHome;
// Add the (+) button programmatically
[self addPlusButton];
plusButtonImageView = [self vc_addFABWithImage:[UIImage imageNamed:@"plus_floating_action"]
target:self
action:@selector(onPlusButtonPressed)];
// Register table view cell used for rooms collection.
[self.recentsTableView registerClass:TableViewCellWithCollectionView.class forCellReuseIdentifier:TableViewCellWithCollectionView.defaultReuseIdentifier];

View file

@ -66,10 +66,9 @@
self.recentsTableView.tag = RecentsDataSourceModePeople;
// Add the (+) button programmatically
[self addPlusButton];
// Apply tintColor on the (+) button
plusButtonImageView.image = [UIImage imageNamed:@"people_floating_action"];
plusButtonImageView = [self vc_addFABWithImage:[UIImage imageNamed:@"people_floating_action"]
target:self
action:@selector(onPlusButtonPressed)];
// Register table view cell for contacts.
[self.recentsTableView registerClass:ContactTableViewCell.class forCellReuseIdentifier:ContactTableViewCell.defaultReuseIdentifier];

View file

@ -51,13 +51,6 @@
RoomMemberDetailsViewController *memberDetailsViewController;
ContactsTableViewController *contactsPickerViewController;
// Display a gradient view above the screen.
CAGradientLayer* tableViewMaskLayer;
// Display a button to invite new member.
UIImageView* addParticipantButtonImageView;
NSLayoutConstraint *addParticipantButtonImageViewBottomConstraint;
UIAlertController *currentAlert;
// Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change.
@ -141,8 +134,12 @@
[self.tableView registerClass:ContactTableViewCell.class forCellReuseIdentifier:@"ParticipantTableViewCellId"];
// Add room creation button programmatically
[self addAddParticipantButton];
// Add invite members button programmatically
[self vc_addFABWithImage:[UIImage imageNamed:@"add_member_floating_action"]
target:self
action:@selector(onAddParticipantButtonPressed)];
// Observe user interface theme change.
kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
@ -168,15 +165,6 @@
self.view.backgroundColor = self.tableView.backgroundColor;
self.tableView.separatorColor = ThemeService.shared.theme.lineBreakColor;
// Update the gradient view above the screen
CGFloat white = 1.0;
[ThemeService.shared.theme.backgroundColor getWhite:&white alpha:nil];
CGColorRef opaqueWhiteColor = [UIColor colorWithWhite:white alpha:1.0].CGColor;
CGColorRef transparentWhiteColor = [UIColor colorWithWhite:white alpha:0].CGColor;
tableViewMaskLayer.colors = @[(__bridge id) transparentWhiteColor, (__bridge id) transparentWhiteColor, (__bridge id) opaqueWhiteColor];
addParticipantButtonImageView.tintColor = ThemeService.shared.theme.tintColor;
if (self.tableView.dataSource)
{
[self.tableView reloadData];
@ -304,40 +292,6 @@
}
}
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
// Sanity check
if (tableViewMaskLayer)
{
CGRect currentBounds = tableViewMaskLayer.bounds;
CGRect newBounds = CGRectIntegral(self.view.frame);
newBounds.size.height -= self.keyboardHeight;
// Check if there is an update
if (!CGSizeEqualToSize(currentBounds.size, newBounds.size))
{
newBounds.origin = CGPointZero;
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseIn
animations:^{
tableViewMaskLayer.bounds = newBounds;
}
completion:^(BOOL finished){
}];
}
// Hide the addParticipants button on landscape when keyboard is visible
BOOL isLandscapeOriented = UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation);
addParticipantButtonImageView.hidden = tableViewMaskLayer.hidden = (isLandscapeOriented && self.keyboardHeight);
}
}
#pragma mark -
- (void)setMxRoom:(MXRoom *)mxRoom
@ -554,24 +508,6 @@
}
}
- (void)setKeyboardHeight:(CGFloat)keyboardHeight
{
super.keyboardHeight = keyboardHeight;
// Update addParticipants button position with animation
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseIn
animations:^{
addParticipantButtonImageViewBottomConstraint.constant = keyboardHeight + 9;
// Force to render the view
[self.view layoutIfNeeded];
}
completion:^(BOOL finished){
}];
}
#pragma mark - Internals
- (void)refreshTableView
@ -587,88 +523,6 @@
topViewController.navigationItem.leftBarButtonItem = nil;
}
- (void)addAddParticipantButton
{
// Add blur mask programmatically
tableViewMaskLayer = [CAGradientLayer layer];
// Consider the grayscale components of the ThemeService.shared.theme.backgroundColor.
CGFloat white = 1.0;
[ThemeService.shared.theme.backgroundColor getWhite:&white alpha:nil];
CGColorRef opaqueWhiteColor = [UIColor colorWithWhite:white alpha:1.0].CGColor;
CGColorRef transparentWhiteColor = [UIColor colorWithWhite:white alpha:0].CGColor;
tableViewMaskLayer.colors = @[(__bridge id) transparentWhiteColor, (__bridge id) transparentWhiteColor, (__bridge id) opaqueWhiteColor];
// display a gradient to the rencents bottom (20% of the bottom of the screen)
tableViewMaskLayer.locations = @[@0.0F,
@0.85F,
@1.0F];
tableViewMaskLayer.bounds = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
tableViewMaskLayer.anchorPoint = CGPointZero;
// CAConstraint is not supported on IOS.
// it seems only being supported on Mac OS.
// so viewDidLayoutSubviews will refresh the layout bounds.
[self.view.layer addSublayer:tableViewMaskLayer];
// Add + button
addParticipantButtonImageView = [[UIImageView alloc] init];
[addParticipantButtonImageView setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view addSubview:addParticipantButtonImageView];
addParticipantButtonImageView.backgroundColor = [UIColor clearColor];
addParticipantButtonImageView.contentMode = UIViewContentModeCenter;
addParticipantButtonImageView.image = [UIImage imageNamed:@"add_participant"];
CGFloat side = 78.0f;
NSLayoutConstraint* widthConstraint = [NSLayoutConstraint constraintWithItem:addParticipantButtonImageView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1
constant:side];
NSLayoutConstraint* heightConstraint = [NSLayoutConstraint constraintWithItem:addParticipantButtonImageView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1
constant:side];
NSLayoutConstraint* centerXConstraint = [NSLayoutConstraint constraintWithItem:addParticipantButtonImageView
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterX
multiplier:1
constant:0];
addParticipantButtonImageViewBottomConstraint = [NSLayoutConstraint constraintWithItem:self.view
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:addParticipantButtonImageView
attribute:NSLayoutAttributeBottom
multiplier:1
constant:self.keyboardHeight + 9];
// Available on iOS 8 and later
[NSLayoutConstraint activateConstraints:@[widthConstraint, heightConstraint, centerXConstraint, addParticipantButtonImageViewBottomConstraint]];
addParticipantButtonImageView.userInteractionEnabled = YES;
// Handle tap gesture
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onAddParticipantButtonPressed)];
[tap setNumberOfTouchesRequired:1];
[tap setNumberOfTapsRequired:1];
[tap setDelegate:self];
[addParticipantButtonImageView addGestureRecognizer:tap];
}
- (void)onAddParticipantButtonPressed
{
// Push the contacts picker.

View file

@ -50,8 +50,9 @@ final class RoomInfoListViewController: UIViewController {
private lazy var basicInfoView: RoomInfoBasicView = {
let view = RoomInfoBasicView.loadFromNib()
view.autoresizingMask = .flexibleWidth
view.translatesAutoresizingMaskIntoConstraints = true
view.onTopicSizeChange = { _ in
self.view.setNeedsLayout()
}
return view
}()
@ -127,25 +128,25 @@ final class RoomInfoListViewController: UIViewController {
return self.theme.statusBarStyle
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
mainTableView.vc_relayoutHeaderView()
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
coordinator.animate(alongsideTransition: {_ in
self.basicInfoView.updateTrimmingOnTopic()
}, completion: nil)
}
// MARK: - Private
private func updateSections(with viewData: RoomInfoListViewData) {
isRoomDirect = viewData.isDirect
basicInfoView.configure(withViewData: viewData.basicInfoViewData)
var tmpSections: [Section] = []
if viewData.isEncrypted {
let footer = viewData.isDirect ?
VectorL10n.roomParticipantsSecurityInformationRoomEncryptedForDm :
VectorL10n.roomParticipantsSecurityInformationRoomEncrypted
let sectionSecurity = Section(header: VectorL10n.securitySettingsTitle,
rows: [],
footer: footer)
tmpSections.append(sectionSecurity)
}
let rowSettings = Row(type: .default, icon: Asset.Images.settingsIcon.image, text: VectorL10n.roomDetailsSettings, accessoryType: .disclosureIndicator) {
self.viewModel.process(viewAction: .navigate(target: .settings))
}
@ -163,7 +164,7 @@ final class RoomInfoListViewController: UIViewController {
rowUploads],
footer: nil)
let leaveTitle = viewData.isDirect ?
let leaveTitle = viewData.basicInfoViewData.isDirect ?
VectorL10n.roomParticipantsLeavePromptTitleForDm :
VectorL10n.roomParticipantsLeavePromptTitle
let rowLeave = Row(type: .destructive, icon: Asset.Images.roomActionLeave.image, text: leaveTitle, accessoryType: .none) {

View file

@ -21,7 +21,5 @@ import Foundation
/// View data object to represent view
struct RoomInfoListViewData {
let numberOfMembers: Int
let isEncrypted: Bool
let isDirect: Bool
let basicInfoViewData: RoomInfoBasicViewData
}

View file

@ -41,11 +41,11 @@ final class RoomInfoListViewModel: NSObject, RoomInfoListViewModelType {
roomDisplayName: room.summary.displayname,
mainRoomAlias: room.summary.aliases?.first,
roomTopic: room.summary.topic,
encryptionImage: encryptionImage)
encryptionImage: encryptionImage,
isEncrypted: room.summary.isEncrypted,
isDirect: room.isDirect)
return RoomInfoListViewData(numberOfMembers: Int(room.summary.membersCount.joined),
isEncrypted: room.summary.isEncrypted,
isDirect: room.isDirect,
basicInfoViewData: basicInfoViewData)
}

View file

@ -16,8 +16,15 @@
import UIKit
import Reusable
import ReadMoreTextView
class RoomInfoBasicView: UIView {
private enum TopicTextViewConstants {
static let font = UIFont.systemFont(ofSize: 15)
static let defaultNumberOfLines = 4
static let moreLessTextPadding = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)
}
@IBOutlet private weak var mainStackView: UIStackView!
@IBOutlet private weak var avatarImageView: MXKImageView!
@ -39,7 +46,42 @@ class RoomInfoBasicView: UIView {
@IBOutlet private weak var badgeImageView: UIImageView!
@IBOutlet private weak var roomNameLabel: UILabel!
@IBOutlet private weak var roomAddressLabel: UILabel!
@IBOutlet private weak var roomTopicLabel: UILabel!
@IBOutlet private weak var topicContainerView: UIView!
@IBOutlet private weak var topicTitleLabel: UILabel! {
didSet {
topicTitleLabel.text = VectorL10n.roomDetailsTopic
}
}
@IBOutlet private weak var roomTopicTextView: ReadMoreTextView! {
didSet {
roomTopicTextView.contentInset = .zero
roomTopicTextView.textContainerInset = .zero
roomTopicTextView.textContainer.lineFragmentPadding = 0
roomTopicTextView.readMoreTextPadding = TopicTextViewConstants.moreLessTextPadding
roomTopicTextView.readLessTextPadding = TopicTextViewConstants.moreLessTextPadding
roomTopicTextView.shouldTrim = true
roomTopicTextView.maximumNumberOfLines = TopicTextViewConstants.defaultNumberOfLines
roomTopicTextView.onSizeChange = { _ in
self.roomTopicTextView.textAlignment = .left
self.onTopicSizeChange?(self)
}
}
}
@IBOutlet private weak var securityContainerView: UIView!
@IBOutlet private weak var securityTitleLabel: UILabel!
@IBOutlet private weak var securityInformationLabel: UILabel!
/// Block to be invoked when topic text view changes its content size.
var onTopicSizeChange: ((RoomInfoBasicView) -> Void)?
/// Force to update topic text view trimming.
func updateTrimmingOnTopic() {
roomTopicTextView.setNeedsUpdateTrim()
let currentValue = roomTopicTextView.shouldTrim
roomTopicTextView.shouldTrim = !currentValue
roomTopicTextView.shouldTrim = currentValue
roomTopicTextView.textAlignment = .left
}
func configure(withViewData viewData: RoomInfoBasicViewData) {
let avatarImage = AvatarGenerator.generateAvatar(forMatrixItem: viewData.roomId, withDisplayName: viewData.roomDisplayName)
@ -61,10 +103,15 @@ class RoomInfoBasicView: UIView {
roomNameLabel.text = viewData.roomDisplayName
roomAddressLabel.text = viewData.mainRoomAlias
roomAddressLabel.isHidden = roomAddressLabel.text?.isEmpty ?? true
roomTopicLabel.text = viewData.roomTopic
roomTopicLabel.isHidden = roomTopicLabel.text?.isEmpty ?? true
roomTopicTextView.text = viewData.roomTopic
topicContainerView.isHidden = roomTopicTextView.text?.isEmpty ?? true
securityTitleLabel.text = VectorL10n.securitySettingsTitle
securityInformationLabel.text = viewData.isDirect ?
VectorL10n.roomParticipantsSecurityInformationRoomEncryptedForDm :
VectorL10n.roomParticipantsSecurityInformationRoomEncrypted
securityContainerView.isHidden = !viewData.isEncrypted
}
}
extension RoomInfoBasicView: NibLoadable {}
@ -75,7 +122,33 @@ extension RoomInfoBasicView: Themable {
backgroundColor = theme.headerBackgroundColor
roomNameLabel.textColor = theme.textPrimaryColor
roomAddressLabel.textColor = theme.textSecondaryColor
roomTopicLabel.textColor = theme.textSecondaryColor
topicTitleLabel.textColor = theme.textSecondaryColor
roomTopicTextView.textColor = theme.textPrimaryColor
roomTopicTextView.linkTextAttributes = [
NSAttributedString.Key.font: TopicTextViewConstants.font,
NSAttributedString.Key.foregroundColor: theme.tintColor
]
let mutableReadMore = NSMutableAttributedString(string: "", attributes: [
NSAttributedString.Key.font: TopicTextViewConstants.font,
NSAttributedString.Key.foregroundColor: theme.textPrimaryColor
])
let attributedMore = NSAttributedString(string: VectorL10n.more, attributes: [
NSAttributedString.Key.font: TopicTextViewConstants.font,
NSAttributedString.Key.foregroundColor: theme.tintColor
])
mutableReadMore.append(attributedMore)
roomTopicTextView.attributedReadMoreText = mutableReadMore
let mutableReadLess = NSMutableAttributedString(string: " ")
let attributedLess = NSAttributedString(string: VectorL10n.less, attributes: [
NSAttributedString.Key.font: TopicTextViewConstants.font,
NSAttributedString.Key.foregroundColor: theme.tintColor
])
mutableReadLess.append(attributedLess)
roomTopicTextView.attributedReadLessText = mutableReadLess
securityTitleLabel.textColor = theme.textSecondaryColor
securityInformationLabel.textColor = theme.textPrimaryColor
}
}

View file

@ -10,21 +10,21 @@
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB" customClass="RoomInfoBasicView" customModule="Riot" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="414" height="183"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="307"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" verticalCompressionResistancePriority="751" axis="vertical" distribution="equalSpacing" alignment="center" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="xmU-kN-zva">
<rect key="frame" x="0.0" y="0.0" width="414" height="183"/>
<stackView opaque="NO" contentMode="scaleToFill" verticalCompressionResistancePriority="751" axis="vertical" alignment="center" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="xmU-kN-zva">
<rect key="frame" x="26" y="0.0" width="362" height="307"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Tgy-Pv-0Gz">
<rect key="frame" x="87" y="0.0" width="240" height="1"/>
<rect key="frame" x="61" y="0.0" width="240" height="1"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="1" id="5Hy-Jn-UrY"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="uhx-GK-2je">
<rect key="frame" x="167" y="11" width="80" height="80"/>
<rect key="frame" x="141" y="9" width="80" height="80"/>
<subviews>
<view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="6tV-Ha-dWM" customClass="MXKImageView">
<rect key="frame" x="0.0" y="0.0" width="80" height="80"/>
@ -63,34 +63,94 @@
<constraint firstAttribute="trailing" secondItem="szu-r5-TIX" secondAttribute="trailing" id="xqQ-Ue-Ldl"/>
</constraints>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" text="Label" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ekk-PI-fnh">
<rect key="frame" x="182" y="100.5" width="50.5" height="24"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" text="Label" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ekk-PI-fnh">
<rect key="frame" x="156" y="97" width="50.5" height="24"/>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="20"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" text="Label" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Yjw-ez-u4W">
<rect key="frame" x="187.5" y="134.5" width="39.5" height="19.5"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" text="Label" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Qyh-eC-KBG">
<rect key="frame" x="187.5" y="163.5" width="39.5" height="19.5"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Yjw-ez-u4W">
<rect key="frame" x="161.5" y="129" width="39.5" height="19.5"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="NSk-JY-5iY">
<rect key="frame" x="0.0" y="156.5" width="362" height="78"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Topic" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cTV-D7-Uha">
<rect key="frame" x="0.0" y="8" width="33" height="16"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" verticalHuggingPriority="252" scrollEnabled="NO" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" editable="NO" text="Lorem ipsum" translatesAutoresizingMaskIntoConstraints="NO" id="DCx-MH-TSC" customClass="ReadMoreTextView" customModule="ReadMoreTextView">
<rect key="frame" x="0.0" y="36" width="362" height="34"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="textColor" systemColor="labelColor" cocoaTouchSystemColor="darkTextColor"/>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
<dataDetectorType key="dataDetectorTypes" phoneNumber="YES" link="YES" address="YES" calendarEvent="YES" shipmentTrackingNumber="YES" flightNumber="YES"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="maximumNumberOfLines">
<integer key="value" value="4"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="boolean" keyPath="shouldTrim" value="YES"/>
</userDefinedRuntimeAttributes>
</textView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="DCx-MH-TSC" firstAttribute="top" secondItem="cTV-D7-Uha" secondAttribute="bottom" constant="12" id="LY8-cQ-p3H"/>
<constraint firstAttribute="trailing" secondItem="DCx-MH-TSC" secondAttribute="trailing" id="Nrg-wG-AlG"/>
<constraint firstItem="cTV-D7-Uha" firstAttribute="leading" secondItem="NSk-JY-5iY" secondAttribute="leading" id="Uab-wX-GVB"/>
<constraint firstItem="cTV-D7-Uha" firstAttribute="top" secondItem="NSk-JY-5iY" secondAttribute="top" constant="8" id="Ut8-xr-JTf"/>
<constraint firstItem="DCx-MH-TSC" firstAttribute="leading" secondItem="NSk-JY-5iY" secondAttribute="leading" id="c6P-hF-axm"/>
<constraint firstAttribute="bottom" secondItem="DCx-MH-TSC" secondAttribute="bottom" constant="8" id="h2M-48-9Ly"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="l54-5L-xAv">
<rect key="frame" x="0.0" y="242.5" width="362" height="64.5"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Security" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="peB-51-q5w">
<rect key="frame" x="0.0" y="8" width="50" height="18.5"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Messages in this room are end to end encrypted" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="HAS-Tr-iTE">
<rect key="frame" x="0.0" y="38.5" width="362" height="18"/>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="HAS-Tr-iTE" secondAttribute="trailing" id="6Ai-05-Ysx"/>
<constraint firstItem="HAS-Tr-iTE" firstAttribute="top" secondItem="peB-51-q5w" secondAttribute="bottom" constant="12" id="HZu-IN-h4I"/>
<constraint firstItem="peB-51-q5w" firstAttribute="leading" secondItem="l54-5L-xAv" secondAttribute="leading" id="IjP-wz-F8H"/>
<constraint firstItem="peB-51-q5w" firstAttribute="top" secondItem="l54-5L-xAv" secondAttribute="top" constant="8" id="LFK-W4-Gpw"/>
<constraint firstAttribute="bottom" secondItem="HAS-Tr-iTE" secondAttribute="bottom" constant="8" id="Sjx-QS-Rfb"/>
<constraint firstItem="HAS-Tr-iTE" firstAttribute="leading" secondItem="l54-5L-xAv" secondAttribute="leading" id="vnf-AI-9s6"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="NSk-JY-5iY" firstAttribute="leading" secondItem="xmU-kN-zva" secondAttribute="leading" id="Rds-uI-ZDv"/>
<constraint firstAttribute="trailing" secondItem="l54-5L-xAv" secondAttribute="trailing" id="ggk-iS-EdG"/>
<constraint firstAttribute="trailing" secondItem="NSk-JY-5iY" secondAttribute="trailing" id="lwP-Fm-6fy"/>
<constraint firstItem="l54-5L-xAv" firstAttribute="leading" secondItem="xmU-kN-zva" secondAttribute="leading" id="q9M-lt-GmG"/>
</constraints>
</stackView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="xmU-kN-zva" secondAttribute="trailing" id="JAT-xr-qng"/>
<constraint firstAttribute="trailingMargin" secondItem="xmU-kN-zva" secondAttribute="trailing" constant="6" id="JAT-xr-qng"/>
<constraint firstAttribute="bottom" secondItem="xmU-kN-zva" secondAttribute="bottom" id="Zen-46-8Ks"/>
<constraint firstItem="xmU-kN-zva" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="ciH-WD-B1a"/>
<constraint firstItem="xmU-kN-zva" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="qbE-Xx-IK9"/>
<constraint firstItem="xmU-kN-zva" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leadingMargin" constant="6" id="qbE-Xx-IK9"/>
</constraints>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<connections>
@ -99,10 +159,15 @@
<outlet property="mainStackView" destination="xmU-kN-zva" id="Hsg-6X-ATq"/>
<outlet property="roomAddressLabel" destination="Yjw-ez-u4W" id="R1L-VC-qHV"/>
<outlet property="roomNameLabel" destination="ekk-PI-fnh" id="prM-OG-suY"/>
<outlet property="roomTopicLabel" destination="Qyh-eC-KBG" id="qN7-ic-y6n"/>
<outlet property="roomTopicTextView" destination="DCx-MH-TSC" id="MB0-cS-wfD"/>
<outlet property="securityContainerView" destination="l54-5L-xAv" id="Duy-QA-wrD"/>
<outlet property="securityInformationLabel" destination="HAS-Tr-iTE" id="GZC-gT-q2z"/>
<outlet property="securityTitleLabel" destination="peB-51-q5w" id="hbl-K6-AbE"/>
<outlet property="shadowView" destination="szu-r5-TIX" id="LDd-uy-FAG"/>
<outlet property="topicContainerView" destination="NSk-JY-5iY" id="YCo-cp-dbU"/>
<outlet property="topicTitleLabel" destination="cTV-D7-Uha" id="nt9-MZ-4t7"/>
</connections>
<point key="canvasLocation" x="243.47826086956525" y="-273.54910714285711"/>
<point key="canvasLocation" x="155.07246376811597" y="-254.12946428571428"/>
</view>
</objects>
</document>

View file

@ -26,4 +26,6 @@ struct RoomInfoBasicViewData {
let mainRoomAlias: String?
let roomTopic: String?
let encryptionImage: UIImage?
let isEncrypted: Bool
let isDirect: Bool
}

View file

@ -2622,7 +2622,7 @@
if (permalink)
{
[[UIPasteboard generalPasteboard] setString:permalink];
MXKPasteboardManager.shared.pasteboard.string = permalink;
}
else
{
@ -5256,7 +5256,7 @@
if (textMessage)
{
[UIPasteboard generalPasteboard].string = textMessage;
MXKPasteboardManager.shared.pasteboard.string = textMessage;
}
else
{

View file

@ -898,7 +898,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti
if (roomdId)
{
[[UIPasteboard generalPasteboard] setString:roomdId];
MXKPasteboardManager.shared.pasteboard.string = roomdId;
}
else
{
@ -1006,7 +1006,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti
if (roomAlias)
{
[[UIPasteboard generalPasteboard] setString:roomAlias];
MXKPasteboardManager.shared.pasteboard.string = roomAlias;
}
else
{
@ -1031,7 +1031,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti
if (permalink)
{
[[UIPasteboard generalPasteboard] setString:permalink];
MXKPasteboardManager.shared.pasteboard.string = permalink;
}
else
{

View file

@ -55,9 +55,9 @@
self.recentsTableView.tag = RecentsDataSourceModeRooms;
// Add the (+) button programmatically
[self addPlusButton];
plusButtonImageView.image = [UIImage imageNamed:@"rooms_floating_action"];
plusButtonImageView = [self vc_addFABWithImage:[UIImage imageNamed:@"rooms_floating_action"]
target:self
action:@selector(onPlusButtonPressed)];
self.enableStickyHeaders = YES;
}

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16096" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="V8j-Lb-PgC">
<device id="retina5_9" orientation="portrait" appearance="light"/>
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
@ -13,14 +13,14 @@
<objects>
<viewController extendedLayoutIncludesOpaqueBars="YES" automaticallyAdjustsScrollViewInsets="NO" id="V8j-Lb-PgC" customClass="EnterPinCodeViewController" customModule="Riot" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="EL9-GA-lwo">
<rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="1YE-D1-eHn">
<rect key="frame" x="0.0" y="64" width="375" height="694"/>
<rect key="frame" x="0.0" y="20" width="375" height="627"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="app_symbol" translatesAutoresizingMaskIntoConstraints="NO" id="8qz-Yk-9a4">
<rect key="frame" x="137.66666666666666" y="277" width="100" height="100"/>
<rect key="frame" x="137.5" y="243.5" width="100" height="100"/>
<constraints>
<constraint firstAttribute="width" constant="100" id="Ux9-pH-SW9"/>
<constraint firstAttribute="height" constant="100" id="o3K-YH-5tn"/>
@ -33,52 +33,34 @@
<constraint firstItem="8qz-Yk-9a4" firstAttribute="centerX" secondItem="1YE-D1-eHn" secondAttribute="centerX" id="cPb-3H-3yK"/>
</constraints>
</view>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="equalSpacing" alignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="DMT-DS-IA8">
<rect key="frame" x="0.0" y="52" width="375" height="718"/>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="equalSpacing" alignment="center" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="DMT-DS-IA8">
<rect key="frame" x="0.0" y="8" width="375" height="651"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ztg-5t-ECh" userLabel="Container">
<rect key="frame" x="20" y="0.0" width="335" height="172.33333333333334"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="app_symbol" translatesAutoresizingMaskIntoConstraints="NO" id="UHg-qE-anw">
<rect key="frame" x="147.66666666666666" y="8" width="40" height="40"/>
<constraints>
<constraint firstAttribute="width" constant="40" id="ERR-Np-6I1"/>
<constraint firstAttribute="height" constant="40" id="zYD-Rk-nOH"/>
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Choose a PIN for security" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bxI-mu-qng">
<rect key="frame" x="0.0" y="57.000000000000007" width="335" height="26.333333333333336"/>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="22"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="PINs help keep your profile, messages and contacts secure, so only you can access them." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Rn2-qe-htS">
<rect key="frame" x="0.0" y="111.33333333333334" width="335" height="61"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" image="app_symbol" translatesAutoresizingMaskIntoConstraints="NO" id="UHg-qE-anw">
<rect key="frame" x="167.5" y="0.0" width="40" height="40"/>
<constraints>
<constraint firstItem="Rn2-qe-htS" firstAttribute="centerX" secondItem="ztg-5t-ECh" secondAttribute="centerX" id="18L-xF-ADZ"/>
<constraint firstItem="Rn2-qe-htS" firstAttribute="top" secondItem="bxI-mu-qng" secondAttribute="bottom" constant="28" id="HtF-cu-6el"/>
<constraint firstItem="bxI-mu-qng" firstAttribute="leading" secondItem="ztg-5t-ECh" secondAttribute="leading" id="IMC-TT-zWD"/>
<constraint firstAttribute="bottom" secondItem="Rn2-qe-htS" secondAttribute="bottom" id="IW3-jM-53d"/>
<constraint firstAttribute="trailing" secondItem="Rn2-qe-htS" secondAttribute="trailing" id="Jda-DD-urk"/>
<constraint firstItem="UHg-qE-anw" firstAttribute="centerX" secondItem="ztg-5t-ECh" secondAttribute="centerX" id="Vhm-GS-xYs"/>
<constraint firstAttribute="trailing" secondItem="bxI-mu-qng" secondAttribute="trailing" id="Vug-jC-5c4"/>
<constraint firstItem="Rn2-qe-htS" firstAttribute="leading" secondItem="ztg-5t-ECh" secondAttribute="leading" id="kWf-33-mfM"/>
<constraint firstItem="bxI-mu-qng" firstAttribute="top" secondItem="UHg-qE-anw" secondAttribute="bottom" constant="9" id="laj-kY-eW1"/>
<constraint firstItem="bxI-mu-qng" firstAttribute="centerX" secondItem="ztg-5t-ECh" secondAttribute="centerX" id="p4o-hz-jZJ"/>
<constraint firstItem="UHg-qE-anw" firstAttribute="top" secondItem="ztg-5t-ECh" secondAttribute="top" constant="8" id="uj5-KC-7FD"/>
<constraint firstAttribute="height" constant="40" id="5If-kl-LuA"/>
<constraint firstAttribute="width" constant="40" id="EK6-ed-26b"/>
</constraints>
</view>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="equalSpacing" alignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="l5x-qO-sdf">
<rect key="frame" x="2" y="211" width="371" height="78.666666666666686"/>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" text="Welcome back.Choose a PIN for security" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bxI-mu-qng">
<rect key="frame" x="16" y="59" width="343" height="53"/>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="22"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Rn2-qe-htS">
<rect key="frame" x="16" y="131.5" width="343" height="54"/>
<string key="text">Setting up a PIN lets you protect data like messages and contacts, so only you can access them by entering the PIN at the start of the app.</string>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="l5x-qO-sdf">
<rect key="frame" x="2" y="204.5" width="371" height="79"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" alignment="center" spacing="24" translatesAutoresizingMaskIntoConstraints="NO" id="xi9-P9-8WP">
<rect key="frame" x="101.66666666666669" y="0.0" width="168" height="24"/>
<rect key="frame" x="101.5" y="0.0" width="168" height="24"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="selection_untick" translatesAutoresizingMaskIntoConstraints="NO" id="Gwx-8X-ZWk">
<rect key="frame" x="0.0" y="0.0" width="24" height="24"/>
@ -88,14 +70,14 @@
</constraints>
</imageView>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" tag="1" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="selection_untick" translatesAutoresizingMaskIntoConstraints="NO" id="qDY-R1-l5l">
<rect key="frame" x="47.999999999999986" y="0.0" width="24" height="24"/>
<rect key="frame" x="48" y="0.0" width="24" height="24"/>
<constraints>
<constraint firstAttribute="width" constant="24" id="QDg-LP-R4J"/>
<constraint firstAttribute="height" constant="24" id="f4G-d8-hoA"/>
</constraints>
</imageView>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" tag="2" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="selection_untick" translatesAutoresizingMaskIntoConstraints="NO" id="X0l-q3-fXm">
<rect key="frame" x="95.999999999999986" y="0.0" width="24" height="24"/>
<rect key="frame" x="96" y="0.0" width="24" height="24"/>
<constraints>
<constraint firstAttribute="width" constant="24" id="HQA-9R-8bC"/>
<constraint firstAttribute="height" constant="24" id="Zjd-RW-DiW"/>
@ -111,7 +93,7 @@
</subviews>
</stackView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="CBc-7Z-a5Z">
<rect key="frame" x="0.0" y="23.999999999999996" width="371" height="54.666666666666657"/>
<rect key="frame" x="0.0" y="24" width="371" height="55"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Q0w-RD-JD3">
<rect key="frame" x="0.0" y="8" width="371" height="2"/>
@ -121,7 +103,7 @@
</constraints>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="For security reasons, this PIN isn't available. Please try another PIN" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="H5g-FI-xEj">
<rect key="frame" x="8" y="18" width="355" height="28.666666666666671"/>
<rect key="frame" x="8" y="18" width="355" height="29"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<color key="textColor" systemColor="systemRedColor" red="1" green="0.23137254900000001" blue="0.18823529410000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -141,11 +123,11 @@
</view>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" alignment="center" spacing="21" translatesAutoresizingMaskIntoConstraints="NO" id="W0M-eq-abZ">
<rect key="frame" x="65.666666666666686" y="328.33333333333331" width="244" height="302.99999999999994"/>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" alignment="center" spacing="12" translatesAutoresizingMaskIntoConstraints="NO" id="W0M-eq-abZ">
<rect key="frame" x="77.5" y="302.5" width="220" height="276"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" alignment="center" spacing="32" translatesAutoresizingMaskIntoConstraints="NO" id="Uqh-o2-7HP">
<rect key="frame" x="0.0" y="0.0" width="244" height="60"/>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" alignment="center" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="Uqh-o2-7HP">
<rect key="frame" x="0.0" y="0.0" width="220" height="60"/>
<subviews>
<button opaque="NO" tag="1" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="BEe-II-qt8">
<rect key="frame" x="0.0" y="0.0" width="60" height="60"/>
@ -160,7 +142,7 @@
</connections>
</button>
<button opaque="NO" tag="2" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="vRL-nn-bIH">
<rect key="frame" x="91.999999999999986" y="0.0" width="60.000000000000014" height="60"/>
<rect key="frame" x="80" y="0.0" width="60" height="60"/>
<constraints>
<constraint firstAttribute="height" constant="60" id="HaJ-0E-bl3"/>
<constraint firstAttribute="width" constant="60" id="JJz-zL-t77"/>
@ -172,7 +154,7 @@
</connections>
</button>
<button opaque="NO" tag="3" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="m5E-4b-a2B">
<rect key="frame" x="184" y="0.0" width="60" height="60"/>
<rect key="frame" x="160" y="0.0" width="60" height="60"/>
<constraints>
<constraint firstAttribute="height" constant="60" id="9Uy-xG-5Vq"/>
<constraint firstAttribute="width" constant="60" id="EZw-k5-DP8"/>
@ -185,8 +167,8 @@
</button>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" alignment="center" spacing="32" translatesAutoresizingMaskIntoConstraints="NO" id="Z9D-6N-neq">
<rect key="frame" x="0.0" y="81" width="244" height="60"/>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" alignment="center" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="Z9D-6N-neq">
<rect key="frame" x="0.0" y="72" width="220" height="60"/>
<subviews>
<button opaque="NO" tag="4" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Q2U-ek-vSc">
<rect key="frame" x="0.0" y="0.0" width="60" height="60"/>
@ -201,7 +183,7 @@
</connections>
</button>
<button opaque="NO" tag="5" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ziv-SY-nXQ">
<rect key="frame" x="91.999999999999986" y="0.0" width="60.000000000000014" height="60"/>
<rect key="frame" x="80" y="0.0" width="60" height="60"/>
<constraints>
<constraint firstAttribute="width" constant="60" id="5Ry-eq-V0D"/>
<constraint firstAttribute="height" constant="60" id="iCm-G8-2Us"/>
@ -213,7 +195,7 @@
</connections>
</button>
<button opaque="NO" tag="6" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="PNU-iI-oCX">
<rect key="frame" x="184" y="0.0" width="60" height="60"/>
<rect key="frame" x="160" y="0.0" width="60" height="60"/>
<constraints>
<constraint firstAttribute="width" constant="60" id="odD-FC-4eB"/>
<constraint firstAttribute="height" constant="60" id="zHt-bd-Jwg"/>
@ -226,8 +208,8 @@
</button>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" alignment="center" spacing="32" translatesAutoresizingMaskIntoConstraints="NO" id="YeU-UN-Uo0">
<rect key="frame" x="0.0" y="162.00000000000006" width="244" height="60"/>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" alignment="center" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="YeU-UN-Uo0">
<rect key="frame" x="0.0" y="144" width="220" height="60"/>
<subviews>
<button opaque="NO" tag="7" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Lnz-5u-oFb">
<rect key="frame" x="0.0" y="0.0" width="60" height="60"/>
@ -242,7 +224,7 @@
</connections>
</button>
<button opaque="NO" tag="8" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="OCE-R0-CMN">
<rect key="frame" x="91.999999999999986" y="0.0" width="60.000000000000014" height="60"/>
<rect key="frame" x="80" y="0.0" width="60" height="60"/>
<constraints>
<constraint firstAttribute="width" constant="60" id="5LE-yh-yoi"/>
<constraint firstAttribute="height" constant="60" id="65e-mr-hid"/>
@ -254,7 +236,7 @@
</connections>
</button>
<button opaque="NO" tag="9" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="1dz-Qd-zCl">
<rect key="frame" x="184" y="0.0" width="60" height="60"/>
<rect key="frame" x="160" y="0.0" width="60" height="60"/>
<constraints>
<constraint firstAttribute="width" constant="60" id="rS1-XX-Xw9"/>
<constraint firstAttribute="height" constant="60" id="zza-iD-Oue"/>
@ -267,8 +249,8 @@
</button>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" alignment="center" spacing="32" translatesAutoresizingMaskIntoConstraints="NO" id="Nrp-tS-u1k">
<rect key="frame" x="0.0" y="243.00000000000006" width="244" height="60"/>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" alignment="center" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="Nrp-tS-u1k">
<rect key="frame" x="0.0" y="216" width="220" height="60"/>
<subviews>
<button opaque="NO" userInteractionEnabled="NO" tag="-99" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="DEv-rc-fGB">
<rect key="frame" x="0.0" y="0.0" width="60" height="60"/>
@ -279,7 +261,7 @@
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="28"/>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="sc1-u3-yvh">
<rect key="frame" x="91.999999999999986" y="0.0" width="60.000000000000014" height="60"/>
<rect key="frame" x="80" y="0.0" width="60" height="60"/>
<constraints>
<constraint firstAttribute="height" constant="60" id="DDy-yf-FOR"/>
<constraint firstAttribute="width" constant="60" id="vSL-tm-biX"/>
@ -291,7 +273,7 @@
</connections>
</button>
<button opaque="NO" tag="-1" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="LpO-9j-dlN">
<rect key="frame" x="184" y="0.0" width="60" height="60"/>
<rect key="frame" x="160" y="0.0" width="60" height="60"/>
<constraints>
<constraint firstAttribute="width" constant="60" id="DAY-CR-kKO"/>
<constraint firstAttribute="height" constant="60" id="iDt-BW-fEz"/>
@ -306,31 +288,27 @@
</stackView>
</subviews>
</stackView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="nCW-ER-9SF" userLabel="Container">
<rect key="frame" x="67.666666666666686" y="670" width="240" height="48"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CRt-Fb-0Dq">
<rect key="frame" x="0.0" y="0.0" width="240" height="48"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<state key="normal" title="Forgot PIN"/>
<connections>
<action selector="forgotPinButtonAction:" destination="V8j-Lb-PgC" eventType="touchUpInside" id="hE4-CJ-Bdh"/>
</connections>
</button>
</subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CRt-Fb-0Dq">
<rect key="frame" x="146.5" y="598" width="82" height="33"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<state key="normal" title="Forgot PIN"/>
<connections>
<action selector="forgotPinButtonAction:" destination="V8j-Lb-PgC" eventType="touchUpInside" id="hE4-CJ-Bdh"/>
</connections>
</button>
<view userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="N9V-f7-d5k">
<rect key="frame" x="67.5" y="650" width="240" height="1"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="CRt-Fb-0Dq" firstAttribute="top" secondItem="nCW-ER-9SF" secondAttribute="top" id="QVD-G0-uHm"/>
<constraint firstAttribute="bottom" secondItem="CRt-Fb-0Dq" secondAttribute="bottom" id="gJw-QQ-7PO"/>
<constraint firstAttribute="trailing" secondItem="CRt-Fb-0Dq" secondAttribute="trailing" id="gnV-kg-BCW"/>
<constraint firstAttribute="height" constant="48" id="whx-HV-FXN"/>
<constraint firstItem="CRt-Fb-0Dq" firstAttribute="leading" secondItem="nCW-ER-9SF" secondAttribute="leading" id="wxI-iX-ugm"/>
<constraint firstAttribute="height" constant="1" id="oFX-h1-fx7"/>
</constraints>
</view>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="ztg-5t-ECh" secondAttribute="trailing" constant="20" id="ADS-wF-wRi"/>
<constraint firstItem="ztg-5t-ECh" firstAttribute="leading" secondItem="DMT-DS-IA8" secondAttribute="leading" constant="20" id="YU9-Am-aht"/>
<constraint firstAttribute="trailing" secondItem="Rn2-qe-htS" secondAttribute="trailing" constant="16" id="WIb-QJ-vx7"/>
<constraint firstItem="bxI-mu-qng" firstAttribute="leading" secondItem="DMT-DS-IA8" secondAttribute="leading" constant="16" id="cg2-vW-LtI"/>
<constraint firstAttribute="trailing" secondItem="bxI-mu-qng" secondAttribute="trailing" constant="16" id="j5H-f5-nqY"/>
<constraint firstItem="Rn2-qe-htS" firstAttribute="leading" secondItem="DMT-DS-IA8" secondAttribute="leading" constant="16" id="y20-NI-Hl0"/>
</constraints>
</stackView>
</subviews>
@ -348,6 +326,7 @@
<viewLayoutGuide key="safeArea" id="bFg-jh-JZB"/>
</view>
<connections>
<outlet property="bottomView" destination="N9V-f7-d5k" id="H5X-Px-d4w"/>
<outlet property="digitsStackView" destination="W0M-eq-abZ" id="xnb-6w-dtC"/>
<outlet property="explanatoryLabel" destination="Rn2-qe-htS" id="8WG-b4-nhE"/>
<outlet property="forgotPinButton" destination="CRt-Fb-0Dq" id="kHp-wn-P0o"/>
@ -364,7 +343,7 @@
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="zK0-v6-7Wt" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-3199.1999999999998" y="-648.02955665024638"/>
<point key="canvasLocation" x="-3199.1999999999998" y="-648.12593703148434"/>
</scene>
</scenes>
<resources>

View file

@ -42,6 +42,7 @@ final class EnterPinCodeViewController: UIViewController {
@IBOutlet private weak var informationLabel: UILabel!
@IBOutlet private weak var explanatoryLabel: UILabel!
@IBOutlet private weak var forgotPinButton: UIButton!
@IBOutlet private weak var bottomView: UIView!
// MARK: Private
@ -160,6 +161,11 @@ final class EnterPinCodeViewController: UIViewController {
}
private func setupViews() {
let cancelBarButtonItem = MXKBarButtonItem(title: VectorL10n.cancel, style: .plain) { [weak self] in
self?.cancelButtonAction()
}
self.navigationItem.rightBarButtonItem = cancelBarButtonItem
showCancelButton()
self.title = ""
@ -177,15 +183,11 @@ final class EnterPinCodeViewController: UIViewController {
}
private func showCancelButton() {
let cancelBarButtonItem = MXKBarButtonItem(title: VectorL10n.cancel, style: .plain) { [weak self] in
self?.cancelButtonAction()
}
self.navigationItem.rightBarButtonItem = cancelBarButtonItem
self.navigationController?.navigationBar.isHidden = false
}
private func hideCancelButton() {
self.navigationItem.rightBarButtonItem = nil
self.navigationController?.navigationBar.isHidden = true
}
private func render(viewState: EnterPinCodeViewState) {
@ -224,6 +226,7 @@ final class EnterPinCodeViewController: UIViewController {
self.informationLabel.text = VectorL10n.pinProtectionChoosePin
self.explanatoryLabel.isHidden = false
self.forgotPinButton.isHidden = true
self.bottomView.isHidden = false
self.notAllowedPinView.isHidden = true
}
@ -242,6 +245,7 @@ final class EnterPinCodeViewController: UIViewController {
self.mainStackView.isHidden = false
self.logoImageView.isHidden = true
self.forgotPinButton.isHidden = true
self.bottomView.isHidden = false
self.notAllowedPinView.isHidden = false
renderPlaceholdersCount(.max, error: true)
@ -273,8 +277,9 @@ final class EnterPinCodeViewController: UIViewController {
self.mainStackView.isHidden = false
self.logoImageView.isHidden = false
self.informationLabel.text = VectorL10n.pinProtectionEnterPin
self.explanatoryLabel.text = nil
self.explanatoryLabel.isHidden = true
self.forgotPinButton.isHidden = false
self.bottomView.isHidden = true
self.notAllowedPinView.isHidden = true
}
@ -282,7 +287,7 @@ final class EnterPinCodeViewController: UIViewController {
self.inactiveView.isHidden = true
self.mainStackView.isHidden = false
self.notAllowedPinView.isHidden = true
self.explanatoryLabel.text = nil
self.explanatoryLabel.isHidden = true
self.placeholderStackView.vc_shake()
}
@ -317,8 +322,9 @@ final class EnterPinCodeViewController: UIViewController {
self.mainStackView.isHidden = false
self.logoImageView.isHidden = true
self.informationLabel.text = VectorL10n.pinProtectionConfirmPinToDisable
self.explanatoryLabel.text = nil
self.explanatoryLabel.isHidden = true
self.forgotPinButton.isHidden = true
self.bottomView.isHidden = false
self.notAllowedPinView.isHidden = true
}
@ -327,7 +333,7 @@ final class EnterPinCodeViewController: UIViewController {
self.inactiveView.isHidden = false
self.mainStackView.isHidden = true
self.notAllowedPinView.isHidden = true
self.explanatoryLabel.text = nil
self.explanatoryLabel.isHidden = true
}
private func renderPlaceholdersCount(_ count: Int, error: Bool = false) {

View file

@ -114,6 +114,8 @@ enum {
}];
[self userInterfaceThemeDidChange];
[self registerDeviceChangesNotification];
}
- (void)userInterfaceThemeDidChange
@ -247,6 +249,29 @@ enum {
}
#pragma mark - Data update
- (void)registerDeviceChangesNotification
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(onDeviceInfoTrustLevelDidChangeNotification:)
name:MXDeviceInfoTrustLevelDidChangeNotification
object:nil];
}
- (void)onDeviceInfoTrustLevelDidChangeNotification:(NSNotification*)notification
{
MXDeviceInfo *deviceInfo = notification.object;
NSString *deviceId = deviceInfo.deviceId;
if ([deviceId isEqualToString:device.deviceId])
{
[self reloadDeviceWithCompletion:^{
}];
}
}
#pragma mark - Segues
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender

View file

@ -204,9 +204,11 @@ TableViewSectionsDelegate>
}];
[self userInterfaceThemeDidChange];
[self registerUserDevicesChangesNotification];
self.tableViewSections = [TableViewSections new];
self.tableViewSections.delegate = self;
[self updateSections];
}
@ -559,6 +561,57 @@ TableViewSectionsDelegate>
}
#pragma mark - Data update
- (void)registerUserDevicesChangesNotification
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(onDeviceInfoTrustLevelDidChangeNotification:)
name:MXDeviceInfoTrustLevelDidChangeNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(crossSigningInfoTrustLevelDidChangeNotification:)
name:MXCrossSigningInfoTrustLevelDidChangeNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(onDidUpdateUsersDevicesNotification:)
name:MXDeviceListDidUpdateUsersDevicesNotification
object:nil];
}
- (void)onDidUpdateUsersDevicesNotification:(NSNotification*)notification
{
NSDictionary *usersDevices = notification.userInfo;
if ([usersDevices.allKeys containsObject:self.mainSession.myUserId])
{
[self loadDevices];
}
}
- (void)onDeviceInfoTrustLevelDidChangeNotification:(NSNotification*)notification
{
MXDeviceInfo *deviceInfo = notification.object;
NSString *userId = deviceInfo.userId;
if ([userId isEqualToString:self.mainSession.myUserId])
{
[self loadDevices];
}
}
- (void)crossSigningInfoTrustLevelDidChangeNotification:(NSNotification*)notification
{
MXCrossSigningInfo *crossSigningInfo = notification.object;
NSString *userId = crossSigningInfo.userId;
if ([userId isEqualToString:self.mainSession.myUserId])
{
[self loadDevices];
}
}
#pragma mark - Cross-signing
- (void)loadCrossSigning

View file

@ -154,13 +154,24 @@ class NotificationService: UNNotificationServiceExtension {
}
}
func fetchEvent(withEventId eventId: String, roomId: String) {
func fetchEvent(withEventId eventId: String, roomId: String, allowSync: Bool = true) {
guard let mxSession = NotificationService.mxSession else {
// there is something wrong, do not change the content
NSLog("[NotificationService] fetchEvent: Either originalContent or mxSession is missing.")
fallbackToBestAttemptContent(forEventId: eventId)
return
}
/// Inline function to handle decryption failure
func handleDecryptionFailure() {
if allowSync {
NSLog("[NotificationService] fetchEvent: Launch a background sync.")
self.launchBackgroundSync(forEventId: eventId, roomId: roomId)
} else {
NSLog("[NotificationService] fetchEvent: Do not sync anymore.")
self.fallbackToBestAttemptContent(forEventId: eventId)
}
}
/// Inline function to handle encryption for event, either from cache or from the backend
/// - Parameter event: The event to be handled
@ -181,14 +192,22 @@ class NotificationService: UNNotificationServiceExtension {
}
// should decrypt it first
if mxSession.decryptEvent(event, inTimeline: nil) {
// decryption succeeded
NSLog("[NotificationService] fetchEvent: Event decrypted successfully.")
self.processEvent(event)
if mxSession.crypto.hasKeys(toDecryptEvent: event) {
// we have keys to decrypt the event
NSLog("[NotificationService] fetchEvent: Event needs to be decrpyted, and we have the keys to decrypt it.")
if mxSession.decryptEvent(event, inTimeline: nil) {
// decryption succeeded
NSLog("[NotificationService] fetchEvent: Event decrypted successfully.")
self.processEvent(event)
} else {
// decryption failed
NSLog("[NotificationService] fetchEvent: Decryption failed even crypto claimed it has the keys.")
handleDecryptionFailure()
}
} else {
// decryption failed
NSLog("[NotificationService] fetchEvent: Event needs to be decrpyted, but we don't have the keys to decrypt it. Launching a background sync.")
self.launchBackgroundSync(forEventId: eventId, roomId: roomId)
// we don't have keys to decrypt the event
NSLog("[NotificationService] fetchEvent: Event needs to be decrpyted, but we don't have the keys to decrypt it.")
handleDecryptionFailure()
}
}
@ -241,7 +260,8 @@ class NotificationService: UNNotificationServiceExtension {
NSLog("[NotificationService] launchBackgroundSync: MXSession.initialBackgroundSync returned too late successfully")
return
}
self.fetchEvent(withEventId: eventId, roomId: roomId)
// do not allow to sync anymore
self.fetchEvent(withEventId: eventId, roomId: roomId, allowSync: false)
break
case .failure(let error):
guard let self = self else {