diff --git a/.idea/dictionaries/bmarty.xml b/.idea/dictionaries/bmarty.xml
index 4585842153..8299f1c4de 100644
--- a/.idea/dictionaries/bmarty.xml
+++ b/.idea/dictionaries/bmarty.xml
@@ -37,6 +37,7 @@
threepid
unpublish
unwedging
+ vctr
\ No newline at end of file
diff --git a/CHANGES.md b/CHANGES.md
index 1849bde397..4dd4fd0cfd 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -44,6 +44,9 @@ Other changes:
- Add documentation on LoginWizard and RegistrationWizard (#3303)
- Setup towncrier tool (#3293)
+ Security:
+ - Element Android shares name of E2EE files with homeserver (#3387)
+
Changes in Element 1.1.7 (2021-05-12)
===================================================
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 4b61777d3f..7e1758077b 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -26,7 +26,7 @@ To install the template (to be done only once):
To create a new screen:
- First create a new package in your code.
-- Then right click on the package, and select `New/New Vector/RiotX Feature`.
+- Then right click on the package, and select `New/New Vector/Element Feature`.
- Follow the Wizard, especially replace `Main` by something more relevant to your feature.
- Click on `Finish`.
- Remaining steps are described as TODO in the generated files, or will be pointed out by the compiler, or at runtime :)
diff --git a/attachment-viewer/build.gradle b/attachment-viewer/build.gradle
index 0f3817d983..c9814171d9 100644
--- a/attachment-viewer/build.gradle
+++ b/attachment-viewer/build.gradle
@@ -55,7 +55,7 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.5.0'
implementation 'androidx.appcompat:appcompat:1.3.0'
- implementation "androidx.recyclerview:recyclerview:1.2.0"
+ implementation "androidx.recyclerview:recyclerview:1.2.1"
implementation 'com.google.android.material:material:1.3.0'
}
\ No newline at end of file
diff --git a/docs/color_migration_guide.md b/docs/color_migration_guide.md
new file mode 100644
index 0000000000..31a531d124
--- /dev/null
+++ b/docs/color_migration_guide.md
@@ -0,0 +1,85 @@
+# Color migration
+
+### Changes
+
+- use colors defined in https://www.figma.com/file/X4XTH9iS2KGJ2wFKDqkyed/Compound?node-id=557%3A0
+- remove unused resources and code (ex: PercentView)
+- split some resource files into smaller file
+- rework the theme files
+- ensure material theme is used everywhere in the theme and in the layout
+- add default style for some views in the theme (ex: Toolbar, etc.)
+- add some debug screen in the debug menu, to test the themes and the button style
+- rework the button style to use `materialThemeOverlay` attribute
+- custom tint icon for menu management has been removed
+- comment with `riotx` has been updated
+
+### Main change for developers
+
+- Read migration guide: https://github.com/vector-im/element-android/pull/3459/files#diff-f0e52729d5e4f6eccbcf72246807aa34ed19c4ef5625ca669df998cd1022874b
+- Use MaterialAlertDialogBuilder instead of AlertDialog.Builder
+- some Epoxy Item included a divider. This has been removed. Use a `dividerItem` or `bottomSheetDividerItem` Epoxy items to add a divider
+- RecyclerView.configureWith now take a divider drawable instead of a divider color
+
+### Remaining work
+
+- Cleanup some vector drawables and ensure a tint is always used instead of hard coded color.
+
+### Migration guide
+
+Some colors and color attribute has been removed, here is the list and what has to be used now.
+
+It can help Element Android forks maintainers to migrate their code.
+
+- riotx_text_primary -> ?vctr_content_primary
+- riotx_text_secondary -> ?vctr_content_secondary
+- riotx_text_tertiary -> ?vctr_content_tertiary
+
+- ?riotx_background -> ?android:colorBackground
+- riotx_background_light -> element_background_light
+- riotx_background_dark -> element_background_dark
+- riotx_background_black -> element_background_black
+
+- riotx_accent -> ?colorPrimary
+- riotx_positive_accent -> ?colorPrimary
+- riotx_accent_alpha25 -> color_primary_alpha25
+- riotx_notice -> ?colorError
+- riotx_destructive_accent -> ?colorError
+- vector_error_color -> ?colorError
+- vector_warning_color -> ?colorError
+
+- riotx_bottom_sheet_background -> ?colorSurface
+- riotx_alerter_background -> ?colorSurface
+
+- riotx_username_1 -> element_name_01
+- riotx_username_2 -> element_name_02
+- riotx_username_3 -> element_name_03
+- riotx_username_4 -> element_name_04
+- riotx_username_5 -> element_name_05
+- riotx_username_6 -> element_name_06
+- riotx_username_7 -> element_name_07
+- riotx_username_8 -> element_name_08
+
+- riotx_avatar_fill_1 -> element_room_01
+- riotx_avatar_fill_2 -> element_room_02
+- riotx_avatar_fill_3 -> element_room_03
+
+- white -> @android:color/white
+- black -> @android:color/black or emoji_color
+
+- riotx_list_header_background_color -> ?vctr_header_background
+- riotx_header_panel_background -> ?vctr_header_background
+- riotx_list_bottom_sheet_divider_color -> ?vctr_list_separator_on_surface
+- riotx_list_divider_color -> ?vctr_list_separator
+- list_divider_color -> ?vctr_list_separator
+- riotx_header_panel_border_mobile -> ?vctr_list_separator
+- riotx_bottom_nav_background_border_color -> ?vctr_list_separator
+- riotx_header_panel_text_secondary -> ?vctr_content_primary
+
+- link_color_light -> element_link_light
+- link_color_dark -> element_link_dark
+
+- riotx_toolbar_primary_text_color -> vctr_content_primary
+- riotx_toolbar_secondary_text_color -> vctr_content_primary
+- riot_primary_text_color -> vctr_content_primary
+
+- riotx_android_secondary -> vctr_content_secondary
diff --git a/fastlane/metadata/android/cs/full_description.txt b/fastlane/metadata/android/cs/full_description.txt
index f9c1f2ad0c..d169c077e1 100644
--- a/fastlane/metadata/android/cs/full_description.txt
+++ b/fastlane/metadata/android/cs/full_description.txt
@@ -1,30 +1,39 @@
-Element je nový typ aplikace pro výměnu zpráv a spolupráci, která:
+Element je zabezpečený komunikátor a zároveň aplikace pro týmovou spolupráci, která je ideální pro skupinové chaty při práci na dálku. Tato chatovací aplikace využívá end-to-end šifrování a poskytuje výkonné videokonference, sdílení souborů a hlasové hovory.
-1. Vám dá kontrolu nad ochranou vašeho soukromí
-2. Umožní vám komunikovat s kýmkoli v síti Matrix a dokonce i mimo ni pomocí integrací s aplikacemi, jako je Slack
-3. Ochrání vás před inzercí, dataminingem a uzavřenými zahradami
-4. Zabezpečí vás end-to-end šifrováním s křížovým podpisem pro ověření ostatních
+Mezi funkce aplikace Element patří:
+- Pokročilé nástroje pro online komunikaci
+- Plně šifrované zprávy umožňující bezpečnější firemní komunikaci i pro pracovníky na dálku
+- Decentralizovaný chat založený na open source frameworku Matrix
+- Bezpečné sdílení souborů se šifrovanými daty při správě projektů
+- Videochaty s funkcí Voice over IP a sdílením obrazovky
+- Snadná integrace s oblíbenými nástroji pro online spolupráci, nástroji pro správu projektů, službami VoIP a dalšími aplikacemi pro týmovou komunikaci
-Element je zcela odlišný od ostatních aplikací pro zasílání zpráv a spolupráci, protože je decentralizovaný a otevřený.
+Element se zcela liší od ostatních aplikací pro zasílání zpráv a spolupráci. Funguje na platformě Matrix, otevřené síti pro bezpečné zasílání zpráv a decentralizovanou komunikaci. Umožňuje vlastní hostování, aby uživatelé měli maximální vlastnictví a kontrolu nad svými daty a zprávami.
-Element vám umožňuje použít vlastní domovský server - nebo si vybrat hostitele - abyste měli soukromí, vlastnictví a kontrolu nad svými daty a konverzacemi. Poskytuje vám přístup k otevřené síti; takže nejste zaseknuti jen při konverzaci s ostatními uživateli Elementu. A je velmi bezpečný.
+Soukromí a šifrované zprávy
+Element vás chrání před nežádoucími reklamami, vytěžováním dat a tzv. walled gardens. Zabezpečuje také všechna vaše data, video a hlasovou komunikaci jeden na jednoho prostřednictvím šifrování end-to-end a křížového ověřování zařízení.
-Element je toho všeho schopen, protože pracuje na Matrixu - standardu otevřené, decentralizované komunikace.
+Element vám dává kontrolu nad vaším soukromím a zároveň vám umožňuje bezpečně komunikovat s kýmkoli v síti Matrix nebo s dalšími nástroji pro firemní spolupráci díky integraci s aplikacemi, jako je Slack.
-Element vám dává kontrolu nad tím, že si můžete vybrat, kdo bude hostovat vaše konverzace. Z aplikace Element si můžete vybrat hostování různými způsoby:
+Element lze hostovat samostatně
+Abyste měli větší kontrolu nad svými citlivými daty a konverzacemi, může být Element hostován na vlastním hardwaru nebo si můžete vybrat libovolného hostitele založeného na systému Matrix - standardu pro decentralizovanou komunikaci s otevřeným zdrojovým kódem. Element vám poskytuje soukromí, soulad se zásadami bezpečnosti a flexibilitu integrace.
-1. Získejte zdarma účet na veřejném serveru matrix.org hostovaném vývojáři Matrixu, nebo si vyberte z tisíců veřejných serverů hostovaných dobrovolníky
-2. Hostujte svůj účet spuštěním serveru na svém vlastním hardwaru
-3. Zaregistrujte si účet na vlastním serveru jednoduchým přihlášením k hostitelské platformě Element Matrix Services
+Vlastněte svá data
+Sami rozhodujete, kde budou vaše data a zprávy uloženy. Bez rizika vytěžování dat nebo přístupu třetích stran.
-Proč zvolit Element?
+Element vám dává kontrolu různými způsoby:
+1. Získejte bezplatný účet na veřejném serveru matrix.org, který hostují vývojáři Matrixu, nebo si vyberte z tisíců veřejných serverů hostovaných dobrovolníky.
+2. Vlastní hostování účtu spuštěním serveru na vlastní IT infrastruktuře.
+3. Zaregistrujte si účet na vlastním serveru tak, že si jednoduše předplatíte hostingovou platformu Element Matrix Services.
-VLASTNĚTE SVÁ DATA : Vy rozhodnete, kde svá data a zprávy ponecháte. Vlastníte je a jsou pod vaší kontrolou, ne nějaký MEGACORP, který těží vaše data nebo poskytuje přístup třetím stranám.
+Otevřené zasílání zpráv a spolupráce
+Můžete chatovat s kýmkoli v síti Matrix, ať už používá aplikaci Element, jinou aplikaci podporující protokol Matrix nebo dokonce i když používá jinou aplikaci pro zasílání zpráv.
-ZPRÁVY A SPOLUPRÁCE : Můžete chatovat s kýmkoli v síti Matrix, ať už používá Element nebo jinou aplikaci, a to i v případě, že používají jiný systém zasílání zpráv, jako je Slack, IRC nebo XMPP.
+Superbezpečné
+Skutečné end-to-end šifrování (zprávy mohou dešifrovat pouze účastníci konverzace) a křížové ověřování zařízení.
-MAXIMÁLNĚ BEZPEČNÉ : Skutečné šifrování typu end-to-end (pouze ti v konverzaci mohou dešifrovat zprávy) a křížové podepisování k ověření zařízení účastníků konverzace.
+Kompletní komunikace a integrace
+Zprávy, hlasové a videohovory, sdílení souborů, sdílení obrazovky a celá řada integrací, botů a widgetů. Vytvářejte místnosti, komunity, zůstaňte v kontaktu a spolupracujte.
-KOMPLETNÍ KOMUNIKACE : Zprávy, hlasové hovory a videohovory, sdílení souborů, sdílení obrazovky a celá řada integrací, robotů a widgetů. Budujte místnosti, komunity, zůstaňte v kontaktu a spolupracujte.
-
-KDEKOLIV JSTE : Zůstaňte v kontaktu, ať jste kdekoli, s plně synchronizovanou historií zpráv na všech vašich zařízeních a na webu na adrese https://app.element.io.
+Navažte tam, kde jste skončili
+Zůstaňte v kontaktu, ať jste kdekoli, díky plně synchronizované historii zpráv ve všech zařízeních a na webu https://app.element.io
diff --git a/fastlane/metadata/android/de/changelogs/40101070.txt b/fastlane/metadata/android/de/changelogs/40101070.txt
new file mode 100644
index 0000000000..757475a44d
--- /dev/null
+++ b/fastlane/metadata/android/de/changelogs/40101070.txt
@@ -0,0 +1,2 @@
+Hauptänderungen in dieser Version: Mit Spaces kannst du deine Räume gruppieren (Beta). Videos können vor dem Senden komprimiert werden.
+Die vollständige Änderungsliste gibt es hier: https://github.com/vector-im/element-android/releases/tag/v1.1.7
diff --git a/fastlane/metadata/android/de/full_description.txt b/fastlane/metadata/android/de/full_description.txt
index 1334adf554..30eb153ee9 100644
--- a/fastlane/metadata/android/de/full_description.txt
+++ b/fastlane/metadata/android/de/full_description.txt
@@ -1,9 +1,9 @@
-Element ist einerseits ein sicherer Messenger, andererseits ideal geeignet für die produktive Zusammenarbeit mit dem Team im Homeoffice. Mit eingebauter Ende-zu-Ende-Verschlüsselung ermöglicht Element umfangreiche und sichere Videokonferenzen, das Teilen von Dateien sowie Sprachanrufe.
+Element ist ein sicherer Messenger und ideal für die produktive Zusammenarbeit mit Ihrem Team im Homeoffice. Mit eingebauter Ende-zu-Ende-Verschlüsselung ermöglicht Element auch umfangreiche und sichere Videokonferenzen, das Teilen von Dateien, Sprachanrufe und vieles mehr.
Element bietet folgende Funktionen:
- Fortschrittliche Werkzeuge für die Online-Kommunikation
- Vollständig verschlüsselte Nachrichten, um eine sichere Kommunikation innerhalb und außerhalb von Unternehmen zu ermöglichen
-- Dezentralisierte Chats, basierend auf dem quelloffenen Matrix-Framework
+- Dezentralisierte Chats, basierend auf dem quelloffenen Matrix-Protokoll
- Sichere und kontrollierte Dateifreigabe durch verschlüsselte Daten beim Verwalten von Projekten
- Videochats mit VoIP und Bildschirmübertragung
- Einfache Einbindung in Ihre bevorzugten Online-Kollaborations- und Projektverwaltungswerkzeuge, VoIP-Dienste und andere Kommunikationsapps für Ihr Team
@@ -11,29 +11,29 @@ Element ist einerseits ein sicherer Messenger, andererseits ideal geeignet für
Element unterscheidet sich grundlegend von anderen Kommunikations- und Kollaborationsapps. Es läuft auf Matrix, einem offenen Netzwerk für sichere und dezentralisierte Kommunikation. Es erlaubt Nutzern ihre eigene Infrastruktur zu betreiben und gibt ihnen damit vollständige Kontrolle und Besitz über ihre eigenen Daten und Nachrichten.
Privatsphäre/Datenschutz und verschlüsselte Kommunikation
-Element schützt Sie vor unerwünschter Werbung, dem Datenschürfen und abgeschlossenen Plattformen. Auch schützt es all Ihre Daten, Ihre Video- und Sprachkommunikation unter vier Augen, durch Ende-zu-Ende-Verschlüsselung und durch das Quersignieren von Geräten zur Verifizierung.
+Element schützt Sie vor unerwünschter Werbung, dem Datensammeln und geschlossenen Plattformen. Auch schützt es all Ihre Daten, Ihre Video- und Sprachkommunikation mittels Ende-zu-Ende-Verschlüsselung und durch das Quersignieren von Geräten zur Verifizierung.
-Element gibt Ihnen die Kontrolle über Ihre Privatsphäre und ermöglicht es Ihnen zugleich, mit jedem im Matrix-Netzwerk sicher zu kommunizieren - oder auch auf anderen geschäftlichen Kollaborationswerkzeugen, zum Beispiel durch das Einbinden von Apps wie Slack.
+Element gibt Ihnen volle Kontrolle über Ihre Privatsphäre und ermöglicht es Ihnen zugleich, mit jedem im Matrix-Netzwerk sicher zu kommunizieren - oder auch auf anderen geschäftlichen Kollaborationswerkzeugen, zum Beispiel durch das Einbinden von Apps wie Slack.
Element kann man selber betreiben
Um mehr Kontrolle über Ihre sensiblen Daten und Konversationen zu ermöglichen, kann man Element selbst betreiben, oder Sie wählen irgendeinen Matrix-basierten Dienst - der Standard für quelloffene, dezentralisierte Kommunikation. Element gibt Ihnen Privatsphäre, Sicherheitskonformität und Flexibilität für Integrationen.
Besitzen Sie Ihre Daten
-Sie entscheiden, wo Sie Ihre Daten und Nachrichten aufbewahren - ohne das Datenschürfen oder den Zugriff Dritter zu riskieren.
+Sie entscheiden, wo Sie Ihre Daten und Nachrichten aufbewahren - ohne das Datensammeln oder den Zugriff Dritter zu riskieren.
-Element gibt Ihnen auf verschiedene Arten die Kontrolle:
-1. Kostenlos auf dem öffentlichen matrix.org-Server registrieren, der von den Matrix-Entwicklern gehostet wird, oder wählen Sie aus Tausenden von öffentlichen Servern, die von Freiwilligen betrieben werden
-2. Ein Konto auf einem eigenen Server in der eigenen IT-Infrastruktur betreiben
-3. Einen Konto auf einem maßgeschneiderten Server erstellen, zum Beispiel durch ein Abonnement der Element Matrix Services (kurz EMS)
+Element gibt Ihnen auf verschiedene Arten Kontrolle:
+1. Sie können sich kostenlos auf dem öffentlichen matrix.org-Server registrieren, der von den Matrix-Entwicklern gehostet wird, oder einen von Tausenden öffentlichen Servern, die von Freiwilligen betrieben werden, auswählen
+2. Sie haben die Möglichkeit, ein Konto auf einem eigenen Server in der eigenen IT-Infrastruktur betreiben
+3. Außerdem können Sie durch ein Abonnement der Element Matrix Services ein Konto auf einem für Sie maßgeschneiderten Server erstellen
Offene Kommunikation und Zusammenarbeit
Sie können mit jedem im Matrix-Netzwerk chatten, egal ob ihr Kontakt Element, eine andere Matrix-App oder sogar eine völlig andere Anwendung nutzt.
Super sicher
-Echte Ende-zu-Ende-Verschlüsselung (nur die Personen in der Unterhaltung können die Nachrichten entschüsseln), sowie die Quersignierung von Geräten zur Verifizierung.
+Durch Ende-zu-Ende-Verschlüsselung können nur die Personen, die in der Unterhaltung sind, die Nachrichten lesen. Außerdem stellt die Verifizierung mittels Quersignierung sicher, dass Sie wirklich mit dem Chatten, mit dem Sie glauben - und niemand Anderem.
Vollständige Kommunikation und Integration
-Kurznachrichten, Sprach- und Videoanrufe, Dateifreigaben, Bildschirmübertragungen und eine ganze Reihe an Integrationen, Bots and Widgets. Schaffen Sie Räume, Communities, bleiben Sie auf dem Laufenden und erledigen Sie Sachen.
+Kurznachrichten, Sprach- und Videoanrufe, Dateifreigaben, Bildschirmübertragungen und einer Menge an Integrationen, Bots und Widgets. Schaffen Sie Räume und Communities, bleiben Sie auf dem Laufenden und erledigen Sie Sachen.
Da Weitermachen, wo Sie aufgehört haben
Bleiben Sie in Kontakt, egal wo Sie sind, mit vollständig synchronisiertem Nachrichtenverlauf quer über all Ihre Geräte und im Netz auf https://app.element.io
diff --git a/fastlane/metadata/android/et/changelogs/40101070.txt b/fastlane/metadata/android/et/changelogs/40101070.txt
new file mode 100644
index 0000000000..8ef65a7396
--- /dev/null
+++ b/fastlane/metadata/android/et/changelogs/40101070.txt
@@ -0,0 +1,2 @@
+Põhilised muudatused selles versioonis: beeta-versioon kogukonnakeskustest ja videofailide pakkimine enne üleslaadimist.
+Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases/tag/v1.1.7
diff --git a/fastlane/metadata/android/hu/changelogs/40100130.txt b/fastlane/metadata/android/hu/changelogs/40100130.txt
index e1b044f4e5..47ce2690f4 100644
--- a/fastlane/metadata/android/hu/changelogs/40100130.txt
+++ b/fastlane/metadata/android/hu/changelogs/40100130.txt
@@ -1,2 +1,2 @@
Főbb változtatások ebben a verzióban: URL előnézet, új emoji billentyűzet, új szoba beállitási lehetőségek, és hó karácsonyra!
-Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.0.12
+Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.0.13
diff --git a/fastlane/metadata/android/hu/changelogs/40100140.txt b/fastlane/metadata/android/hu/changelogs/40100140.txt
new file mode 100644
index 0000000000..1b86da9ab1
--- /dev/null
+++ b/fastlane/metadata/android/hu/changelogs/40100140.txt
@@ -0,0 +1,2 @@
+Fő változás ebben a verzióban: Szoba jogosultságok szerkesztése, automatikus sötét/világos téma és sok hibajavítás.
+Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.0.14
diff --git a/fastlane/metadata/android/hu/changelogs/40100150.txt b/fastlane/metadata/android/hu/changelogs/40100150.txt
new file mode 100644
index 0000000000..b48fd6a0d7
--- /dev/null
+++ b/fastlane/metadata/android/hu/changelogs/40100150.txt
@@ -0,0 +1,2 @@
+Fő változás ebben a verzióban: Közösségi hálózatos bejelentkezés támogatása
+Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.0.15
diff --git a/fastlane/metadata/android/hu/changelogs/40100160.txt b/fastlane/metadata/android/hu/changelogs/40100160.txt
new file mode 100644
index 0000000000..bb983ed5e8
--- /dev/null
+++ b/fastlane/metadata/android/hu/changelogs/40100160.txt
@@ -0,0 +1,2 @@
+Fő változás ebben a verzióban: Közösségi hálózatos bejelentkezés
+Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.0.15 and https://github.com/vector-im/element-android/releases/tag/v1.0.16
diff --git a/fastlane/metadata/android/hu/changelogs/40100170.txt b/fastlane/metadata/android/hu/changelogs/40100170.txt
new file mode 100644
index 0000000000..806470d74e
--- /dev/null
+++ b/fastlane/metadata/android/hu/changelogs/40100170.txt
@@ -0,0 +1,2 @@
+Fő változás ebben a verzióban: Hibajavítás!
+Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.0.17
diff --git a/fastlane/metadata/android/hu/changelogs/40101000.txt b/fastlane/metadata/android/hu/changelogs/40101000.txt
new file mode 100644
index 0000000000..0bc4f5d49f
--- /dev/null
+++ b/fastlane/metadata/android/hu/changelogs/40101000.txt
@@ -0,0 +1,2 @@
+Fő változás ebben a verzióban: VoIP (hang és videóhívás közvetlen beszélgetésekben) fejlesztés és hibajavítás
+Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.1.0
diff --git a/fastlane/metadata/android/hu/changelogs/40101010.txt b/fastlane/metadata/android/hu/changelogs/40101010.txt
new file mode 100644
index 0000000000..503fc0ab2f
--- /dev/null
+++ b/fastlane/metadata/android/hu/changelogs/40101010.txt
@@ -0,0 +1,2 @@
+Fő változás ebben a verzióban: sebesség javítás és hibajavítás
+Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.1.1
diff --git a/fastlane/metadata/android/hu/changelogs/40101020.txt b/fastlane/metadata/android/hu/changelogs/40101020.txt
new file mode 100644
index 0000000000..04d67ac5ae
--- /dev/null
+++ b/fastlane/metadata/android/hu/changelogs/40101020.txt
@@ -0,0 +1,2 @@
+Fő változás ebben a verzióban: sebesség javítás és hibajavítás
+Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.1.2
diff --git a/fastlane/metadata/android/hu/changelogs/40101030.txt b/fastlane/metadata/android/hu/changelogs/40101030.txt
new file mode 100644
index 0000000000..4d0e46739e
--- /dev/null
+++ b/fastlane/metadata/android/hu/changelogs/40101030.txt
@@ -0,0 +1,2 @@
+Fő változás ebben a verzióban: sebesség javítás és hibajavítás
+Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.1.3
diff --git a/fastlane/metadata/android/hu/changelogs/40101040.txt b/fastlane/metadata/android/hu/changelogs/40101040.txt
new file mode 100644
index 0000000000..1c6921f0d5
--- /dev/null
+++ b/fastlane/metadata/android/hu/changelogs/40101040.txt
@@ -0,0 +1,2 @@
+Fő változás ebben a verzióban: sebesség javítás és hibajavítás
+Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.1.4
diff --git a/fastlane/metadata/android/hu/changelogs/40101050.txt b/fastlane/metadata/android/hu/changelogs/40101050.txt
new file mode 100644
index 0000000000..c937bb9215
--- /dev/null
+++ b/fastlane/metadata/android/hu/changelogs/40101050.txt
@@ -0,0 +1,2 @@
+Fő változás ebben a verzióban: javítás az 1.1.4 verzióhoz
+Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.1.5
diff --git a/fastlane/metadata/android/hu/changelogs/40101060.txt b/fastlane/metadata/android/hu/changelogs/40101060.txt
new file mode 100644
index 0000000000..a9b37e66a9
--- /dev/null
+++ b/fastlane/metadata/android/hu/changelogs/40101060.txt
@@ -0,0 +1,2 @@
+Fő változás ebben a verzióban: javítás az 1.1.5 verzióhoz
+Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.1.6
diff --git a/fastlane/metadata/android/hu/changelogs/40101070.txt b/fastlane/metadata/android/hu/changelogs/40101070.txt
new file mode 100644
index 0000000000..4acfbea1ea
--- /dev/null
+++ b/fastlane/metadata/android/hu/changelogs/40101070.txt
@@ -0,0 +1,2 @@
+Fő változás ebben a verzióban: béta állapotú Tér támogatás. Videó tömörítés küldés előtt.
+Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.1.7
diff --git a/fastlane/metadata/android/hu/full_description.txt b/fastlane/metadata/android/hu/full_description.txt
index b75f259d02..032346ccb8 100644
--- a/fastlane/metadata/android/hu/full_description.txt
+++ b/fastlane/metadata/android/hu/full_description.txt
@@ -1,30 +1,40 @@
-Az Element egy új üzenetküldő, és csapatmunka alkalmazás, amivel
+Element egy biztonságos üzenetküldő és csapatmunka támogató alkalmazás ami ideális távoli munkavégzés közben csoportos csevegéshez. Az alkalmazás végpontok közötti titkosítást használ videó konferenciához, fájl megosztáshoz és videó hivásokhoz.
-1. A te kezedben van az irányítás a saját adataid fölött, hogy megőrizhesd a magánszférádat
-2. Akárkivel beszélgethetsz a Matrix hálózatban, sőt még azon kívül is, például olyan alkalmazások integrálásával, mint a Slack
-3. Megvédheted magad a hirdetésektől, adatbányászattól, és a nagy cégek megoldásaiba való bezártságtól
-4. Biztonságosan beszélgethetsz, a végpontok közötti titkosításnak köszönhetően, az eszközök megbízhatóságát az eszköz-közti hitelesítéssel garantálva
+Element tulajdonságai:
+- Fejlett online kommunikációs eszköz
+- Teljesen titkosított üzenetküldés biztonságos céges kommunikációt kínál még a távdolgozóknak is
+- Elosztott csevegés a Matrix nyílt forráskódú keretrendszer felhasználásával
+- Bizontságos fájl megosztás titkosítottan projektek kezeléséhez
+- Videó hívás VoIP-pal és képernyőmegosztással
+- Könnyen integrálható a kedvenc online kollaborációs eszközöddel, projekt menedzsment eszközzel, VoIP szolgáltatással vagy más csoport üzenetküldő alkalmazással
-Az Element teljesen más, mint a többi üzenetküldő és csapatmunka alkalmazás, mert nyílt forráskódú, és decentralizált (nem központilag irányított).
+Element teljesen más mint a többi üzenetküldő alkalmazás. Matrixot használ, egy nyílt hálózatot a decentralizált biztonságos kommunikációhoz. Lehetőséget ad saját szerver üzemeltetésére ami maximális tulajdont és kontrollt biztosít az adatok fölött.
-Az Element lehetővé teszi, hogy saját szervert futtass - vagy válassz egy szolgáltatót - így te birtoklod az adataidat, ezáltal megőrizve a magánszférád és a biztonságod. Egy nyitott hálózathoz ad hozzáférést, így nem csak a többi Element felhasználóval tudsz beszélgetni, hanem másokkal is. Ráadásul nagyon biztonságos.
+Magánélet védelme és titkosított üzenetküldés
+Element megóv a kéretlen hirdetésektől, adatbányászattól és a különböző szigetszerű megoldásoktól. Minden adatot biztonságba helyez, egy az egybe videó és hang kommunikáció végpontok között titkosítva ahol az eszközök hitelesítve vannak.
-Az Element-tel azért válik mindez lehetővé, mert a Matrix hálózatra épül - egy nyílt, decentralizált kommunikációs szabványra.
+Element a kezedbe adja az adatvédelmi irányítást miközben bárkivel kommunikálhatsz a Matrix hálózatban vagy más üzleti kollaborációs eszközzel ami integrálva van, mint amilyen a Slack.
-Az Element a te kezedbe adja az irányítást azáltal, hogy eldöntheted, ki tárolja a beszélgetéseidet. Az Element alkalmazásból több féle szolgáltatót is választhatsz:
+Element futtatható saját szerveren
-1. Regisztrálhatsz ingyen egy fiókot a matrix.org nyilvános szerveren, amit a Matrix fejlesztői üzemeltetnek, vagy választhatsz a több ezer, ingyenes szerver közül, amit önkéntesek üzemeltetnek
-2. A saját számítógépeden is futtathatsz szervert
-3. Előfizethetsz egy saját szerverre az Element Matrix Szolgáltatások platformon
+Azért, hogy az érzékeny adatok és beszélgetések minnél inkább az irányításod alatt lehessen az Elementet saját magadnak üzemeltetheted vagy választhatsz bármely Matrixon alapuló - szabványos nyílt forráskódú és decentralizált kommunikáció - szoláltató közül. Element adatvédelmet, biztonságot és rugalmas integrációkat biztosít.
-Miért jó az Element-et választani?
+A te adatod a tiéd
+Te döntöd el, hogy hol tárolod az adataidat és üzeneteidet. Adatbányászat vagy harmadik fél hozzáférésének kockázata nélkül.
-ADATAID MEGVÉDÉSE : Eldöntheted, hol tárold az adataid és üzeneteid. A te tulajdonodban van, nem valami megacégnél, ami bányássza az adataid, vagy továbbadja másoknak.
+Element többféle képpen adja vissza az irányítást:
+1. Szerezz egy ingyenes hozzáférést a matrix.org nyilvános szerverre amit a Matrix fejlesztők üzemeltetnek vagy válassz a több ezer önkéntesek által üzemeltetett nyilvános szerverből
+2. Üzemeltess szerver magadnak a saját infrastruktúrádon
+3. Iratkozz fel egy egyedi szerverre az Element Matrix Services platformon
-NYÍLT BESZÉLGETÉS, ÉS CSAPATMUNKA : Akárkivel cseveghetsz a Matrix hálózatban, akár az Element-et használják, akár valamilyen másik Matrix alkalmazást, de még akkor is, ha egy másik csevegő hálózatot használnak, olyat, mint például a Slack, IRC, vagy az XMPP.
+Nyílt üzenetküldés és kollaboráció
+Bárkivel beszélgethetsz a Matrix hálózaton, akár az Elementet használja akár egy másik Matrix alkalmazást használ vagy akár egy eltérő üzenetküldőt.
-SZUPER-BIZTONSÁGOS : Valódi, végpontok közötti titkosítás (csak a beszélgetés résztvevői tudják elolvasni az üzeneteket), és eszköz-közti hitelesítés, hogy ellenőrizhesd a résztvevők eszközeit.
+Fantasztikusan biztonságos
+Igazi végpontok között titkosítás (csak a beszélgetésben résztvevők tudják visszafejteni) és hitelesítés eszközök közötti aláírásokkal.
-TELJES KOMMUNIKÁCIÓ : Üzenetküldés, hang- és videóhívások, fájlmegosztás, képernyőmegosztás, és egy rakás integráció, bot, és widget. Hozz létre szobákat, közösségeket, maradj elérhető, és végezzétek el a feladatokat.
+Teljes kommunikáció és integráció
+Üzenetküldés, hang és videóhívás, fájl megosztás, képernyő megosztás és egy csomó integráció, botok és kisalkalmazások. Építs szobákat, közösségeket, maradj kapcsolatban és végezz el dolgokat.
-AKÁRHOL, AHOL CSAK SZÜKSÉG VAN RÁ : Akárhol is vagy, maradj elérhető, a teljes mértékben szinkronizált beszélgetésekkel az összes eszközödön, és a weben a https://app.element.io oldalon.
+Vedd fel a fonalat
+Maradj kapcsolatban bárhol minden eszközödön a szinkronizált üzenetekkel és a weben a https://app.element.io oldallal
diff --git a/fastlane/metadata/android/hu/short_description.txt b/fastlane/metadata/android/hu/short_description.txt
index 89f7c13f54..2dfe14c516 100644
--- a/fastlane/metadata/android/hu/short_description.txt
+++ b/fastlane/metadata/android/hu/short_description.txt
@@ -1 +1 @@
-Biztonságos, decentralizált chat és VoIP. Tartsd az adataid biztonságban.
+Csoportos üzenetküldő - titkosított üzenetek, videó hívások
diff --git a/fastlane/metadata/android/hu/title.txt b/fastlane/metadata/android/hu/title.txt
index 8e493d2d08..c463dea393 100644
--- a/fastlane/metadata/android/hu/title.txt
+++ b/fastlane/metadata/android/hu/title.txt
@@ -1 +1 @@
-Element (régebben Riot.im)
+Element - Biztonságos üzenetküldő
diff --git a/fastlane/metadata/android/it/changelogs/40101070.txt b/fastlane/metadata/android/it/changelogs/40101070.txt
new file mode 100644
index 0000000000..6f7ffcd958
--- /dev/null
+++ b/fastlane/metadata/android/it/changelogs/40101070.txt
@@ -0,0 +1,2 @@
+Modifiche principali in questa versione: supporto beta per gli Spazi. Compressione video prima dell'invio.
+Cronologia completa: https://github.com/vector-im/element-android/releases/tag/v1.1.7
diff --git a/fastlane/metadata/android/sv/changelogs/40101070.txt b/fastlane/metadata/android/sv/changelogs/40101070.txt
new file mode 100644
index 0000000000..4756a2d028
--- /dev/null
+++ b/fastlane/metadata/android/sv/changelogs/40101070.txt
@@ -0,0 +1,2 @@
+Huvudsakliga ändringar i den här versionen: betastöd för utrymmen. Komprimera video innan den skickas.
+Full ändringslogg: https://github.com/vector-im/element-android/releases/tag/v1.1.7
diff --git a/fastlane/metadata/android/uk/changelogs/40101070.txt b/fastlane/metadata/android/uk/changelogs/40101070.txt
new file mode 100644
index 0000000000..4d60bb1704
--- /dev/null
+++ b/fastlane/metadata/android/uk/changelogs/40101070.txt
@@ -0,0 +1,2 @@
+Основні зміни в цій версії: бета-підтримка Spaces. Стиснення відео перед надсиланням.
+Повний журнал змін: https://github.com/vector-im/element-android/releases/tag/v1.1.7
diff --git a/fastlane/metadata/android/uk/full_description.txt b/fastlane/metadata/android/uk/full_description.txt
index 026ae4162a..df06315754 100644
--- a/fastlane/metadata/android/uk/full_description.txt
+++ b/fastlane/metadata/android/uk/full_description.txt
@@ -1,30 +1,39 @@
-Element — це застосунок для спілкування та співпраці нового типу, який:
+Element — це і безпечний месенджер, і застосунок для співпраці команди, який ідеально підходить для групових бесід під час віддаленої роботи. Цей застосунок для спілкування застосовує наскрізне шифрування для забезпечення відеоконференцій, обміну файлами та голосових викликів.
-1. Надає вам повний контроль за своєю конфіденційністю
-2. Дозволяє спілкування з будь-ким у мережі Matrix та поза нею, інтегруючись із такими застосунками, як Slack
-3. Убезпечує вас від реклами, збору даних та штучних обмежень
-4. Захищає ваше спілкування наскрізним шифруванням із перехресним підписуванням для звірення інших осіб
+Можливості Element включають:
+- Розширені засоби спілкування в Інтернеті
+- Повністю зашифровані повідомлення для надання можливості безпечнішого корпоративного спілкування, навіть для віддалених працівників
+- Децентралізований чат на основі відкритого коду Matrix
+- Безпечний обмін файлами із зашифрованими даними для керування проєктами
+- Відеочати з передачею голосу через IP та показом екрану іншим
+- Проста інтеграція з вашими улюбленими інструментами для онлайн-співпраці, інструментами керування проєктами, послугами VoIP та іншими застосунками обміну повідомленнями для команд
-Element ґрунтовно відрізняється від інших застосунків для спілкування та співпраці тому що він є децентралізованим та відкритоджерельним.
+Element цілковито відрізняється від інших застосунків обміну повідомленнями та спільної роботи. Він працює на Matrix, відкритій мережі для безпечного обміну повідомленнями та децентралізованого зв'язку. Це дозволяє самостійне розгортання, щоб надати користувачам якнайбільше володіння та контролю над їх даними та повідомленнями.
-Element дозволяє вам розміщувати сервер в себе або обирати будь-якого з надавачів послуг, таким чином забезпечуючи вам конфіденційність і можливість володіти власними даними й бесідами та контролювати їх. Він надає вам доступ до відкритої мережі, тож ви не є обмеженими спілкуванням виключно з користувачами Element. І він є дуже надійним та безпечним.
+Приватність та обмін зашифрованими повідомленнями
+Element захищає вас від небажаної реклами, збору даних та обмежень. Він також захищає всі ваші дані, відео та голосовий зв'язок віч-на-віч за допомогою наскрізного шифрування та взаємного підписування пристроїв.
-Element здатен забезпечити усе це завдяки тому, що він заснований на протоколі Matrix — стандарті для відкритого та децентралізованого спілкування.
+Element дає вам можливість контролювати вашу приватність, одночасно дозволяючи вам безпечно спілкуватися з будь-ким у мережі Matrix або через інші інструменти ділової співпраці, інтегрувавшись із такими програмами, як Slack.
-Element надає вам повний контроль, дозволяючи обирати з-поміж надавачів послуг, що обслуговують сервери з вашими бесідами. Ви вільні обрати будь-який спосіб розміщення прямо з застосунку Element:
+Element можна розгортати самостійно
+Щоб забезпечити більше контролю над вашими приватними даними та розмовами, Element можна самостійно розміщувати або ви можете вибрати будь-який вузол на основі Matrix — стандарт для децентралізованого спілкування з відкритим кодом. Element надає вам приватність, відповідність безпеці та гнучкість інтеграції.
-1. Отримати безкоштовний обліковий запис на загальнодоступному сервері matrix.org, який обслуговують розробники Matrix, чи на одному з тисяч публічних серверів, які обслуговують волонтери
-2. Розмістити свій обліковий запис на власному сервері
-3. Зареєструватись на індивідуальному сервері, просто підписавшись на послуги платформи Element Matrix Services
+Ваші дані
+Ви вирішуєте, де зберігати свої дані та повідомлення. Без ризику видобутку даних або стороннього доступу.
-Чому я маю обрати Element?
+Element надає такі можливості на вибір:
+1. Отримайте безплатний обліковий запис на загальнодоступному сервері matrix.org, розміщеному розробниками Matrix, або виберіть серед тисяч загальнодоступних серверів, розміщених волонтерами
+2. Самостійно розмістіть свій обліковий запис, запустивши сервер на власній ІТ-інфраструктурі
+3. Зареєструйте обліковий запис на власному сервері, просто підписавшись на хостинг-платформу Element Matrix Services
-ВОЛОДІЙТЕ ВАШИМИ ДАНИМИ : Ви вирішуєте де тримати ваші дані та повідомлення. Саме ви володієте ними та контролюєте їх, а не якась Мегакорпорація, що збирає ваші дані та надає стороннім особам доступ до них.
+Відкриті обмін повідомленнями та співпраця
+Ви можете спілкуватися з усіма у мережі Matrix, незалежно від того, чи користуються вони Element, іншим застосунком Matrix або навіть якщо іншим застосунком для обміну повідомленнями.
-ВІДКРИТІ ОБМІН ПОВІДОМЛЕННЯМИ ТА СПІВПРАЦЯ : Ви можете балакати з будь-ким у мережі Matrix, хоч вони користуються Element, хоч іншим застосунком для Matrix, і навіть якщо вони користуються іншою системою обміну повідомленнями на кшталт Slack, IRC чи XMPP.
+Надбезпечний
+Справжнє наскрізне шифрування (лише учасники бесіди можуть розшифровувати повідомлення) та взаємне підписування пристроїв.
-НАДБЕЗПЕЧНІСТЬ : Справжнє наскрізне шифрування (лише ваші співрозмовники здатні дешифровувати повідомлення) та перехресне підписування для звірення пристроїв інших учасників бесіди.
+Повноцінні спілкування та інтеграція
+Обмін повідомленнями, голосові та відеовиклики, обмін файлами, спільний доступ до екрана та ціла купа інтеграцій, ботів та віджетів. Створюйте кімнати, спільноти, залишайтеся на зв’язку та виконуйте завдання.
-ДОВЕРШЕНИЙ ЗВʼЯЗОК : Повідомлення, голосові та відеодзвінки, обмін файлами, розподіл екрану та ціла купа інтеграцій, ботів та знадобів. Створюйте кімнати й спільноти, залишайтесь на зв'язку та завершуйте свої справи.
-
-ДЕ Б ВИ НЕ БУЛИ : Залишайтесь на зв'язку де б ви не були, разом з синхронізовною історією листувань на усіх ваших пристроях та в Інтернеті на https://app.element.io.
+Продовжуйте, де зупинилися
+Залишайтеся на зв'язку, де б ви не знаходились, з повністю синхронізованою історією повідомлень на всіх своїх пристроях та в Інтернеті за адресою https://app.element.io
diff --git a/fastlane/metadata/android/zh-Hans/changelogs/40101020.txt b/fastlane/metadata/android/zh-Hans/changelogs/40101020.txt
new file mode 100644
index 0000000000..0de3f2aed0
--- /dev/null
+++ b/fastlane/metadata/android/zh-Hans/changelogs/40101020.txt
@@ -0,0 +1,2 @@
+此版本中的主要更新:改进性能和错误修复!
+完整的更新记录:https://github.com/vector-im/element-android/releases/tag/v1.1.2
diff --git a/fastlane/metadata/android/zh-Hans/changelogs/40101030.txt b/fastlane/metadata/android/zh-Hans/changelogs/40101030.txt
new file mode 100644
index 0000000000..5a7fae92d5
--- /dev/null
+++ b/fastlane/metadata/android/zh-Hans/changelogs/40101030.txt
@@ -0,0 +1,2 @@
+此版本中的主要更新:改进性能和修复错误!
+完整的更新记录:https://github.com/vector-im/element-android/releases/tag/v1.1.3
diff --git a/fastlane/metadata/android/zh-Hans/changelogs/40101040.txt b/fastlane/metadata/android/zh-Hans/changelogs/40101040.txt
new file mode 100644
index 0000000000..44a3547b3e
--- /dev/null
+++ b/fastlane/metadata/android/zh-Hans/changelogs/40101040.txt
@@ -0,0 +1,2 @@
+此版本中的主要更新:改进性能和修复错误!
+完整的更新记录:https://github.com/vector-im/element-android/releases/tag/v1.1.4
diff --git a/fastlane/metadata/android/zh-Hans/changelogs/40101050.txt b/fastlane/metadata/android/zh-Hans/changelogs/40101050.txt
new file mode 100644
index 0000000000..c320815a00
--- /dev/null
+++ b/fastlane/metadata/android/zh-Hans/changelogs/40101050.txt
@@ -0,0 +1,2 @@
+此版本中的主要更新:1.1.4 的热修复
+完整的更新记录:https://github.com/vector-im/element-android/releases/tag/v1.1.5
diff --git a/fastlane/metadata/android/zh-Hans/changelogs/40101060.txt b/fastlane/metadata/android/zh-Hans/changelogs/40101060.txt
new file mode 100644
index 0000000000..193ef8f48e
--- /dev/null
+++ b/fastlane/metadata/android/zh-Hans/changelogs/40101060.txt
@@ -0,0 +1,2 @@
+此版本中的主要更新:1.1.5 的热修复
+完整的更新记录:https://github.com/vector-im/element-android/releases/tag/v1.1.6
diff --git a/fastlane/metadata/android/zh-Hans/changelogs/40101070.txt b/fastlane/metadata/android/zh-Hans/changelogs/40101070.txt
new file mode 100644
index 0000000000..ba8e92be9b
--- /dev/null
+++ b/fastlane/metadata/android/zh-Hans/changelogs/40101070.txt
@@ -0,0 +1,2 @@
+此版本中的主要更新:对「空间」的测试版支持。发送前压缩视频。
+完整的更新记录:https://github.com/vector-im/element-android/releases/tag/v1.1.7
diff --git a/fastlane/metadata/android/zh-Hans/full_description.txt b/fastlane/metadata/android/zh-Hans/full_description.txt
index 4791c9652b..fa6b00f1e4 100644
--- a/fastlane/metadata/android/zh-Hans/full_description.txt
+++ b/fastlane/metadata/android/zh-Hans/full_description.txt
@@ -1,30 +1,39 @@
-Element 是一种新型的通讯与协作应用:
+Element 不仅是安全的通讯软件,同时也是生产力团队协作应用,非常适合在远端工作时进行群组聊天。此聊天应用使用了端到端加密来提供强大的视频会议、文件分享与语音通话功能。
-1. 使您可以掌控您的隐私
-2. 使您与 Matrix 网络中的任何人交流,甚至可以通过集成功能与如 Slack 之类的其他应用通讯
-3. 保护您免受广告,大数据挖掘和封闭服务的侵害
-4. 通过端到端加密保证安全,通过交叉签名验证其他人
+Element 的功能包含了:
+- 进阶的线上通讯工具
+- 完全加密的信息,即使对于远端工作者来说,也可以有更安全的公司通讯
+- 以 Matrix 开放源码框架为基础的去中心化的聊天
+- 在管理项目时通过加密资料安全地分享文件
+- 包含了 VoIP 与画面分享的视频聊天
+- 与你最喜欢的协作工具、项目管理工具、VoIP 服务与其他团队信息应用轻松整合
-Element 与其他通讯与协作应用完全不同,因为它是去中心化且开源的。
+Element 与其他信息传递与协作应用完全不同。它在 Matrix(一个用于安全传递讯息与去中心化通讯的开放网络)上运行。其可以自建,让使用者对他们的资料和信息拥有最大的所有权与控制权。
-Element 允许您自托管——或者选择托管商——因此,您能拥有数据和会话的隐私权,所有权和控制权。它允许您访问开放网络;因此,您可以与 Element 用户以外的人交流。并且它非常安全。
+隐私与加密信息传递
+Element 保护你不受不想要的广告、信息泄露与围城侵扰。其也通过端到端加密与交叉签章装置验证保护了你所有的资料,并提供一对一视频以及语音通讯。
-Element 之所以可以做到这些,是因为它在 Matrix 上运行——开放,去中心化通讯的标准。
+Element 通过与其他商业协作工具,如 Slack 等应用整合,让你可以在控制你的隐私的同时,也可以与 Matrix 网络上的任何人安全地通讯。
-通过让您选择由谁来托管您的会话,Element 让您掌控一切。在 Element 应用中,您可以选择不同的托管方式:
+Element 可以自建
+为了可以完整控制你的敏感资料与对话,Element 可以自建,你也可以选择任何以 Matrix 为基础的服务提供商,开放源码、去中心化的通讯标准。Element 为你提供隐私、安全合规与整合灵活性。
-1. 在由 Matrix 开发者托管的 matrix.org 公共服务器上获取免费帐户,或从志愿者托管的上千个公共服务器中选择
-2. 在您自己的硬件上运行服务器,自托管您的会话
-3. 通过订阅 Element Matrix Services 托管平台,简单地在自定义服务器上注册账户
+拥有你的资料
+你可以决定将你的资料与信息储存在何处。没有信息泄露或被第三方爬取的风险。
-为什么选择 Element?
+Element 透过不同的方式让你掌控一切:
+1. 在 Matrix 开发者架设的 matrix.org 公开服务器上取得免费帐号,或是从数千个由志愿者架设的公开服务器中选择
+2. 在你自己的 IT 基础架构上的服务器自行托管你的帐号
+3. 只要订阅 Element Matrix Services 托管平台就可以在自定义的服务器上注册帐号
-掌控您的数据 :您来决定存放您的数据和消息的位置。拥有并控制它的是您,而不是挖掘您的数据或与第三方分享的巨型企业。
+开放信息传递与协作
+你可以与 Matrix 网络上的任何人聊天,不论他们是使用 Element、其他 Matrix 应用或其他通讯应用。
-开放通讯与协作 :您可以与 Matrix 网络中的任何人聊天,不论他们使用 Element 还是其他 Matrix 应用,甚至/即使他们在使用不同的通讯系统,例如 Slack,IRC 或 XMPP。
+超级安全
+真正的端到端加密(仅有那些在对话中的可以解密讯息)以及交叉签章装置验证。
-超级安全 :支持真正的端到端加密(仅有会话中的人可以解密消息),还有能够验证会话参与方的设备的交叉签名。
+完整的通讯与整合
+信息传递、语音与视频通话、文件分享、画面分享与超多的整合、机器人与挂件。建构聊天室、社群、保持联络并完成工作。
-完善的通讯方式 :消息,语音和视频通话,文件共享,屏幕共享和大量集成功能,机器人和小挂件。建立房间与社区,保持联系并完成工作。
-
-随时随地 :消息历史可在您的全部设备和 https://app.element.io 网页端之间完全同步,无论您在哪里,都可以保持联系。
+从上次离开的地方开始
+无论你身在何处,都可以透过在你所有设备与网页 https://app.element.io 间完全同步的信息历史保持联络
diff --git a/fastlane/metadata/android/zh-Hant/changelogs/40101070.txt b/fastlane/metadata/android/zh-Hant/changelogs/40101070.txt
new file mode 100644
index 0000000000..c62c7d5224
--- /dev/null
+++ b/fastlane/metadata/android/zh-Hant/changelogs/40101070.txt
@@ -0,0 +1,2 @@
+此版本中的主要變動:對「空間」的測試版支援。傳送前壓縮影片。
+完整的變更紀錄:https://github.com/vector-im/element-android/releases/tag/v1.1.7
diff --git a/matrix-sdk-android-rx/src/main/java/org/matrix/android/sdk/rx/RxSession.kt b/matrix-sdk-android-rx/src/main/java/org/matrix/android/sdk/rx/RxSession.kt
index 252359193d..58fb760ff5 100644
--- a/matrix-sdk-android-rx/src/main/java/org/matrix/android/sdk/rx/RxSession.kt
+++ b/matrix-sdk-android-rx/src/main/java/org/matrix/android/sdk/rx/RxSession.kt
@@ -24,7 +24,7 @@ import kotlinx.coroutines.rx2.rxSingle
import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.query.QueryStringValue
import org.matrix.android.sdk.api.session.Session
-import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent
+import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME
import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME
import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo
@@ -35,6 +35,7 @@ import org.matrix.android.sdk.api.session.group.model.GroupSummary
import org.matrix.android.sdk.api.session.identity.ThreePid
import org.matrix.android.sdk.api.session.pushers.Pusher
import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
+import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataEvent
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
import org.matrix.android.sdk.api.session.room.model.RoomSummary
@@ -177,10 +178,17 @@ class RxSession(private val session: Session) {
}
}
- fun liveUserAccountData(types: Set): Observable> {
- return session.userAccountDataService().getLiveAccountDataEvents(types).asObservable()
+ fun liveUserAccountData(types: Set): Observable> {
+ return session.accountDataService().getLiveUserAccountDataEvents(types).asObservable()
.startWithCallable {
- session.userAccountDataService().getAccountDataEvents(types)
+ session.accountDataService().getUserAccountDataEvents(types)
+ }
+ }
+
+ fun liveRoomAccountData(types: Set): Observable> {
+ return session.accountDataService().getLiveRoomAccountDataEvents(types).asObservable()
+ .startWithCallable {
+ session.accountDataService().getRoomAccountDataEvents(types)
}
}
@@ -201,7 +209,7 @@ class RxSession(private val session: Session) {
}
fun liveSecretSynchronisationInfo(): Observable {
- return Observable.combineLatest, Optional, Optional, SecretsSynchronisationInfo>(
+ return Observable.combineLatest, Optional, Optional, SecretsSynchronisationInfo>(
liveUserAccountData(setOf(MASTER_KEY_SSSS_NAME, USER_SIGNING_KEY_SSSS_NAME, SELF_SIGNING_KEY_SSSS_NAME, KEYBACKUP_SECRET_SSSS_NAME)),
liveCrossSigningInfo(session.myUserId),
liveCrossSigningPrivateKeys(),
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt
index 25c22bca57..d14de30c90 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt
@@ -33,7 +33,7 @@ import org.matrix.android.sdk.common.TestConstants
import org.matrix.android.sdk.internal.crypto.SSSS_ALGORITHM_AES_HMAC_SHA2
import org.matrix.android.sdk.internal.crypto.crosssigning.toBase64NoPadding
import org.matrix.android.sdk.internal.crypto.secrets.DefaultSharedSecretStorageService
-import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent
+import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
@@ -73,12 +73,12 @@ class QuadSTests : InstrumentedTest {
// Assert Account data is updated
val accountDataLock = CountDownLatch(1)
- var accountData: AccountDataEvent? = null
+ var accountData: UserAccountDataEvent? = null
val liveAccountData = runBlocking(Dispatchers.Main) {
- aliceSession.userAccountDataService().getLiveAccountDataEvent("${DefaultSharedSecretStorageService.KEY_ID_BASE}.$TEST_KEY_ID")
+ aliceSession.accountDataService().getLiveUserAccountDataEvent("${DefaultSharedSecretStorageService.KEY_ID_BASE}.$TEST_KEY_ID")
}
- val accountDataObserver = Observer?> { t ->
+ val accountDataObserver = Observer?> { t ->
if (t?.getOrNull()?.type == "${DefaultSharedSecretStorageService.KEY_ID_BASE}.$TEST_KEY_ID") {
accountData = t.getOrNull()
accountDataLock.countDown()
@@ -100,13 +100,13 @@ class QuadSTests : InstrumentedTest {
quadS.setDefaultKey(TEST_KEY_ID)
}
- var defaultKeyAccountData: AccountDataEvent? = null
+ var defaultKeyAccountData: UserAccountDataEvent? = null
val defaultDataLock = CountDownLatch(1)
val liveDefAccountData = runBlocking(Dispatchers.Main) {
- aliceSession.userAccountDataService().getLiveAccountDataEvent(DefaultSharedSecretStorageService.DEFAULT_KEY_ID)
+ aliceSession.accountDataService().getLiveUserAccountDataEvent(DefaultSharedSecretStorageService.DEFAULT_KEY_ID)
}
- val accountDefDataObserver = Observer?> { t ->
+ val accountDefDataObserver = Observer?> { t ->
if (t?.getOrNull()?.type == DefaultSharedSecretStorageService.DEFAULT_KEY_ID) {
defaultKeyAccountData = t.getOrNull()!!
defaultDataLock.countDown()
@@ -206,7 +206,7 @@ class QuadSTests : InstrumentedTest {
)
}
- val accountDataEvent = aliceSession.userAccountDataService().getAccountDataEvent("my.secret")
+ val accountDataEvent = aliceSession.accountDataService().getUserAccountDataEvent("my.secret")
val encryptedContent = accountDataEvent?.content?.get("encrypted") as? Map<*, *>
assertEquals("Content should contains two encryptions", 2, encryptedContent?.keys?.size ?: 0)
@@ -275,14 +275,14 @@ class QuadSTests : InstrumentedTest {
mTestHelper.signOutAndClose(aliceSession)
}
- private fun assertAccountData(session: Session, type: String): AccountDataEvent {
+ private fun assertAccountData(session: Session, type: String): UserAccountDataEvent {
val accountDataLock = CountDownLatch(1)
- var accountData: AccountDataEvent? = null
+ var accountData: UserAccountDataEvent? = null
val liveAccountData = runBlocking(Dispatchers.Main) {
- session.userAccountDataService().getLiveAccountDataEvent(type)
+ session.accountDataService().getLiveUserAccountDataEvent(type)
}
- val accountDataObserver = Observer?> { t ->
+ val accountDataObserver = Observer?> { t ->
if (t?.getOrNull()?.type == type) {
accountData = t.getOrNull()
accountDataLock.countDown()
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt
index e888e5d2de..2f981ffbbe 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt
@@ -24,7 +24,7 @@ import org.matrix.android.sdk.api.failure.GlobalError
import org.matrix.android.sdk.api.federation.FederationService
import org.matrix.android.sdk.api.pushrules.PushRuleService
import org.matrix.android.sdk.api.session.account.AccountService
-import org.matrix.android.sdk.api.session.accountdata.AccountDataService
+import org.matrix.android.sdk.api.session.accountdata.SessionAccountDataService
import org.matrix.android.sdk.api.session.cache.CacheService
import org.matrix.android.sdk.api.session.call.CallSignalingService
import org.matrix.android.sdk.api.session.content.ContentUploadStateTracker
@@ -239,9 +239,9 @@ interface Session :
fun openIdService(): OpenIdService
/**
- * Returns the user account data service associated with the session
+ * Returns the account data service associated with the session
*/
- fun userAccountDataService(): AccountDataService
+ fun accountDataService(): SessionAccountDataService
/**
* Add a listener to the session.
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/accountdata/SessionAccountDataService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/accountdata/SessionAccountDataService.kt
new file mode 100644
index 0000000000..2ffb9112d1
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/accountdata/SessionAccountDataService.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.android.sdk.api.session.accountdata
+
+import androidx.lifecycle.LiveData
+import org.matrix.android.sdk.api.session.events.model.Content
+import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataEvent
+import org.matrix.android.sdk.api.util.Optional
+
+/**
+ * This service is attached globally to the session.
+ */
+interface SessionAccountDataService {
+ /**
+ * Retrieve the account data with the provided type or null if not found
+ */
+ fun getUserAccountDataEvent(type: String): UserAccountDataEvent?
+
+ /**
+ * Observe the account data with the provided type
+ */
+ fun getLiveUserAccountDataEvent(type: String): LiveData>
+
+ /**
+ * Retrieve the account data with the provided types. The return list can have a different size that
+ * the size of the types set, because some AccountData may not exist.
+ * If an empty set is provided, all the AccountData are retrieved
+ */
+ fun getUserAccountDataEvents(types: Set): List
+
+ /**
+ * Observe the account data with the provided types. If an empty set is provided, all the AccountData are observed
+ */
+ fun getLiveUserAccountDataEvents(types: Set): LiveData>
+
+ /**
+ * Retrieve the room account data with the provided types. The return list can have a different size that
+ * the size of the types set, because some AccountData may not exist.
+ * If an empty set is provided, all the room AccountData are retrieved
+ */
+ fun getRoomAccountDataEvents(types: Set): List
+
+ /**
+ * Observe the room account data with the provided types. If an empty set is provided, AccountData of every room are observed
+ */
+ fun getLiveRoomAccountDataEvents(types: Set): LiveData>
+
+ /**
+ * Update the account data with the provided type and the provided account data content
+ */
+ suspend fun updateUserAccountData(type: String, content: Content)
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/accountdata/AccountDataEvent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/accountdata/UserAccountDataEvent.kt
similarity index 91%
rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/accountdata/AccountDataEvent.kt
rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/accountdata/UserAccountDataEvent.kt
index e5cbd07aaf..77381a28c4 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/accountdata/AccountDataEvent.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/accountdata/UserAccountDataEvent.kt
@@ -22,10 +22,10 @@ import org.matrix.android.sdk.api.session.events.model.Content
/**
* This is a simplified Event with just a type and a content.
- * Currently used types are defined in [UserAccountDataTypes].
+ * Currently used types are defined in [UserAccountDataTypes]
*/
@JsonClass(generateAdapter = true)
-data class AccountDataEvent(
+data class UserAccountDataEvent(
@Json(name = "type") val type: String,
@Json(name = "content") val content: Content
)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt
index 1b7a5243e2..e3f00a24b6 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt
@@ -42,7 +42,6 @@ import org.matrix.android.sdk.internal.crypto.model.event.RoomKeyWithHeldContent
import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
import org.matrix.android.sdk.internal.crypto.model.rest.DevicesListResponse
import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyRequestBody
-import kotlin.jvm.Throws
interface CryptoService {
@@ -82,9 +81,11 @@ interface CryptoService {
fun getDeviceTrackingStatus(userId: String): Int
- fun importRoomKeys(roomKeysAsArray: ByteArray, password: String, progressListener: ProgressListener?, callback: MatrixCallback)
+ suspend fun importRoomKeys(roomKeysAsArray: ByteArray,
+ password: String,
+ progressListener: ProgressListener?): ImportRoomKeysResult
- fun exportRoomKeys(password: String, callback: MatrixCallback)
+ suspend fun exportRoomKeys(password: String): ByteArray
fun setRoomBlacklistUnverifiedDevices(roomId: String)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/identity/IdentityService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/identity/IdentityService.kt
index 8f8967e8fb..ae546b6cec 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/identity/IdentityService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/identity/IdentityService.kt
@@ -35,7 +35,7 @@ interface IdentityService {
/**
* Check if the identity server is valid
* See https://matrix.org/docs/spec/identity_service/latest#status-check
- * RiotX SDK only supports identity server API v2
+ * Matrix Android SDK2 only supports identity server API v2
*/
suspend fun isValidIdentityServer(url: String)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt
index 41bcbf8ff6..cb04b05a74 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt
@@ -17,7 +17,7 @@
package org.matrix.android.sdk.api.session.room
import androidx.lifecycle.LiveData
-import org.matrix.android.sdk.api.session.accountdata.AccountDataService
+import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataService
import org.matrix.android.sdk.api.session.room.alias.AliasService
import org.matrix.android.sdk.api.session.room.call.RoomCallService
import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService
@@ -57,7 +57,7 @@ interface Room :
RelationService,
RoomCryptoService,
RoomPushRuleService,
- AccountDataService {
+ RoomAccountDataService {
/**
* The roomId of this room
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/accountdata/RoomAccountDataEvent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/accountdata/RoomAccountDataEvent.kt
new file mode 100644
index 0000000000..eb676ab5e7
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/accountdata/RoomAccountDataEvent.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.android.sdk.api.session.room.accountdata
+
+import org.matrix.android.sdk.api.session.events.model.Content
+
+/**
+ * This is a simplified Event with just a roomId, a type and a content.
+ * Currently used types are defined in [RoomAccountDataTypes].
+ */
+data class RoomAccountDataEvent(
+ val roomId: String,
+ val type: String,
+ val content: Content
+)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/accountdata/AccountDataService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/accountdata/RoomAccountDataService.kt
similarity index 81%
rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/accountdata/AccountDataService.kt
rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/accountdata/RoomAccountDataService.kt
index 77f3eb0cd9..190749c85c 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/accountdata/AccountDataService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/accountdata/RoomAccountDataService.kt
@@ -14,37 +14,37 @@
* limitations under the License.
*/
-package org.matrix.android.sdk.api.session.accountdata
+package org.matrix.android.sdk.api.session.room.accountdata
import androidx.lifecycle.LiveData
import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.util.Optional
/**
- * This service can be attached globally to the session so it represents user data or attached to a single room.
+ * This service is attached to a single room.
*/
-interface AccountDataService {
+interface RoomAccountDataService {
/**
* Retrieve the account data with the provided type or null if not found
*/
- fun getAccountDataEvent(type: String): AccountDataEvent?
+ fun getAccountDataEvent(type: String): RoomAccountDataEvent?
/**
* Observe the account data with the provided type
*/
- fun getLiveAccountDataEvent(type: String): LiveData>
+ fun getLiveAccountDataEvent(type: String): LiveData>
/**
* Retrieve the account data with the provided types. The return list can have a different size that
* the size of the types set, because some AccountData may not exist.
* If an empty set is provided, all the AccountData are retrieved
*/
- fun getAccountDataEvents(types: Set): List
+ fun getAccountDataEvents(types: Set): List
/**
* Observe the account data with the provided types. If an empty set is provided, all the AccountData are observed
*/
- fun getLiveAccountDataEvents(types: Set): LiveData>
+ fun getLiveAccountDataEvents(types: Set): LiveData>
/**
* Update the account data with the provided type and the provided account data content
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt
index 7f5cfe8df1..d170ae3dd3 100755
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt
@@ -388,7 +388,7 @@ internal class DefaultCryptoService @Inject constructor(
cryptoStore.close()
}
- // Aways enabled on RiotX
+ // Always enabled on Matrix Android SDK2
override fun isCryptoEnabled() = true
/**
@@ -928,14 +928,10 @@ internal class DefaultCryptoService @Inject constructor(
* Export the crypto keys
*
* @param password the password
- * @param callback the exported keys
+ * @return the exported keys
*/
- override fun exportRoomKeys(password: String, callback: MatrixCallback) {
- cryptoCoroutineScope.launch(coroutineDispatchers.main) {
- runCatching {
- exportRoomKeys(password, MXMegolmExportEncryption.DEFAULT_ITERATION_COUNT)
- }.foldToCallback(callback)
- }
+ override suspend fun exportRoomKeys(password: String): ByteArray {
+ return exportRoomKeys(password, MXMegolmExportEncryption.DEFAULT_ITERATION_COUNT)
}
/**
@@ -963,42 +959,37 @@ internal class DefaultCryptoService @Inject constructor(
* @param roomKeysAsArray the room keys as array.
* @param password the password
* @param progressListener the progress listener
- * @param callback the asynchronous callback.
+ * @return the result ImportRoomKeysResult
*/
- override fun importRoomKeys(roomKeysAsArray: ByteArray,
- password: String,
- progressListener: ProgressListener?,
- callback: MatrixCallback) {
- cryptoCoroutineScope.launch(coroutineDispatchers.main) {
- runCatching {
- withContext(coroutineDispatchers.crypto) {
- Timber.v("## CRYPTO | importRoomKeys starts")
+ override suspend fun importRoomKeys(roomKeysAsArray: ByteArray,
+ password: String,
+ progressListener: ProgressListener?): ImportRoomKeysResult {
+ return withContext(coroutineDispatchers.crypto) {
+ Timber.v("## CRYPTO | importRoomKeys starts")
- val t0 = System.currentTimeMillis()
- val roomKeys = MXMegolmExportEncryption.decryptMegolmKeyFile(roomKeysAsArray, password)
- val t1 = System.currentTimeMillis()
+ val t0 = System.currentTimeMillis()
+ val roomKeys = MXMegolmExportEncryption.decryptMegolmKeyFile(roomKeysAsArray, password)
+ val t1 = System.currentTimeMillis()
- Timber.v("## CRYPTO | importRoomKeys : decryptMegolmKeyFile done in ${t1 - t0} ms")
+ Timber.v("## CRYPTO | importRoomKeys : decryptMegolmKeyFile done in ${t1 - t0} ms")
- val importedSessions = MoshiProvider.providesMoshi()
- .adapter>(Types.newParameterizedType(List::class.java, MegolmSessionData::class.java))
- .fromJson(roomKeys)
+ val importedSessions = MoshiProvider.providesMoshi()
+ .adapter>(Types.newParameterizedType(List::class.java, MegolmSessionData::class.java))
+ .fromJson(roomKeys)
- val t2 = System.currentTimeMillis()
+ val t2 = System.currentTimeMillis()
- Timber.v("## CRYPTO | importRoomKeys : JSON parsing ${t2 - t1} ms")
+ Timber.v("## CRYPTO | importRoomKeys : JSON parsing ${t2 - t1} ms")
- if (importedSessions == null) {
- throw Exception("Error")
- }
+ if (importedSessions == null) {
+ throw Exception("Error")
+ }
- megolmSessionDataImporter.handle(
- megolmSessionsData = importedSessions,
- fromBackup = false,
- progressListener = progressListener
- )
- }
- }.foldToCallback(callback)
+ megolmSessionDataImporter.handle(
+ megolmSessionsData = importedSessions,
+ fromBackup = false,
+ progressListener = progressListener
+ )
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmDecryption.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmDecryption.kt
index a29ac457fb..70d2022299 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmDecryption.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmDecryption.kt
@@ -155,7 +155,7 @@ internal class MXMegolmDecryption(private val userId: String,
withHeldInfo.code?.value ?: "",
withHeldInfo.reason)
} else {
- // This is un-used in riotX SDK, not sure if needed
+ // This is un-used in Matrix Android SDK2, not sure if needed
// addEventToPendingList(event, timeline)
if (requestKeysOnFail) {
requestKeysForEvent(event, false)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt
index 1f80ce2c81..fb10cf4482 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt
@@ -18,7 +18,7 @@ package org.matrix.android.sdk.internal.crypto.secrets
import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.listeners.ProgressListener
-import org.matrix.android.sdk.api.session.accountdata.AccountDataService
+import org.matrix.android.sdk.api.session.accountdata.SessionAccountDataService
import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.securestorage.EncryptedSecretContent
import org.matrix.android.sdk.api.session.securestorage.IntegrityResult
@@ -56,7 +56,7 @@ import kotlin.experimental.and
internal class DefaultSharedSecretStorageService @Inject constructor(
@UserId private val userId: String,
- private val accountDataService: AccountDataService,
+ private val accountDataService: SessionAccountDataService,
private val outgoingGossipingRequestManager: OutgoingGossipingRequestManager,
private val coroutineDispatchers: MatrixCoroutineDispatchers,
private val cryptoCoroutineScope: CoroutineScope
@@ -84,7 +84,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
)
} ?: storageKeyContent
- accountDataService.updateAccountData("$KEY_ID_BASE.$keyId", signedContent.toContent())
+ accountDataService.updateUserAccountData("$KEY_ID_BASE.$keyId", signedContent.toContent())
SsssKeyCreationInfo(
keyId = keyId,
content = storageKeyContent,
@@ -113,7 +113,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
)
} ?: storageKeyContent
- accountDataService.updateAccountData(
+ accountDataService.updateUserAccountData(
"$KEY_ID_BASE.$keyId",
signedContent.toContent()
)
@@ -127,11 +127,11 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
}
override fun hasKey(keyId: String): Boolean {
- return accountDataService.getAccountDataEvent("$KEY_ID_BASE.$keyId") != null
+ return accountDataService.getUserAccountDataEvent("$KEY_ID_BASE.$keyId") != null
}
override fun getKey(keyId: String): KeyInfoResult {
- val accountData = accountDataService.getAccountDataEvent("$KEY_ID_BASE.$keyId")
+ val accountData = accountDataService.getUserAccountDataEvent("$KEY_ID_BASE.$keyId")
?: return KeyInfoResult.Error(SharedSecretStorageError.UnknownKey(keyId))
return SecretStorageKeyContent.fromJson(accountData.content)?.let {
KeyInfoResult.Success(
@@ -143,14 +143,14 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
override suspend fun setDefaultKey(keyId: String) {
val existingKey = getKey(keyId)
if (existingKey is KeyInfoResult.Success) {
- accountDataService.updateAccountData(DEFAULT_KEY_ID, mapOf("key" to keyId))
+ accountDataService.updateUserAccountData(DEFAULT_KEY_ID, mapOf("key" to keyId))
} else {
throw SharedSecretStorageError.UnknownKey(keyId)
}
}
override fun getDefaultKey(): KeyInfoResult {
- val accountData = accountDataService.getAccountDataEvent(DEFAULT_KEY_ID)
+ val accountData = accountDataService.getUserAccountDataEvent(DEFAULT_KEY_ID)
?: return KeyInfoResult.Error(SharedSecretStorageError.UnknownKey(DEFAULT_KEY_ID))
val keyId = accountData.content["key"] as? String
?: return KeyInfoResult.Error(SharedSecretStorageError.UnknownKey(DEFAULT_KEY_ID))
@@ -178,7 +178,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
}
}
- accountDataService.updateAccountData(
+ accountDataService.updateUserAccountData(
type = name,
content = mapOf("encrypted" to encryptedContents)
)
@@ -288,7 +288,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
}
override fun getAlgorithmsForSecret(name: String): List {
- val accountData = accountDataService.getAccountDataEvent(name)
+ val accountData = accountDataService.getUserAccountDataEvent(name)
?: return listOf(KeyInfoResult.Error(SharedSecretStorageError.UnknownSecret(name)))
val encryptedContent = accountData.content[ENCRYPTED] as? Map<*, *>
?: return listOf(KeyInfoResult.Error(SharedSecretStorageError.SecretNotEncrypted(name)))
@@ -303,7 +303,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
}
override suspend fun getSecret(name: String, keyId: String?, secretKey: SsssKeySpec): String {
- val accountData = accountDataService.getAccountDataEvent(name) ?: throw SharedSecretStorageError.UnknownSecret(name)
+ val accountData = accountDataService.getUserAccountDataEvent(name) ?: throw SharedSecretStorageError.UnknownSecret(name)
val encryptedContent = accountData.content[ENCRYPTED] as? Map<*, *> ?: throw SharedSecretStorageError.SecretNotEncrypted(name)
val key = keyId?.let { getKey(it) } as? KeyInfoResult.Success ?: getDefaultKey() as? KeyInfoResult.Success
?: throw SharedSecretStorageError.UnknownKey(name)
@@ -368,7 +368,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
}
secretNames.forEach { secretName ->
- val secretEvent = accountDataService.getAccountDataEvent(secretName)
+ val secretEvent = accountDataService.getUserAccountDataEvent(secretName)
?: return IntegrityResult.Error(SharedSecretStorageError.UnknownSecret(secretName))
if ((secretEvent.content["encrypted"] as? Map<*, *>)?.get(keyInfo.id) == null) {
return IntegrityResult.Error(SharedSecretStorageError.SecretNotEncryptedWithKey(secretName, keyInfo.id))
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/AccountDataMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/AccountDataMapper.kt
index 4edfdad897..dca0f927ad 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/AccountDataMapper.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/AccountDataMapper.kt
@@ -17,7 +17,8 @@
package org.matrix.android.sdk.internal.database.mapper
import com.squareup.moshi.Moshi
-import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent
+import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
+import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataEvent
import org.matrix.android.sdk.api.util.JSON_DICT_PARAMETERIZED_TYPE
import org.matrix.android.sdk.internal.database.model.RoomAccountDataEntity
import org.matrix.android.sdk.internal.database.model.UserAccountDataEntity
@@ -27,15 +28,16 @@ internal class AccountDataMapper @Inject constructor(moshi: Moshi) {
private val adapter = moshi.adapter>(JSON_DICT_PARAMETERIZED_TYPE)
- fun map(entity: UserAccountDataEntity): AccountDataEvent {
- return AccountDataEvent(
+ fun map(entity: UserAccountDataEntity): UserAccountDataEvent {
+ return UserAccountDataEvent(
type = entity.type ?: "",
content = entity.contentStr?.let { adapter.fromJson(it) }.orEmpty()
)
}
- fun map(entity: RoomAccountDataEntity): AccountDataEvent {
- return AccountDataEvent(
+ fun map(roomId: String, entity: RoomAccountDataEntity): RoomAccountDataEvent {
+ return RoomAccountDataEvent(
+ roomId = roomId,
type = entity.type ?: "",
content = entity.contentStr?.let { adapter.fromJson(it) }.orEmpty()
)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/DefaultLegacySessionImporter.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/DefaultLegacySessionImporter.kt
index e0e2f96fa9..4586cfea1e 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/DefaultLegacySessionImporter.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/DefaultLegacySessionImporter.kt
@@ -153,7 +153,7 @@ internal class DefaultLegacySessionImporter @Inject constructor(
}
private fun importCryptoDb(legacyConfig: LegacyHomeServerConnectionConfig) {
- // Here we migrate the DB, we copy the crypto DB to the location specific to RiotX, and we encrypt it.
+ // Here we migrate the DB, we copy the crypto DB to the location specific to Matrix SDK2, and we encrypt it.
val userMd5 = legacyConfig.credentials.userId.md5()
val sessionId = legacyConfig.credentials.let { (if (it.deviceId.isNullOrBlank()) it.userId else "${it.userId}|${it.deviceId}").md5() }
@@ -177,12 +177,12 @@ internal class DefaultLegacySessionImporter @Inject constructor(
Timber.d("Migration: copy DB to encrypted DB")
Realm.getInstance(realmConfiguration).use {
- // Move the DB to the new location, handled by RiotX
+ // Move the DB to the new location, handled by Matrix SDK2
it.writeEncryptedCopyTo(File(newLocation, realmConfiguration.realmFileName), realmKeysUtils.getRealmEncryptionKey(keyAlias))
}
}
- // Delete all the files created by Riot Android which will not be used anymore by RiotX
+ // Delete all the files created by Riot Android which will not be used anymore by Element
private fun clearFileSystem(legacyConfig: LegacyHomeServerConnectionConfig) {
val cryptoFolder = legacyConfig.credentials.userId.md5()
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/UserAgentHolder.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/UserAgentHolder.kt
index 973c120f59..1a88404128 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/UserAgentHolder.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/UserAgentHolder.kt
@@ -36,7 +36,7 @@ internal class UserAgentHolder @Inject constructor(private val context: Context,
/**
* Create an user agent with the application version.
- * Ex: RiotX/1.0.0 (Linux; U; Android 6.0.1; SM-A510F Build/MMB29; Flavour GPlay; MatrixAndroidSDK_X 1.0)
+ * Ex: Element/1.0.0 (Linux; U; Android 6.0.1; SM-A510F Build/MMB29; Flavour GPlay; MatrixAndroidSDK_X 1.0)
*
* @param flavorDescription the flavor description
*/
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt
index 1f47978198..1cf99bbbd7 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt
@@ -29,7 +29,7 @@ import org.matrix.android.sdk.api.pushrules.PushRuleService
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.SessionLifecycleObserver
import org.matrix.android.sdk.api.session.account.AccountService
-import org.matrix.android.sdk.api.session.accountdata.AccountDataService
+import org.matrix.android.sdk.api.session.accountdata.SessionAccountDataService
import org.matrix.android.sdk.api.session.cache.CacheService
import org.matrix.android.sdk.api.session.call.CallSignalingService
import org.matrix.android.sdk.api.session.content.ContentUploadStateTracker
@@ -74,7 +74,6 @@ import org.matrix.android.sdk.internal.session.identity.DefaultIdentityService
import org.matrix.android.sdk.internal.session.sync.SyncTokenStore
import org.matrix.android.sdk.internal.session.sync.job.SyncThread
import org.matrix.android.sdk.internal.session.sync.job.SyncWorker
-import org.matrix.android.sdk.internal.session.user.accountdata.UserAccountDataService
import org.matrix.android.sdk.internal.util.createUIHandler
import timber.log.Timber
import javax.inject.Inject
@@ -118,7 +117,7 @@ internal class DefaultSession @Inject constructor(
private val contentDownloadStateTracker: ContentDownloadStateTracker,
private val initialSyncProgressService: Lazy,
private val homeServerCapabilitiesService: Lazy,
- private val accountDataService: Lazy,
+ private val accountDataService: Lazy,
private val _sharedSecretStorageService: Lazy,
private val accountService: Lazy,
private val eventService: Lazy,
@@ -293,7 +292,7 @@ internal class DefaultSession @Inject constructor(
override fun openIdService(): OpenIdService = openIdService.get()
- override fun userAccountDataService(): AccountDataService = accountDataService.get()
+ override fun accountDataService(): SessionAccountDataService = accountDataService.get()
override fun getOkHttpClient(): OkHttpClient {
return unauthenticatedWithCertificateOkHttpClient.get()
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionModule.kt
index 49ce92372e..e6da21315b 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionModule.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionModule.kt
@@ -34,7 +34,7 @@ import org.matrix.android.sdk.api.auth.data.sessionId
import org.matrix.android.sdk.api.crypto.MXCryptoConfig
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.SessionLifecycleObserver
-import org.matrix.android.sdk.api.session.accountdata.AccountDataService
+import org.matrix.android.sdk.api.session.accountdata.SessionAccountDataService
import org.matrix.android.sdk.api.session.events.EventService
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilitiesService
import org.matrix.android.sdk.api.session.initsync.InitialSyncProgressService
@@ -93,7 +93,7 @@ import org.matrix.android.sdk.internal.session.room.send.queue.EventSenderProces
import org.matrix.android.sdk.internal.session.room.tombstone.RoomTombstoneEventProcessor
import org.matrix.android.sdk.internal.session.securestorage.DefaultSecureStorageService
import org.matrix.android.sdk.internal.session.typing.DefaultTypingUsersTracker
-import org.matrix.android.sdk.internal.session.user.accountdata.UserAccountDataService
+import org.matrix.android.sdk.internal.session.user.accountdata.DefaultSessionAccountDataService
import org.matrix.android.sdk.internal.session.widgets.DefaultWidgetURLFormatter
import org.matrix.android.sdk.internal.util.md5
import retrofit2.Retrofit
@@ -364,7 +364,7 @@ internal abstract class SessionModule {
abstract fun bindHomeServerCapabilitiesService(service: DefaultHomeServerCapabilitiesService): HomeServerCapabilitiesService
@Binds
- abstract fun bindAccountDataService(service: UserAccountDataService): AccountDataService
+ abstract fun bindSessionAccountDataService(service: DefaultSessionAccountDataService): SessionAccountDataService
@Binds
abstract fun bindEventService(service: DefaultEventService): EventService
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/integrationmanager/IntegrationManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/integrationmanager/IntegrationManager.kt
index f79f8084a8..aa82cf9222 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/integrationmanager/IntegrationManager.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/integrationmanager/IntegrationManager.kt
@@ -33,7 +33,7 @@ import org.matrix.android.sdk.internal.extensions.observeNotNull
import org.matrix.android.sdk.api.session.SessionLifecycleObserver
import org.matrix.android.sdk.internal.session.SessionScope
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes
-import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent
+import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import org.matrix.android.sdk.internal.session.user.accountdata.UserAccountDataDataSource
import org.matrix.android.sdk.internal.session.user.accountdata.UpdateUserAccountDataTask
import org.matrix.android.sdk.internal.session.widgets.helper.WidgetFactory
@@ -240,7 +240,7 @@ internal class IntegrationManager @Inject constructor(matrixConfiguration: Matri
)
}
- private fun AccountDataEvent.asIntegrationManagerWidgetContent(): WidgetContent? {
+ private fun UserAccountDataEvent.asIntegrationManagerWidgetContent(): WidgetContent? {
return extractWidgetSequence(widgetFactory)
.filter {
WidgetType.IntegrationManager == it.type
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoom.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoom.kt
index 5a2eef7e8a..0d9c106d41 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoom.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoom.kt
@@ -17,10 +17,10 @@
package org.matrix.android.sdk.internal.session.room
import androidx.lifecycle.LiveData
-import org.matrix.android.sdk.api.session.accountdata.AccountDataService
import org.matrix.android.sdk.api.session.crypto.CryptoService
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.room.Room
+import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataService
import org.matrix.android.sdk.api.session.room.alias.AliasService
import org.matrix.android.sdk.api.session.room.call.RoomCallService
import org.matrix.android.sdk.api.session.room.members.MembershipService
@@ -42,7 +42,6 @@ import org.matrix.android.sdk.api.session.space.Space
import org.matrix.android.sdk.api.util.Optional
import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
import org.matrix.android.sdk.internal.session.permalinks.ViaParameterFinder
-import org.matrix.android.sdk.internal.session.room.accountdata.RoomAccountDataService
import org.matrix.android.sdk.internal.session.room.state.SendStateTask
import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource
import org.matrix.android.sdk.internal.session.search.SearchTask
@@ -86,7 +85,7 @@ internal class DefaultRoom(override val roomId: String,
RelationService by relationService,
MembershipService by roomMembersService,
RoomPushRuleService by roomPushRuleService,
- AccountDataService by roomAccountDataService {
+ RoomAccountDataService by roomAccountDataService {
override fun getRoomSummaryLive(): LiveData> {
return roomSummaryDataSource.getRoomSummaryLive(roomId)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomFactory.kt
index 8efbf2360a..9ddb8f1177 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomFactory.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomFactory.kt
@@ -19,8 +19,8 @@ package org.matrix.android.sdk.internal.session.room
import org.matrix.android.sdk.api.session.crypto.CryptoService
import org.matrix.android.sdk.api.session.room.Room
import org.matrix.android.sdk.internal.session.SessionScope
-import org.matrix.android.sdk.internal.session.room.accountdata.RoomAccountDataService
import org.matrix.android.sdk.internal.session.permalinks.ViaParameterFinder
+import org.matrix.android.sdk.internal.session.room.accountdata.DefaultRoomAccountDataService
import org.matrix.android.sdk.internal.session.room.alias.DefaultAliasService
import org.matrix.android.sdk.internal.session.room.call.DefaultRoomCallService
import org.matrix.android.sdk.internal.session.room.draft.DefaultDraftService
@@ -61,7 +61,7 @@ internal class DefaultRoomFactory @Inject constructor(private val cryptoService:
private val relationServiceFactory: DefaultRelationService.Factory,
private val membershipServiceFactory: DefaultMembershipService.Factory,
private val roomPushRuleServiceFactory: DefaultRoomPushRuleService.Factory,
- private val roomAccountDataServiceFactory: RoomAccountDataService.Factory,
+ private val roomAccountDataServiceFactory: DefaultRoomAccountDataService.Factory,
private val sendStateTask: SendStateTask,
private val viaParameterFinder: ViaParameterFinder,
private val searchTask: SearchTask) :
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/accountdata/RoomAccountDataService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/accountdata/DefaultRoomAccountDataService.kt
similarity index 78%
rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/accountdata/RoomAccountDataService.kt
rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/accountdata/DefaultRoomAccountDataService.kt
index 9e9e9dc322..d43c1d3217 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/accountdata/RoomAccountDataService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/accountdata/DefaultRoomAccountDataService.kt
@@ -20,34 +20,34 @@ import androidx.lifecycle.LiveData
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
-import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent
-import org.matrix.android.sdk.api.session.accountdata.AccountDataService
import org.matrix.android.sdk.api.session.events.model.Content
+import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataEvent
+import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataService
import org.matrix.android.sdk.api.util.Optional
-internal class RoomAccountDataService @AssistedInject constructor(@Assisted private val roomId: String,
+internal class DefaultRoomAccountDataService @AssistedInject constructor(@Assisted private val roomId: String,
private val dataSource: RoomAccountDataDataSource,
private val updateRoomAccountDataTask: UpdateRoomAccountDataTask
-) : AccountDataService {
+) : RoomAccountDataService {
@AssistedFactory
interface Factory {
- fun create(roomId: String): RoomAccountDataService
+ fun create(roomId: String): DefaultRoomAccountDataService
}
- override fun getAccountDataEvent(type: String): AccountDataEvent? {
+ override fun getAccountDataEvent(type: String): RoomAccountDataEvent? {
return dataSource.getAccountDataEvent(roomId, type)
}
- override fun getLiveAccountDataEvent(type: String): LiveData> {
+ override fun getLiveAccountDataEvent(type: String): LiveData> {
return dataSource.getLiveAccountDataEvent(roomId, type)
}
- override fun getAccountDataEvents(types: Set): List {
+ override fun getAccountDataEvents(types: Set): List {
return dataSource.getAccountDataEvents(roomId, types)
}
- override fun getLiveAccountDataEvents(types: Set): LiveData> {
+ override fun getLiveAccountDataEvents(types: Set): LiveData> {
return dataSource.getLiveAccountDataEvents(roomId, types)
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/accountdata/RoomAccountDataDataSource.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/accountdata/RoomAccountDataDataSource.kt
index 0bcf9d7f38..0e4493846c 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/accountdata/RoomAccountDataDataSource.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/accountdata/RoomAccountDataDataSource.kt
@@ -20,14 +20,16 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.Transformations
import com.zhuinden.monarchy.Monarchy
-import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent
+import io.realm.Realm
+import io.realm.RealmQuery
+import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataEvent
import org.matrix.android.sdk.api.util.Optional
import org.matrix.android.sdk.api.util.toOptional
import org.matrix.android.sdk.internal.database.RealmSessionProvider
import org.matrix.android.sdk.internal.database.mapper.AccountDataMapper
import org.matrix.android.sdk.internal.database.model.RoomAccountDataEntityFields
import org.matrix.android.sdk.internal.database.model.RoomEntity
-import org.matrix.android.sdk.internal.database.query.where
+import org.matrix.android.sdk.internal.database.model.RoomEntityFields
import org.matrix.android.sdk.internal.di.SessionDatabase
import javax.inject.Inject
@@ -35,43 +37,62 @@ internal class RoomAccountDataDataSource @Inject constructor(@SessionDatabase pr
private val realmSessionProvider: RealmSessionProvider,
private val accountDataMapper: AccountDataMapper) {
- fun getAccountDataEvent(roomId: String, type: String): AccountDataEvent? {
+ fun getAccountDataEvent(roomId: String, type: String): RoomAccountDataEvent? {
return getAccountDataEvents(roomId, setOf(type)).firstOrNull()
}
- fun getLiveAccountDataEvent(roomId: String, type: String): LiveData> {
+ fun getLiveAccountDataEvent(roomId: String, type: String): LiveData> {
return Transformations.map(getLiveAccountDataEvents(roomId, setOf(type))) {
it.firstOrNull()?.toOptional()
}
}
- fun getAccountDataEvents(roomId: String, types: Set): List {
+ /**
+ * @param roomId the roomId to search for account data event. If null will check in every room.
+ * @param types the types to filter. If empty will return all account data event in given room (or every room if roomId is null)
+ *
+ */
+ fun getAccountDataEvents(roomId: String?, types: Set): List {
return realmSessionProvider.withRealm { realm ->
- val roomEntity = RoomEntity.where(realm, roomId).findFirst() ?: return@withRealm emptyList()
+ val roomEntity = buildRoomQuery(realm, roomId, types).findFirst() ?: return@withRealm emptyList()
roomEntity.accountDataEvents(types)
}
}
- fun getLiveAccountDataEvents(roomId: String, types: Set): LiveData> {
- val liveRoomEntity = monarchy.findAllManagedWithChanges { RoomEntity.where(it, roomId) }
- val resultLiveData = MediatorLiveData>()
- resultLiveData.addSource(liveRoomEntity) {
- val roomEntity = it.realmResults.firstOrNull()
- if (roomEntity == null) {
- resultLiveData.postValue(emptyList())
- } else {
- val mappedResult = roomEntity.accountDataEvents(types)
- resultLiveData.postValue(mappedResult)
- }
+ /**
+ * @param roomId the roomId to search for account data event. If null will check in every room.
+ * @param types the types to filter. If empty will return all account data event in the given room (or every room if roomId is null).
+ *
+ */
+ fun getLiveAccountDataEvents(roomId: String?, types: Set): LiveData> {
+ val liveRoomEntity = monarchy.findAllManagedWithChanges {
+ buildRoomQuery(it, roomId, types)
+ }
+ val resultLiveData = MediatorLiveData>()
+ resultLiveData.addSource(liveRoomEntity) { changeSet ->
+ val mappedResult = changeSet.realmResults.flatMap { it.accountDataEvents(types) }
+ resultLiveData.postValue(mappedResult)
}
return resultLiveData
}
- private fun RoomEntity.accountDataEvents(types: Set): List {
+ private fun buildRoomQuery(realm: Realm, roomId: String?, types: Set): RealmQuery {
+ val query = realm.where(RoomEntity::class.java)
+ if (roomId != null) {
+ query.equalTo(RoomEntityFields.ROOM_ID, roomId)
+ }
+ query.isNotEmpty(RoomEntityFields.ACCOUNT_DATA.`$`)
+ if (types.isNotEmpty()) {
+ query.`in`(RoomEntityFields.ACCOUNT_DATA.TYPE, types.toTypedArray())
+ }
+ return query
+ }
+
+ private fun RoomEntity.accountDataEvents(types: Set): List {
val query = accountData.where()
if (types.isNotEmpty()) {
query.`in`(RoomAccountDataEntityFields.TYPE, types.toTypedArray())
}
- return query.findAll().map { accountDataMapper.map(it) }
+ return query.findAll().map { accountDataMapper.map(roomId, it) }
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt
index e230599f8f..8cc5d943b7 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt
@@ -24,7 +24,6 @@ import io.realm.RealmQuery
import io.realm.RealmResults
import io.realm.Sort
import org.matrix.android.sdk.api.MatrixCallback
-import org.matrix.android.sdk.api.NoOpMatrixCallback
import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.events.model.EventType
@@ -168,9 +167,7 @@ internal class DefaultTimeline(
timelineEvents.addChangeListener(eventsChangeListener)
handleInitialLoad()
loadRoomMembersTask
- .configureWith(LoadRoomMembersTask.Params(roomId)) {
- this.callback = NoOpMatrixCallback()
- }
+ .configureWith(LoadRoomMembersTask.Params(roomId))
.executeBy(taskExecutor)
// Ensure ReadReceipt from init sync are loaded
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/typing/DefaultTypingService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/typing/DefaultTypingService.kt
index 39b7967bc1..b76829e893 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/typing/DefaultTypingService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/typing/DefaultTypingService.kt
@@ -18,13 +18,13 @@ package org.matrix.android.sdk.internal.session.room.typing
import android.os.SystemClock
import dagger.assisted.Assisted
-import dagger.assisted.AssistedInject
import dagger.assisted.AssistedFactory
-import org.matrix.android.sdk.api.MatrixCallback
+import dagger.assisted.AssistedInject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.session.room.typing.TypingService
-import org.matrix.android.sdk.api.util.Cancelable
-import org.matrix.android.sdk.internal.task.TaskExecutor
-import org.matrix.android.sdk.internal.task.configureWith
import timber.log.Timber
/**
@@ -35,7 +35,6 @@ import timber.log.Timber
*/
internal class DefaultTypingService @AssistedInject constructor(
@Assisted private val roomId: String,
- private val taskExecutor: TaskExecutor,
private val sendTypingTask: SendTypingTask
) : TypingService {
@@ -44,8 +43,8 @@ internal class DefaultTypingService @AssistedInject constructor(
fun create(roomId: String): DefaultTypingService
}
- private var currentTask: Cancelable? = null
- private var currentAutoStopTask: Cancelable? = null
+ private val coroutineScope = CoroutineScope(Job())
+ private var currentTask: Job? = null
// What the homeserver knows
private var userIsTyping = false
@@ -53,26 +52,24 @@ internal class DefaultTypingService @AssistedInject constructor(
// Last time the user is typing event has been sent
private var lastRequestTimestamp: Long = 0
+ /**
+ * Notify to the server that the user is typing and schedule the auto typing off
+ */
override fun userIsTyping() {
- scheduleAutoStop()
-
val now = SystemClock.elapsedRealtime()
-
- if (userIsTyping && now < lastRequestTimestamp + MIN_DELAY_BETWEEN_TWO_USER_IS_TYPING_REQUESTS_MILLIS) {
- Timber.d("Typing: Skip start request")
- return
- }
-
- Timber.d("Typing: Send start request")
- userIsTyping = true
- lastRequestTimestamp = now
-
currentTask?.cancel()
-
- val params = SendTypingTask.Params(roomId, true)
- currentTask = sendTypingTask
- .configureWith(params)
- .executeBy(taskExecutor)
+ currentTask = coroutineScope.launch {
+ if (userIsTyping && now < lastRequestTimestamp + MIN_DELAY_BETWEEN_TWO_USER_IS_TYPING_REQUESTS_MILLIS) {
+ Timber.d("Typing: Skip start request")
+ } else {
+ Timber.d("Typing: Send start request")
+ lastRequestTimestamp = now
+ sendRequest(true)
+ }
+ delay(MIN_DELAY_TO_SEND_STOP_TYPING_REQUEST_WHEN_NO_USER_ACTIVITY_MILLIS)
+ Timber.d("Typing: auto stop")
+ sendRequest(false)
+ }
}
override fun userStopsTyping() {
@@ -82,35 +79,22 @@ internal class DefaultTypingService @AssistedInject constructor(
}
Timber.d("Typing: Send stop request")
- userIsTyping = false
lastRequestTimestamp = 0
- currentAutoStopTask?.cancel()
currentTask?.cancel()
-
- val params = SendTypingTask.Params(roomId, false)
- currentTask = sendTypingTask
- .configureWith(params)
- .executeBy(taskExecutor)
+ currentTask = coroutineScope.launch {
+ sendRequest(false)
+ }
}
- private fun scheduleAutoStop() {
- Timber.d("Typing: Schedule auto stop")
- currentAutoStopTask?.cancel()
-
- val params = SendTypingTask.Params(
- roomId,
- false,
- delay = MIN_DELAY_TO_SEND_STOP_TYPING_REQUEST_WHEN_NO_USER_ACTIVITY_MILLIS)
- currentAutoStopTask = sendTypingTask
- .configureWith(params) {
- callback = object : MatrixCallback {
- override fun onSuccess(data: Unit) {
- userIsTyping = false
- }
- }
- }
- .executeBy(taskExecutor)
+ private suspend fun sendRequest(isTyping: Boolean) {
+ try {
+ sendTypingTask.execute(SendTypingTask.Params(roomId, isTyping))
+ userIsTyping = isTyping
+ } catch (failure: Throwable) {
+ // Ignore network error, etc...
+ Timber.w(failure, "Unable to send typing request")
+ }
}
companion object {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/typing/SendTypingTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/typing/SendTypingTask.kt
index 0b0df74311..0bdceb9ade 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/typing/SendTypingTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/typing/SendTypingTask.kt
@@ -17,11 +17,10 @@
package org.matrix.android.sdk.internal.session.room.typing
import org.matrix.android.sdk.internal.di.UserId
+import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
import org.matrix.android.sdk.internal.network.executeRequest
import org.matrix.android.sdk.internal.session.room.RoomAPI
import org.matrix.android.sdk.internal.task.Task
-import kotlinx.coroutines.delay
-import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
import javax.inject.Inject
internal interface SendTypingTask : Task {
@@ -29,9 +28,7 @@ internal interface SendTypingTask : Task {
data class Params(
val roomId: String,
val isTyping: Boolean,
- val typingTimeoutMillis: Int? = 30_000,
- // Optional delay before sending the request to the homeserver
- val delay: Long? = null
+ val typingTimeoutMillis: Int? = 30_000
)
}
@@ -42,8 +39,6 @@ internal class DefaultSendTypingTask @Inject constructor(
) : SendTypingTask {
override suspend fun execute(params: SendTypingTask.Params) {
- delay(params.delay ?: -1)
-
executeRequest(globalErrorReceiver) {
roomAPI.sendTypingState(
params.roomId,
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/UserAccountDataSyncHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/UserAccountDataSyncHandler.kt
index 3aebd90ed2..b8d987d500 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/UserAccountDataSyncHandler.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/UserAccountDataSyncHandler.kt
@@ -23,7 +23,7 @@ import io.realm.kotlin.where
import org.matrix.android.sdk.api.pushrules.RuleScope
import org.matrix.android.sdk.api.pushrules.RuleSetKey
import org.matrix.android.sdk.api.pushrules.rest.GetPushRulesResponse
-import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent
+import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes
import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.session.events.model.toModel
@@ -113,7 +113,7 @@ internal class UserAccountDataSyncHandler @Inject constructor(
}
}
- private fun handlePushRules(realm: Realm, event: AccountDataEvent) {
+ private fun handlePushRules(realm: Realm, event: UserAccountDataEvent) {
val pushRules = event.content.toModel() ?: return
realm.where(PushRulesEntity::class.java)
.findAll()
@@ -155,7 +155,7 @@ internal class UserAccountDataSyncHandler @Inject constructor(
realm.insertOrUpdate(underrides)
}
- private fun handleDirectChatRooms(realm: Realm, event: AccountDataEvent) {
+ private fun handleDirectChatRooms(realm: Realm, event: UserAccountDataEvent) {
val content = event.content.toModel() ?: return
content.forEach { (userId, roomIds) ->
roomIds.forEach { roomId ->
@@ -181,7 +181,7 @@ internal class UserAccountDataSyncHandler @Inject constructor(
}
}
- private fun handleIgnoredUsers(realm: Realm, event: AccountDataEvent) {
+ private fun handleIgnoredUsers(realm: Realm, event: UserAccountDataEvent) {
val userIds = event.content.toModel()?.ignoredUsers?.keys ?: return
realm.where(IgnoredUserEntity::class.java)
.findAll()
@@ -191,7 +191,7 @@ internal class UserAccountDataSyncHandler @Inject constructor(
// TODO If not initial sync, we should execute a init sync
}
- private fun handleBreadcrumbs(realm: Realm, event: AccountDataEvent) {
+ private fun handleBreadcrumbs(realm: Realm, event: UserAccountDataEvent) {
val recentRoomIds = event.content.toModel()?.recentRoomIds ?: return
val entity = BreadcrumbsEntity.getOrCreate(realm)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/model/accountdata/UserAccountDataSync.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/model/accountdata/UserAccountDataSync.kt
index ddb71cd19f..05b50ab2c5 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/model/accountdata/UserAccountDataSync.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/model/accountdata/UserAccountDataSync.kt
@@ -18,9 +18,9 @@ package org.matrix.android.sdk.internal.session.sync.model.accountdata
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
-import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent
+import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
@JsonClass(generateAdapter = true)
internal data class UserAccountDataSync(
- @Json(name = "events") val list: List = emptyList()
+ @Json(name = "events") val list: List = emptyList()
)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/parsing/RoomSyncAccountDataHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/parsing/RoomSyncAccountDataHandler.kt
index c8aab586a0..8bf9ad5b90 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/parsing/RoomSyncAccountDataHandler.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/parsing/RoomSyncAccountDataHandler.kt
@@ -56,7 +56,6 @@ internal class RoomSyncAccountDataHandler @Inject constructor(private val roomTa
private fun handleGeneric(roomEntity: RoomEntity, content: JsonDict?, eventType: String) {
val existing = roomEntity.accountData.where().equalTo(RoomAccountDataEntityFields.TYPE, eventType).findFirst()
if (existing != null) {
- // Update current value
existing.contentStr = ContentMapper.map(content)
} else {
val roomAccountData = RoomAccountDataEntity(
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UserAccountDataService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/DefaultSessionAccountDataService.kt
similarity index 55%
rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UserAccountDataService.kt
rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/DefaultSessionAccountDataService.kt
index b15d1d0f8b..ff1750ce8e 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UserAccountDataService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/DefaultSessionAccountDataService.kt
@@ -18,42 +18,53 @@ package org.matrix.android.sdk.internal.session.user.accountdata
import androidx.lifecycle.LiveData
import com.zhuinden.monarchy.Monarchy
-import org.matrix.android.sdk.api.session.accountdata.AccountDataService
+import org.matrix.android.sdk.api.session.accountdata.SessionAccountDataService
import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.util.Optional
import org.matrix.android.sdk.internal.di.SessionDatabase
import org.matrix.android.sdk.internal.session.sync.UserAccountDataSyncHandler
-import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent
+import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
+import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataEvent
+import org.matrix.android.sdk.internal.session.room.accountdata.RoomAccountDataDataSource
import org.matrix.android.sdk.internal.task.TaskExecutor
import org.matrix.android.sdk.internal.task.configureWith
import org.matrix.android.sdk.internal.util.awaitCallback
import javax.inject.Inject
-internal class UserAccountDataService @Inject constructor(
+internal class DefaultSessionAccountDataService @Inject constructor(
@SessionDatabase private val monarchy: Monarchy,
private val updateUserAccountDataTask: UpdateUserAccountDataTask,
private val userAccountDataSyncHandler: UserAccountDataSyncHandler,
- private val accountDataDataSource: UserAccountDataDataSource,
+ private val userAccountDataDataSource: UserAccountDataDataSource,
+ private val roomAccountDataDataSource: RoomAccountDataDataSource,
private val taskExecutor: TaskExecutor
-) : AccountDataService {
+) : SessionAccountDataService {
- override fun getAccountDataEvent(type: String): AccountDataEvent? {
- return accountDataDataSource.getAccountDataEvent(type)
+ override fun getUserAccountDataEvent(type: String): UserAccountDataEvent? {
+ return userAccountDataDataSource.getAccountDataEvent(type)
}
- override fun getLiveAccountDataEvent(type: String): LiveData> {
- return accountDataDataSource.getLiveAccountDataEvent(type)
+ override fun getLiveUserAccountDataEvent(type: String): LiveData> {
+ return userAccountDataDataSource.getLiveAccountDataEvent(type)
}
- override fun getAccountDataEvents(types: Set): List {
- return accountDataDataSource.getAccountDataEvents(types)
+ override fun getUserAccountDataEvents(types: Set): List {
+ return userAccountDataDataSource.getAccountDataEvents(types)
}
- override fun getLiveAccountDataEvents(types: Set): LiveData> {
- return accountDataDataSource.getLiveAccountDataEvents(types)
+ override fun getLiveUserAccountDataEvents(types: Set): LiveData> {
+ return userAccountDataDataSource.getLiveAccountDataEvents(types)
}
- override suspend fun updateAccountData(type: String, content: Content) {
+ override fun getRoomAccountDataEvents(types: Set): List {
+ return roomAccountDataDataSource.getAccountDataEvents(null, types)
+ }
+
+ override fun getLiveRoomAccountDataEvents(types: Set): LiveData> {
+ return roomAccountDataDataSource.getLiveAccountDataEvents(null, types)
+ }
+
+ override suspend fun updateUserAccountData(type: String, content: Content) {
val params = UpdateUserAccountDataTask.AnyParams(type = type, any = content)
awaitCallback { callback ->
updateUserAccountDataTask.configureWith(params) {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UserAccountDataDataSource.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UserAccountDataDataSource.kt
index f64b1bdd2e..b36bdc80f8 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UserAccountDataDataSource.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UserAccountDataDataSource.kt
@@ -21,7 +21,7 @@ import androidx.lifecycle.Transformations
import com.zhuinden.monarchy.Monarchy
import io.realm.Realm
import io.realm.RealmQuery
-import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent
+import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import org.matrix.android.sdk.api.util.Optional
import org.matrix.android.sdk.api.util.toOptional
import org.matrix.android.sdk.internal.database.RealmSessionProvider
@@ -35,23 +35,23 @@ internal class UserAccountDataDataSource @Inject constructor(@SessionDatabase pr
private val realmSessionProvider: RealmSessionProvider,
private val accountDataMapper: AccountDataMapper) {
- fun getAccountDataEvent(type: String): AccountDataEvent? {
+ fun getAccountDataEvent(type: String): UserAccountDataEvent? {
return getAccountDataEvents(setOf(type)).firstOrNull()
}
- fun getLiveAccountDataEvent(type: String): LiveData> {
+ fun getLiveAccountDataEvent(type: String): LiveData> {
return Transformations.map(getLiveAccountDataEvents(setOf(type))) {
it.firstOrNull()?.toOptional()
}
}
- fun getAccountDataEvents(types: Set): List {
+ fun getAccountDataEvents(types: Set): List {
return realmSessionProvider.withRealm {
accountDataEventsQuery(it, types).findAll().map(accountDataMapper::map)
}
}
- fun getLiveAccountDataEvents(types: Set): LiveData> {
+ fun getLiveAccountDataEvents(types: Set): LiveData> {
return monarchy.findAllMappedWithChanges(
{ accountDataEventsQuery(it, types) },
accountDataMapper::map
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/WidgetManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/WidgetManager.kt
index ca1a129da7..e0f43a11c5 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/WidgetManager.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/WidgetManager.kt
@@ -23,7 +23,7 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.Transformations
import org.matrix.android.sdk.api.query.QueryStringValue
import org.matrix.android.sdk.api.session.Session
-import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent
+import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes
import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.session.events.model.Event
@@ -47,7 +47,7 @@ import javax.inject.Inject
@SessionScope
internal class WidgetManager @Inject constructor(private val integrationManager: IntegrationManager,
- private val accountDataDataSource: UserAccountDataDataSource,
+ private val userAccountDataDataSource: UserAccountDataDataSource,
private val stateEventDataSource: StateEventDataSource,
private val createWidgetTask: CreateWidgetTask,
private val widgetFactory: WidgetFactory,
@@ -136,7 +136,7 @@ internal class WidgetManager @Inject constructor(private val integrationManager:
widgetTypes: Set? = null,
excludedTypes: Set? = null
): LiveData> {
- val widgetsAccountData = accountDataDataSource.getLiveAccountDataEvent(UserAccountDataTypes.TYPE_WIDGETS)
+ val widgetsAccountData = userAccountDataDataSource.getLiveAccountDataEvent(UserAccountDataTypes.TYPE_WIDGETS)
return Transformations.map(widgetsAccountData) {
it.getOrNull()?.mapToWidgets(widgetTypes, excludedTypes).orEmpty()
}
@@ -146,12 +146,12 @@ internal class WidgetManager @Inject constructor(private val integrationManager:
widgetTypes: Set? = null,
excludedTypes: Set? = null
): List {
- val widgetsAccountData = accountDataDataSource.getAccountDataEvent(UserAccountDataTypes.TYPE_WIDGETS) ?: return emptyList()
+ val widgetsAccountData = userAccountDataDataSource.getAccountDataEvent(UserAccountDataTypes.TYPE_WIDGETS) ?: return emptyList()
return widgetsAccountData.mapToWidgets(widgetTypes, excludedTypes)
}
- private fun AccountDataEvent.mapToWidgets(widgetTypes: Set? = null,
- excludedTypes: Set? = null): List {
+ private fun UserAccountDataEvent.mapToWidgets(widgetTypes: Set? = null,
+ excludedTypes: Set? = null): List {
return extractWidgetSequence(widgetFactory)
.filter {
val widgetType = it.widgetContent.type ?: return@filter false
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/helper/UserAccountWidgets.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/helper/UserAccountWidgets.kt
index 5aa32d5a31..6f423b38a0 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/helper/UserAccountWidgets.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/helper/UserAccountWidgets.kt
@@ -19,10 +19,10 @@ package org.matrix.android.sdk.internal.session.widgets.helper
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.util.JsonDict
-import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent
+import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import org.matrix.android.sdk.api.session.widgets.model.Widget
-internal fun AccountDataEvent.extractWidgetSequence(widgetFactory: WidgetFactory): Sequence {
+internal fun UserAccountDataEvent.extractWidgetSequence(widgetFactory: WidgetFactory): Sequence {
return content.asSequence()
.mapNotNull {
@Suppress("UNCHECKED_CAST")
diff --git a/newsfragment/2449.feature b/newsfragment/2449.feature
new file mode 100644
index 0000000000..7fca1730b6
--- /dev/null
+++ b/newsfragment/2449.feature
@@ -0,0 +1 @@
+Migrate DefaultTypingService, KeysImporter and KeysExporter to coroutines
\ No newline at end of file
diff --git a/newsfragment/3182.feature b/newsfragment/3182.feature
new file mode 100644
index 0000000000..83eee3c29c
--- /dev/null
+++ b/newsfragment/3182.feature
@@ -0,0 +1 @@
+Update Message Composer design
\ No newline at end of file
diff --git a/newsfragment/3435.feature b/newsfragment/3435.feature
new file mode 100644
index 0000000000..222092924d
--- /dev/null
+++ b/newsfragment/3435.feature
@@ -0,0 +1 @@
+Cleanup Epoxy items, and debounce all the clicks
\ No newline at end of file
diff --git a/newsfragment/3459.feature b/newsfragment/3459.feature
new file mode 100644
index 0000000000..eedec1dfda
--- /dev/null
+++ b/newsfragment/3459.feature
@@ -0,0 +1,2 @@
+Migrate to new colors and cleanup the style and theme
+Ref: https://material.io/blog/migrate-android-material-components
\ No newline at end of file
diff --git a/newsfragment/3467.misc b/newsfragment/3467.misc
new file mode 100644
index 0000000000..b726da2353
--- /dev/null
+++ b/newsfragment/3467.misc
@@ -0,0 +1 @@
+VoIP: Change hold direction to send-only.
\ No newline at end of file
diff --git a/newsfragment/3479.removal b/newsfragment/3479.removal
new file mode 100644
index 0000000000..f492a13f58
--- /dev/null
+++ b/newsfragment/3479.removal
@@ -0,0 +1 @@
+Splits SessionAccountDataService and RoomAccountDataService and offers to query RoomAccountDataEvent at the session level.
\ No newline at end of file
diff --git a/tools/check/forbidden_strings_in_code.txt b/tools/check/forbidden_strings_in_code.txt
index 9770ed0d4d..e0645e00b3 100644
--- a/tools/check/forbidden_strings_in_code.txt
+++ b/tools/check/forbidden_strings_in_code.txt
@@ -136,8 +136,9 @@ android\.R\.id\.home===2
### Kotlin conversion tools introduce this, but is can be replace by trim()
trim \{ it \<\= \' \' \}
-### Use AlertDialog form v7 compat lib
+### Use MaterialAlertDialogBuilder
android\.app\.AlertDialog
+androidx\.appcompat\.app\.AlertDialog===4
### Put the operator at the beginning of next line
&&$
diff --git a/tools/check/forbidden_strings_in_resources.txt b/tools/check/forbidden_strings_in_resources.txt
index cefeeb6351..92eec6cdfd 100644
--- a/tools/check/forbidden_strings_in_resources.txt
+++ b/tools/check/forbidden_strings_in_resources.txt
@@ -84,3 +84,22 @@ layout_constraintLeft_
### Use androidx.recyclerview.widget.RecyclerView because EpoxyRecyclerViews add behavior we do not want to
+
+
+
+
+
diff --git a/vector/src/debug/java/im/vector/app/features/debug/DebugBottomSheet.kt b/vector/src/debug/java/im/vector/app/features/debug/DebugBottomSheet.kt
new file mode 100644
index 0000000000..0ac9a894ae
--- /dev/null
+++ b/vector/src/debug/java/im/vector/app/features/debug/DebugBottomSheet.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2021 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.debug
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment
+import im.vector.app.databinding.ActivityTestMaterialThemeBinding
+
+class DebugBottomSheet : BottomSheetDialogFragment() {
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ // Reuse tha Activity layout
+ val binding = ActivityTestMaterialThemeBinding.inflate(inflater, container, false)
+ return binding.root
+ }
+}
diff --git a/vector/src/debug/java/im/vector/app/features/debug/DebugMaterialThemeActivity.kt b/vector/src/debug/java/im/vector/app/features/debug/DebugMaterialThemeActivity.kt
index 8df1feab1e..de6b981c02 100644
--- a/vector/src/debug/java/im/vector/app/features/debug/DebugMaterialThemeActivity.kt
+++ b/vector/src/debug/java/im/vector/app/features/debug/DebugMaterialThemeActivity.kt
@@ -18,9 +18,8 @@ package im.vector.app.features.debug
import android.os.Bundle
import android.view.Menu
-import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
-import com.google.android.material.bottomsheet.BottomSheetDialogFragment
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar
import im.vector.app.R
import im.vector.app.core.utils.toast
@@ -45,7 +44,8 @@ abstract class DebugMaterialThemeActivity : AppCompatActivity() {
}
views.debugShowDialog.setOnClickListener {
- AlertDialog.Builder(this)
+ MaterialAlertDialogBuilder(this)
+ .setTitle("Dialog title")
.setMessage("Dialog content")
.setIcon(R.drawable.ic_settings_x)
.setPositiveButton("Positive", null)
@@ -55,7 +55,7 @@ abstract class DebugMaterialThemeActivity : AppCompatActivity() {
}
views.debugShowBottomSheet.setOnClickListener {
- BottomSheetDialogFragment().show(supportFragmentManager, "TAG")
+ DebugBottomSheet().show(supportFragmentManager, "TAG")
}
}
diff --git a/vector/src/debug/java/im/vector/app/features/debug/DebugMaterialThemeDarkDefaultActivity.kt b/vector/src/debug/java/im/vector/app/features/debug/DebugMaterialThemeDarkDefaultActivity.kt
new file mode 100644
index 0000000000..7e014577de
--- /dev/null
+++ b/vector/src/debug/java/im/vector/app/features/debug/DebugMaterialThemeDarkDefaultActivity.kt
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2019 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.debug
+
+class DebugMaterialThemeDarkDefaultActivity : DebugMaterialThemeActivity()
diff --git a/vector/src/debug/java/im/vector/app/features/debug/DebugMaterialThemeDarkActivity.kt b/vector/src/debug/java/im/vector/app/features/debug/DebugMaterialThemeDarkTestActivity.kt
similarity index 89%
rename from vector/src/debug/java/im/vector/app/features/debug/DebugMaterialThemeDarkActivity.kt
rename to vector/src/debug/java/im/vector/app/features/debug/DebugMaterialThemeDarkTestActivity.kt
index e6e1bf04ee..4a1ed04f6a 100644
--- a/vector/src/debug/java/im/vector/app/features/debug/DebugMaterialThemeDarkActivity.kt
+++ b/vector/src/debug/java/im/vector/app/features/debug/DebugMaterialThemeDarkTestActivity.kt
@@ -16,4 +16,4 @@
package im.vector.app.features.debug
-class DebugMaterialThemeDarkActivity : DebugMaterialThemeActivity()
+class DebugMaterialThemeDarkTestActivity : DebugMaterialThemeActivity()
diff --git a/vector/src/debug/java/im/vector/app/features/debug/DebugMaterialThemeDarkVectorActivity.kt b/vector/src/debug/java/im/vector/app/features/debug/DebugMaterialThemeDarkVectorActivity.kt
new file mode 100644
index 0000000000..6ac27aed45
--- /dev/null
+++ b/vector/src/debug/java/im/vector/app/features/debug/DebugMaterialThemeDarkVectorActivity.kt
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2019 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.debug
+
+class DebugMaterialThemeDarkVectorActivity : DebugMaterialThemeActivity()
diff --git a/vector/src/debug/java/im/vector/app/features/debug/DebugMaterialThemeLightDefaultActivity.kt b/vector/src/debug/java/im/vector/app/features/debug/DebugMaterialThemeLightDefaultActivity.kt
new file mode 100644
index 0000000000..f6327e363b
--- /dev/null
+++ b/vector/src/debug/java/im/vector/app/features/debug/DebugMaterialThemeLightDefaultActivity.kt
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2019 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.debug
+
+class DebugMaterialThemeLightDefaultActivity : DebugMaterialThemeActivity()
diff --git a/vector/src/debug/java/im/vector/app/features/debug/DebugMaterialThemeLightActivity.kt b/vector/src/debug/java/im/vector/app/features/debug/DebugMaterialThemeLightTestActivity.kt
similarity index 89%
rename from vector/src/debug/java/im/vector/app/features/debug/DebugMaterialThemeLightActivity.kt
rename to vector/src/debug/java/im/vector/app/features/debug/DebugMaterialThemeLightTestActivity.kt
index d1d3061cad..ae6c1dd68c 100644
--- a/vector/src/debug/java/im/vector/app/features/debug/DebugMaterialThemeLightActivity.kt
+++ b/vector/src/debug/java/im/vector/app/features/debug/DebugMaterialThemeLightTestActivity.kt
@@ -16,4 +16,4 @@
package im.vector.app.features.debug
-class DebugMaterialThemeLightActivity : DebugMaterialThemeActivity()
+class DebugMaterialThemeLightTestActivity : DebugMaterialThemeActivity()
diff --git a/vector/src/debug/java/im/vector/app/features/debug/DebugMaterialThemeLightVectorActivity.kt b/vector/src/debug/java/im/vector/app/features/debug/DebugMaterialThemeLightVectorActivity.kt
new file mode 100644
index 0000000000..b4fb3c1cc8
--- /dev/null
+++ b/vector/src/debug/java/im/vector/app/features/debug/DebugMaterialThemeLightVectorActivity.kt
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2019 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.debug
+
+class DebugMaterialThemeLightVectorActivity : DebugMaterialThemeActivity()
diff --git a/vector/src/debug/java/im/vector/app/features/debug/DebugMenuActivity.kt b/vector/src/debug/java/im/vector/app/features/debug/DebugMenuActivity.kt
index 8699b238ec..65a24c9aeb 100644
--- a/vector/src/debug/java/im/vector/app/features/debug/DebugMenuActivity.kt
+++ b/vector/src/debug/java/im/vector/app/features/debug/DebugMenuActivity.kt
@@ -71,10 +71,29 @@ class DebugMenuActivity : VectorBaseActivity() {
private fun setupViews() {
views.debugTestTextViewLink.setOnClickListener { testTextViewLink() }
+ views.debugOpenButtonStyles.setOnClickListener {
+ startActivity(Intent(this, DebugVectorButtonStylesActivity::class.java))
+ }
views.debugShowSasEmoji.setOnClickListener { showSasEmoji() }
views.debugTestNotification.setOnClickListener { testNotification() }
- views.debugTestMaterialThemeLight.setOnClickListener { testMaterialThemeLight() }
- views.debugTestMaterialThemeDark.setOnClickListener { testMaterialThemeDark() }
+ views.debugTestMaterialThemeLightDefault.setOnClickListener {
+ startActivity(Intent(this, DebugMaterialThemeLightDefaultActivity::class.java))
+ }
+ views.debugTestMaterialThemeLightTest.setOnClickListener {
+ startActivity(Intent(this, DebugMaterialThemeLightTestActivity::class.java))
+ }
+ views.debugTestMaterialThemeLightVector.setOnClickListener {
+ startActivity(Intent(this, DebugMaterialThemeLightVectorActivity::class.java))
+ }
+ views.debugTestMaterialThemeDarkDefault.setOnClickListener {
+ startActivity(Intent(this, DebugMaterialThemeDarkDefaultActivity::class.java))
+ }
+ views.debugTestMaterialThemeDarkTest.setOnClickListener {
+ startActivity(Intent(this, DebugMaterialThemeDarkTestActivity::class.java))
+ }
+ views.debugTestMaterialThemeDarkVector.setOnClickListener {
+ startActivity(Intent(this, DebugMaterialThemeDarkVectorActivity::class.java))
+ }
views.debugTestCrash.setOnClickListener { testCrash() }
views.debugScanQrCode.setOnClickListener { scanQRCode() }
}
@@ -174,14 +193,6 @@ class DebugMenuActivity : VectorBaseActivity() {
)
}
- private fun testMaterialThemeLight() {
- startActivity(Intent(this, DebugMaterialThemeLightActivity::class.java))
- }
-
- private fun testMaterialThemeDark() {
- startActivity(Intent(this, DebugMaterialThemeDarkActivity::class.java))
- }
-
private fun testCrash() {
throw RuntimeException("Application crashed from user demand")
}
diff --git a/vector/src/debug/java/im/vector/app/features/debug/DebugVectorButtonStylesActivity.kt b/vector/src/debug/java/im/vector/app/features/debug/DebugVectorButtonStylesActivity.kt
new file mode 100644
index 0000000000..783a2a3eb5
--- /dev/null
+++ b/vector/src/debug/java/im/vector/app/features/debug/DebugVectorButtonStylesActivity.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2021 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.debug
+
+import im.vector.app.core.platform.VectorBaseActivity
+import im.vector.app.databinding.ActivityDebugButtonStylesBinding
+
+class DebugVectorButtonStylesActivity : VectorBaseActivity() {
+ override fun getBinding() = ActivityDebugButtonStylesBinding.inflate(layoutInflater)
+}
diff --git a/vector/src/debug/res/layout/activity_debug_button_styles.xml b/vector/src/debug/res/layout/activity_debug_button_styles.xml
new file mode 100644
index 0000000000..3973f7cbb6
--- /dev/null
+++ b/vector/src/debug/res/layout/activity_debug_button_styles.xml
@@ -0,0 +1,131 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vector/src/debug/res/layout/activity_debug_menu.xml b/vector/src/debug/res/layout/activity_debug_menu.xml
index 6a41488987..454d8992fd 100644
--- a/vector/src/debug/res/layout/activity_debug_menu.xml
+++ b/vector/src/debug/res/layout/activity_debug_menu.xml
@@ -20,51 +20,106 @@
android:padding="@dimen/layout_horizontal_margin"
android:showDividers="middle">
-
-
-
+ android:text="Light theme" />
-
+
+
+
+
+
+
+
+
+
+ android:text="Dark theme" />
-
+
+
+
+
+
+
+
+
+
+
+
-
-
diff --git a/vector/src/debug/res/layout/activity_test_material_theme.xml b/vector/src/debug/res/layout/activity_test_material_theme.xml
index 21a2d3fbf5..2ec23a4b31 100644
--- a/vector/src/debug/res/layout/activity_test_material_theme.xml
+++ b/vector/src/debug/res/layout/activity_test_material_theme.xml
@@ -5,7 +5,6 @@
android:id="@+id/coordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="vertical"
tools:context=".features.debug.DebugMaterialThemeActivity"
tools:ignore="HardcodedText">
@@ -28,6 +27,229 @@
app:subtitle="Toolbar Subtitle"
app:title="Toolbar Title" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
+
+
-
+
+
-
+
+
+
+
-
-
-
-
@@ -146,7 +413,8 @@
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal">
+
+
diff --git a/vector/src/debug/res/layout/demo_themes.xml b/vector/src/debug/res/layout/demo_themes.xml
index ba970d699c..7cd4a77066 100644
--- a/vector/src/debug/res/layout/demo_themes.xml
+++ b/vector/src/debug/res/layout/demo_themes.xml
@@ -8,8 +8,7 @@
+ android:orientation="vertical">
diff --git a/vector/src/debug/res/layout/item_test_linkify.xml b/vector/src/debug/res/layout/item_test_linkify.xml
index 89d1dade0d..a6062256a3 100644
--- a/vector/src/debug/res/layout/item_test_linkify.xml
+++ b/vector/src/debug/res/layout/item_test_linkify.xml
@@ -1,5 +1,5 @@
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/vector/src/debug/res/values/styles.xml b/vector/src/debug/res/values/styles.xml
index 063f652d08..090de4dd4b 100644
--- a/vector/src/debug/res/values/styles.xml
+++ b/vector/src/debug/res/values/styles.xml
@@ -7,6 +7,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/app/core/animations/behavior/PercentViewBehavior.kt b/vector/src/main/java/im/vector/app/core/animations/behavior/PercentViewBehavior.kt
deleted file mode 100644
index 8b42485cb6..0000000000
--- a/vector/src/main/java/im/vector/app/core/animations/behavior/PercentViewBehavior.kt
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright 2020 New Vector Ltd
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package im.vector.app.core.animations.behavior
-
-import android.animation.ArgbEvaluator
-import android.content.Context
-import android.graphics.drawable.ColorDrawable
-import android.util.AttributeSet
-import android.view.View
-import androidx.coordinatorlayout.widget.CoordinatorLayout
-import androidx.core.content.withStyledAttributes
-
-import im.vector.app.R
-import kotlin.math.abs
-
-private const val UNSPECIFIED_INT = Integer.MAX_VALUE
-private val UNSPECIFIED_FLOAT = Float.MAX_VALUE
-private const val DEPEND_TYPE_HEIGHT = 0
-private const val DEPEND_TYPE_WIDTH = 1
-private const val DEPEND_TYPE_X = 2
-private const val DEPEND_TYPE_Y = 3
-
-class PercentViewBehavior(context: Context, attrs: AttributeSet) : CoordinatorLayout.Behavior(context, attrs) {
-
- private var dependType: Int = 0
- private var dependViewId: Int = 0
- private var dependTarget: Int = 0
- private var dependStartX: Int = 0
- private var dependStartY: Int = 0
- private var dependStartWidth: Int = 0
- private var dependStartHeight: Int = 0
-
- private var startX: Int = 0
- private var startY: Int = 0
- private var startWidth: Int = 0
- private var startHeight: Int = 0
- private var startBackgroundColor: Int = 0
- private var startAlpha: Float = 0f
- private var startRotateX: Float = 0f
- private var startRotateY: Float = 0f
-
- private var targetX: Int = 0
- private var targetY: Int = 0
- private var targetWidth: Int = 0
- private var targetHeight: Int = 0
- private var targetBackgroundColor: Int = 0
- private var targetAlpha: Float = 0f
- private var targetRotateX: Float = 0f
- private var targetRotateY: Float = 0f
-
- /**
- * Is the values prepared to be use
- */
- private var isPrepared: Boolean = false
-
- init {
- context.withStyledAttributes(attrs, R.styleable.PercentViewBehavior) {
- dependViewId = getResourceId(R.styleable.PercentViewBehavior_behavior_dependsOn, 0)
- dependType = getInt(R.styleable.PercentViewBehavior_behavior_dependType, DEPEND_TYPE_WIDTH)
- dependTarget = getDimensionPixelOffset(R.styleable.PercentViewBehavior_behavior_dependTarget, UNSPECIFIED_INT)
- targetX = getDimensionPixelOffset(R.styleable.PercentViewBehavior_behavior_targetX, UNSPECIFIED_INT)
- targetY = getDimensionPixelOffset(R.styleable.PercentViewBehavior_behavior_targetY, UNSPECIFIED_INT)
- targetWidth = getDimensionPixelOffset(R.styleable.PercentViewBehavior_behavior_targetWidth, UNSPECIFIED_INT)
- targetHeight = getDimensionPixelOffset(R.styleable.PercentViewBehavior_behavior_targetHeight, UNSPECIFIED_INT)
- targetBackgroundColor = getColor(R.styleable.PercentViewBehavior_behavior_targetBackgroundColor, UNSPECIFIED_INT)
- targetAlpha = getFloat(R.styleable.PercentViewBehavior_behavior_targetAlpha, UNSPECIFIED_FLOAT)
- targetRotateX = getFloat(R.styleable.PercentViewBehavior_behavior_targetRotateX, UNSPECIFIED_FLOAT)
- targetRotateY = getFloat(R.styleable.PercentViewBehavior_behavior_targetRotateY, UNSPECIFIED_FLOAT)
- }
- }
-
- private fun prepare(parent: CoordinatorLayout, child: View, dependency: View) {
- dependStartX = dependency.x.toInt()
- dependStartY = dependency.y.toInt()
- dependStartWidth = dependency.width
- dependStartHeight = dependency.height
- startX = child.x.toInt()
- startY = child.y.toInt()
- startWidth = child.width
- startHeight = child.height
- startAlpha = child.alpha
- startRotateX = child.rotationX
- startRotateY = child.rotationY
-
- // only set the start background color when the background is color drawable
- val background = child.background
- if (background is ColorDrawable) {
- startBackgroundColor = background.color
- }
-
- // if parent fitsSystemWindows is true, add status bar height to target y if specified
- if (parent.fitsSystemWindows && targetY != UNSPECIFIED_INT) {
- var result = 0
- val resources = parent.context.resources
- val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android")
- if (resourceId > 0) {
- result = resources.getDimensionPixelSize(resourceId)
- }
- targetY += result
- }
- isPrepared = true
- }
-
- override fun layoutDependsOn(parent: CoordinatorLayout, child: V, dependency: View): Boolean {
- return dependency.id == dependViewId
- }
-
- override fun onDependentViewChanged(parent: CoordinatorLayout, child: V, dependency: View): Boolean {
- // first time, prepare values before continue
- if (!isPrepared) {
- prepare(parent, child, dependency)
- }
- updateView(child, dependency)
- return false
- }
-
- override fun onLayoutChild(parent: CoordinatorLayout, child: V, layoutDirection: Int): Boolean {
- val bool = super.onLayoutChild(parent, child, layoutDirection)
- if (isPrepared) {
- updateView(child, parent.getDependencies(child)[0])
- }
- return bool
- }
-
- /**
- * Update the child view from the dependency states
- *
- * @param child child view
- * @param dependency dependency view
- */
- private fun updateView(child: V, dependency: View) {
- var percent = 0f
- var start = 0f
- var current = 0f
- var end = UNSPECIFIED_INT.toFloat()
- when (dependType) {
- DEPEND_TYPE_WIDTH -> {
- start = dependStartWidth.toFloat()
- current = dependency.width.toFloat()
- end = dependTarget.toFloat()
- }
- DEPEND_TYPE_HEIGHT -> {
- start = dependStartHeight.toFloat()
- current = dependency.height.toFloat()
- end = dependTarget.toFloat()
- }
- DEPEND_TYPE_X -> {
- start = dependStartX.toFloat()
- current = dependency.x
- end = dependTarget.toFloat()
- }
- DEPEND_TYPE_Y -> {
- start = dependStartY.toFloat()
- current = dependency.y
- end = dependTarget.toFloat()
- }
- }
-
- // need to define target value according to the depend type, if not then skip
- if (end != UNSPECIFIED_INT.toFloat()) {
- percent = abs(current - start) / abs(end - start)
- }
- updateViewWithPercent(child, if (percent > 1f) 1f else percent)
- }
-
- private fun updateViewWithPercent(child: View, percent: Float) {
- var newX = if (targetX == UNSPECIFIED_INT) 0f else (targetX - startX) * percent
- var newY = if (targetY == UNSPECIFIED_INT) 0f else (targetY - startY) * percent
-
- // set scale
- if (targetWidth != UNSPECIFIED_INT) {
- val newWidth = startWidth + (targetWidth - startWidth) * percent
- child.scaleX = newWidth / startWidth
- newX -= (startWidth - newWidth) / 2
- }
- if (targetHeight != UNSPECIFIED_INT) {
- val newHeight = startHeight + (targetHeight - startHeight) * percent
- child.scaleY = newHeight / startHeight
- newY -= (startHeight - newHeight) / 2
- }
-
- // set new position
- child.translationX = newX
- child.translationY = newY
-
- // set alpha
- if (targetAlpha != UNSPECIFIED_FLOAT) {
- child.alpha = startAlpha + (targetAlpha - startAlpha) * percent
- }
-
- // set background color
- if (targetBackgroundColor != UNSPECIFIED_INT && startBackgroundColor != 0) {
- val evaluator = ArgbEvaluator()
- val color = evaluator.evaluate(percent, startBackgroundColor, targetBackgroundColor) as Int
- child.setBackgroundColor(color)
- }
-
- // set rotation
- if (targetRotateX != UNSPECIFIED_FLOAT) {
- child.rotationX = startRotateX + (targetRotateX - startRotateX) * percent
- }
- if (targetRotateY != UNSPECIFIED_FLOAT) {
- child.rotationY = startRotateY + (targetRotateY - startRotateY) * percent
- }
-
- child.requestLayout()
- }
-}
diff --git a/vector/src/main/java/im/vector/app/core/di/ScreenComponent.kt b/vector/src/main/java/im/vector/app/core/di/ScreenComponent.kt
index 9dbfa8fe30..3c11bfcd13 100644
--- a/vector/src/main/java/im/vector/app/core/di/ScreenComponent.kt
+++ b/vector/src/main/java/im/vector/app/core/di/ScreenComponent.kt
@@ -32,6 +32,7 @@ import im.vector.app.features.call.conference.VectorJitsiActivity
import im.vector.app.features.call.transfer.CallTransferActivity
import im.vector.app.features.createdirect.CreateDirectRoomActivity
import im.vector.app.features.crypto.keysbackup.settings.KeysBackupManageActivity
+import im.vector.app.features.crypto.keysbackup.setup.KeysBackupSetupActivity
import im.vector.app.features.crypto.quads.SharedSecureStorageActivity
import im.vector.app.features.crypto.recover.BootstrapBottomSheet
import im.vector.app.features.crypto.verification.VerificationBottomSheet
@@ -138,6 +139,7 @@ interface ScreenComponent {
fun inject(activity: LinkHandlerActivity)
fun inject(activity: MainActivity)
fun inject(activity: RoomDirectoryActivity)
+ fun inject(activity: KeysBackupSetupActivity)
fun inject(activity: BugReportActivity)
fun inject(activity: FilteredRoomsActivity)
fun inject(activity: CreateRoomActivity)
diff --git a/vector/src/main/java/im/vector/app/core/dialogs/ConfirmationDialogBuilder.kt b/vector/src/main/java/im/vector/app/core/dialogs/ConfirmationDialogBuilder.kt
index ed429b30c6..d2d0967939 100644
--- a/vector/src/main/java/im/vector/app/core/dialogs/ConfirmationDialogBuilder.kt
+++ b/vector/src/main/java/im/vector/app/core/dialogs/ConfirmationDialogBuilder.kt
@@ -18,8 +18,8 @@ package im.vector.app.core.dialogs
import android.app.Activity
import androidx.annotation.StringRes
-import androidx.appcompat.app.AlertDialog
import androidx.core.view.isVisible
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.databinding.DialogConfirmationWithReasonBinding
@@ -46,7 +46,7 @@ object ConfirmationDialogBuilder {
views.dialogReasonInput.setHint(reasonHintRes)
}
- AlertDialog.Builder(activity)
+ MaterialAlertDialogBuilder(activity)
.setTitle(titleRes)
.setView(layout)
.setPositiveButton(positiveRes) { _, _ ->
diff --git a/vector/src/main/java/im/vector/app/core/dialogs/DialogLocker.kt b/vector/src/main/java/im/vector/app/core/dialogs/DialogLocker.kt
index caad06c959..51a513e11e 100644
--- a/vector/src/main/java/im/vector/app/core/dialogs/DialogLocker.kt
+++ b/vector/src/main/java/im/vector/app/core/dialogs/DialogLocker.kt
@@ -18,6 +18,7 @@ package im.vector.app.core.dialogs
import android.os.Bundle
import androidx.appcompat.app.AlertDialog
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.core.platform.Restorable
import timber.log.Timber
@@ -38,7 +39,7 @@ class DialogLocker(savedInstanceState: Bundle?) : Restorable {
isDialogDisplayed = true
}
- fun displayDialog(builder: () -> AlertDialog.Builder): AlertDialog? {
+ fun displayDialog(builder: () -> MaterialAlertDialogBuilder): AlertDialog? {
return if (isDialogDisplayed) {
Timber.w("Filtered dialog request")
null
diff --git a/vector/src/main/java/im/vector/app/core/dialogs/ExportKeysDialog.kt b/vector/src/main/java/im/vector/app/core/dialogs/ExportKeysDialog.kt
index 23018fe758..afa50de9b6 100644
--- a/vector/src/main/java/im/vector/app/core/dialogs/ExportKeysDialog.kt
+++ b/vector/src/main/java/im/vector/app/core/dialogs/ExportKeysDialog.kt
@@ -18,7 +18,7 @@ package im.vector.app.core.dialogs
import android.app.Activity
import android.text.Editable
-import androidx.appcompat.app.AlertDialog
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.extensions.showPassword
import im.vector.app.core.platform.SimpleTextWatcher
@@ -31,7 +31,7 @@ class ExportKeysDialog {
fun show(activity: Activity, exportKeyDialogListener: ExportKeyDialogListener) {
val dialogLayout = activity.layoutInflater.inflate(R.layout.dialog_export_e2e_keys, null)
val views = DialogExportE2eKeysBinding.bind(dialogLayout)
- val builder = AlertDialog.Builder(activity)
+ val builder = MaterialAlertDialogBuilder(activity)
.setTitle(R.string.encryption_export_room_keys)
.setView(dialogLayout)
diff --git a/vector/src/main/java/im/vector/app/core/dialogs/Extensions.kt b/vector/src/main/java/im/vector/app/core/dialogs/Extensions.kt
index f444fca221..56544f929e 100644
--- a/vector/src/main/java/im/vector/app/core/dialogs/Extensions.kt
+++ b/vector/src/main/java/im/vector/app/core/dialogs/Extensions.kt
@@ -16,12 +16,12 @@
package im.vector.app.core.dialogs
-import androidx.annotation.ColorRes
+import androidx.annotation.AttrRes
import androidx.appcompat.app.AlertDialog
-import androidx.core.content.ContextCompat
import im.vector.app.R
+import im.vector.app.features.themes.ThemeUtils
-fun AlertDialog.withColoredButton(whichButton: Int, @ColorRes color: Int = R.color.vector_error_color): AlertDialog {
- getButton(whichButton)?.setTextColor(ContextCompat.getColor(context, color))
+fun AlertDialog.withColoredButton(whichButton: Int, @AttrRes color: Int = R.attr.colorError): AlertDialog {
+ getButton(whichButton)?.setTextColor(ThemeUtils.getColor(context, color))
return this
}
diff --git a/vector/src/main/java/im/vector/app/core/dialogs/GalleryOrCameraDialogHelper.kt b/vector/src/main/java/im/vector/app/core/dialogs/GalleryOrCameraDialogHelper.kt
index 8cb122d5bb..3b25fd3f89 100644
--- a/vector/src/main/java/im/vector/app/core/dialogs/GalleryOrCameraDialogHelper.kt
+++ b/vector/src/main/java/im/vector/app/core/dialogs/GalleryOrCameraDialogHelper.kt
@@ -18,11 +18,12 @@ package im.vector.app.core.dialogs
import android.app.Activity
import android.net.Uri
-import androidx.appcompat.app.AlertDialog
import androidx.core.net.toUri
import androidx.fragment.app.Fragment
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.yalantis.ucrop.UCrop
import im.vector.app.R
+import im.vector.app.core.dialogs.GalleryOrCameraDialogHelper.Listener
import im.vector.app.core.extensions.insertBeforeLast
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.resources.ColorProvider
@@ -101,7 +102,7 @@ class GalleryOrCameraDialogHelper(
}
fun show() {
- AlertDialog.Builder(activity)
+ MaterialAlertDialogBuilder(activity)
.setTitle(R.string.attachment_type_dialog_title)
.setItems(arrayOf(
fragment.getString(R.string.attachment_type_camera),
diff --git a/vector/src/main/java/im/vector/app/core/dialogs/ManuallyVerifyDialog.kt b/vector/src/main/java/im/vector/app/core/dialogs/ManuallyVerifyDialog.kt
index 91f16f371c..979558afd8 100644
--- a/vector/src/main/java/im/vector/app/core/dialogs/ManuallyVerifyDialog.kt
+++ b/vector/src/main/java/im/vector/app/core/dialogs/ManuallyVerifyDialog.kt
@@ -17,7 +17,7 @@
package im.vector.app.core.dialogs
import android.app.Activity
-import androidx.appcompat.app.AlertDialog
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.databinding.DialogDeviceVerifyBinding
import org.matrix.android.sdk.api.extensions.getFingerprintHumanReadable
@@ -28,7 +28,7 @@ object ManuallyVerifyDialog {
fun show(activity: Activity, cryptoDeviceInfo: CryptoDeviceInfo, onVerified: (() -> Unit)) {
val dialogLayout = activity.layoutInflater.inflate(R.layout.dialog_device_verify, null)
val views = DialogDeviceVerifyBinding.bind(dialogLayout)
- val builder = AlertDialog.Builder(activity)
+ val builder = MaterialAlertDialogBuilder(activity)
.setTitle(R.string.cross_signing_verify_by_text)
.setView(dialogLayout)
.setPositiveButton(R.string.encryption_information_verify) { _, _ ->
diff --git a/vector/src/main/java/im/vector/app/core/dialogs/PhotoOrVideoDialog.kt b/vector/src/main/java/im/vector/app/core/dialogs/PhotoOrVideoDialog.kt
index d9188397d8..dad1fba600 100644
--- a/vector/src/main/java/im/vector/app/core/dialogs/PhotoOrVideoDialog.kt
+++ b/vector/src/main/java/im/vector/app/core/dialogs/PhotoOrVideoDialog.kt
@@ -17,8 +17,8 @@
package im.vector.app.core.dialogs
import android.app.Activity
-import androidx.appcompat.app.AlertDialog
import androidx.core.view.isVisible
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.databinding.DialogPhotoOrVideoBinding
import im.vector.app.features.settings.VectorPreferences
@@ -51,7 +51,7 @@ class PhotoOrVideoDialog(
// Always default to photo
views.dialogPhotoOrVideoPhoto.isChecked = true
- AlertDialog.Builder(activity)
+ MaterialAlertDialogBuilder(activity)
.setTitle(R.string.option_take_photo_video)
.setView(dialogLayout)
.setPositiveButton(R.string._continue) { _, _ ->
@@ -95,7 +95,7 @@ class PhotoOrVideoDialog(
views.dialogPhotoOrVideoVideo.isChecked = currentMode == VectorPreferences.TAKE_PHOTO_VIDEO_MODE_VIDEO
views.dialogPhotoOrVideoAlwaysAsk.isChecked = currentMode == VectorPreferences.TAKE_PHOTO_VIDEO_MODE_ALWAYS_ASK
- AlertDialog.Builder(activity)
+ MaterialAlertDialogBuilder(activity)
.setTitle(R.string.option_take_photo_video)
.setView(dialogLayout)
.setPositiveButton(R.string.save) { _, _ ->
diff --git a/vector/src/main/java/im/vector/app/core/dialogs/PromptPasswordDialog.kt b/vector/src/main/java/im/vector/app/core/dialogs/PromptPasswordDialog.kt
index 1839a8b11c..500062376e 100644
--- a/vector/src/main/java/im/vector/app/core/dialogs/PromptPasswordDialog.kt
+++ b/vector/src/main/java/im/vector/app/core/dialogs/PromptPasswordDialog.kt
@@ -21,6 +21,7 @@ import android.content.DialogInterface
import android.text.Editable
import android.view.KeyEvent
import androidx.appcompat.app.AlertDialog
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.extensions.hideKeyboard
import im.vector.app.core.extensions.showPassword
@@ -47,7 +48,7 @@ class PromptPasswordDialog {
views.promptPasswordPasswordReveal.render(passwordVisible)
}
- AlertDialog.Builder(activity)
+ MaterialAlertDialogBuilder(activity)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle(R.string.devices_delete_dialog_title)
.setView(dialogLayout)
diff --git a/vector/src/main/java/im/vector/app/core/dialogs/UnrecognizedCertificateDialog.kt b/vector/src/main/java/im/vector/app/core/dialogs/UnrecognizedCertificateDialog.kt
index bf25275335..ca92e6aa75 100644
--- a/vector/src/main/java/im/vector/app/core/dialogs/UnrecognizedCertificateDialog.kt
+++ b/vector/src/main/java/im/vector/app/core/dialogs/UnrecognizedCertificateDialog.kt
@@ -16,7 +16,7 @@
package im.vector.app.core.dialogs
import android.app.Activity
-import androidx.appcompat.app.AlertDialog
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.resources.StringProvider
@@ -92,7 +92,7 @@ class UnrecognizedCertificateDialog @Inject constructor(
}
}
- val builder = AlertDialog.Builder(activity)
+ val builder = MaterialAlertDialogBuilder(activity)
val inflater = activity.layoutInflater
val layout = inflater.inflate(R.layout.dialog_ssl_fingerprint, null)
val views = DialogSslFingerprintBinding.bind(layout)
diff --git a/vector/src/main/java/im/vector/app/core/epoxy/BottomSheetDividerItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/BottomSheetDividerItem.kt
new file mode 100644
index 0000000000..2d65f0ce0c
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/epoxy/BottomSheetDividerItem.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2019 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package im.vector.app.core.epoxy
+
+import com.airbnb.epoxy.EpoxyModelClass
+import im.vector.app.R
+
+@EpoxyModelClass(layout = R.layout.item_divider_on_surface)
+abstract class BottomSheetDividerItem : VectorEpoxyModel() {
+ class Holder : VectorEpoxyHolder()
+}
diff --git a/vector/src/main/java/im/vector/app/core/epoxy/DividerItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/DividerItem.kt
index a08b7d7e0c..73568444b6 100644
--- a/vector/src/main/java/im/vector/app/core/epoxy/DividerItem.kt
+++ b/vector/src/main/java/im/vector/app/core/epoxy/DividerItem.kt
@@ -15,25 +15,10 @@
*/
package im.vector.app.core.epoxy
-import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
-/**
- * Default background color is for the bottom sheets (R.attr.vctr_list_bottom_sheet_divider_color).
- * To use in fragment, set color using R.attr.riotx_list_divider_color
- */
@EpoxyModelClass(layout = R.layout.item_divider)
abstract class DividerItem : VectorEpoxyModel() {
-
- @EpoxyAttribute var color: Int = -1
-
- override fun bind(holder: Holder) {
- super.bind(holder)
- if (color != -1) {
- holder.view.setBackgroundColor(color)
- }
- }
-
class Holder : VectorEpoxyHolder()
}
diff --git a/vector/src/main/java/im/vector/app/core/epoxy/ErrorWithRetryItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/ErrorWithRetryItem.kt
index f555a70d3f..8d2b2be6c2 100644
--- a/vector/src/main/java/im/vector/app/core/epoxy/ErrorWithRetryItem.kt
+++ b/vector/src/main/java/im/vector/app/core/epoxy/ErrorWithRetryItem.kt
@@ -29,14 +29,14 @@ abstract class ErrorWithRetryItem : VectorEpoxyModel(
@EpoxyAttribute
var text: String? = null
- @EpoxyAttribute
- var listener: (() -> Unit)? = null
+ @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
+ var listener: ClickListener? = null
override fun bind(holder: Holder) {
super.bind(holder)
holder.textView.text = text
holder.buttonView.isVisible = listener != null
- holder.buttonView.setOnClickListener { listener?.invoke() }
+ holder.buttonView.onClick(listener)
}
class Holder : VectorEpoxyHolder() {
diff --git a/vector/src/main/java/im/vector/app/core/epoxy/Listener.kt b/vector/src/main/java/im/vector/app/core/epoxy/Listener.kt
index e271b5abb5..e959d800b8 100644
--- a/vector/src/main/java/im/vector/app/core/epoxy/Listener.kt
+++ b/vector/src/main/java/im/vector/app/core/epoxy/Listener.kt
@@ -17,12 +17,22 @@
package im.vector.app.core.epoxy
import android.view.View
+import im.vector.app.core.utils.DebouncedClickListener
/**
- * Generally we do not care about the View parameter in [View.OnClickListener.onClick()], so create facility to remove it.
+ * View.OnClickListener lambda
*/
-typealias ClickListener = () -> Unit
+typealias ClickListener = (View) -> Unit
fun View.onClick(listener: ClickListener?) {
- setOnClickListener { listener?.invoke() }
+ if (listener == null) {
+ setOnClickListener(null)
+ } else {
+ setOnClickListener(DebouncedClickListener(listener))
+ }
}
+
+/**
+ * Simple Text listener lambda
+ */
+typealias TextListener = (String) -> Unit
diff --git a/vector/src/main/java/im/vector/app/core/epoxy/VectorEpoxyFormExt.kt b/vector/src/main/java/im/vector/app/core/epoxy/VectorEpoxyFormExt.kt
index f93b07a98d..4bc40ce557 100644
--- a/vector/src/main/java/im/vector/app/core/epoxy/VectorEpoxyFormExt.kt
+++ b/vector/src/main/java/im/vector/app/core/epoxy/VectorEpoxyFormExt.kt
@@ -16,7 +16,9 @@
package im.vector.app.core.epoxy
+import android.text.TextWatcher
import android.widget.CompoundButton
+import android.widget.TextView
import com.google.android.material.switchmaterial.SwitchMaterial
import com.google.android.material.textfield.TextInputEditText
@@ -39,3 +41,9 @@ fun VectorEpoxyHolder.setValueOnce(switchView: SwitchMaterial, switchChecked: Bo
switchView.setOnCheckedChangeListener(listener)
}
}
+
+fun TextView.addTextChangedListenerOnce(textWatcher: TextWatcher) {
+ // Ensure the watcher is not added multiple times
+ removeTextChangedListener(textWatcher)
+ addTextChangedListener(textWatcher)
+}
diff --git a/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetActionItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetActionItem.kt
index 80792648f6..854a5d3419 100644
--- a/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetActionItem.kt
+++ b/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetActionItem.kt
@@ -30,8 +30,10 @@ import androidx.core.widget.ImageViewCompat
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
+import im.vector.app.core.epoxy.ClickListener
import im.vector.app.core.epoxy.VectorEpoxyHolder
import im.vector.app.core.epoxy.VectorEpoxyModel
+import im.vector.app.core.epoxy.onClick
import im.vector.app.features.themes.ThemeUtils
/**
@@ -69,19 +71,17 @@ abstract class BottomSheetActionItem : VectorEpoxyModel Unit)? = null
+ @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
+ var userClicked: ClickListener? = null
override fun bind(holder: Holder) {
super.bind(holder)
avatarRenderer.render(matrixItem, holder.avatar)
- holder.avatar.setOnClickListener { userClicked?.invoke() }
- holder.sender.setOnClickListener { userClicked?.invoke() }
+ holder.avatar.onClick(userClicked)
+ holder.sender.onClick(userClicked)
holder.sender.setTextOrHide(matrixItem.displayName)
data?.let {
imageContentRenderer?.render(it, ImageContentRenderer.Mode.THUMBNAIL, holder.imagePreview)
diff --git a/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetQuickReactionsItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetQuickReactionsItem.kt
index ca8ef89c68..3f6b23a85f 100644
--- a/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetQuickReactionsItem.kt
+++ b/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetQuickReactionsItem.kt
@@ -24,6 +24,7 @@ import im.vector.app.EmojiCompatFontProvider
import im.vector.app.R
import im.vector.app.core.epoxy.VectorEpoxyHolder
import im.vector.app.core.epoxy.VectorEpoxyModel
+import im.vector.app.core.epoxy.onClick
/**
* A quick reaction list for bottom sheet.
@@ -50,7 +51,7 @@ abstract class BottomSheetQuickReactionsItem : VectorEpoxyModel : VectorEpoxy
@EpoxyAttribute
var userEncryptionTrustLevel: RoomEncryptionTrustLevel? = null
- @EpoxyAttribute var clickListener: View.OnClickListener? = null
+
+ @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
+ var clickListener: ClickListener? = null
@CallSuper
override fun bind(holder: T) {
@@ -43,7 +46,7 @@ abstract class BaseProfileMatrixItem : VectorEpoxy
.takeIf { it != bestName }
// Special case for ThreePid fake matrix item
.takeIf { it != "@" }
- holder.view.setOnClickListener(clickListener?.takeIf { editable })
+ holder.view.onClick(clickListener?.takeIf { editable })
holder.titleView.text = bestName
holder.subtitleView.setTextOrHide(matrixId)
holder.editableView.isVisible = editable
diff --git a/vector/src/main/java/im/vector/app/core/epoxy/profiles/ProfileActionItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/profiles/ProfileActionItem.kt
index 2769121afa..33e5172146 100644
--- a/vector/src/main/java/im/vector/app/core/epoxy/profiles/ProfileActionItem.kt
+++ b/vector/src/main/java/im/vector/app/core/epoxy/profiles/ProfileActionItem.kt
@@ -19,7 +19,6 @@ package im.vector.app.core.epoxy.profiles
import android.content.res.ColorStateList
import android.widget.ImageView
import android.widget.TextView
-import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.core.widget.ImageViewCompat
import com.airbnb.epoxy.EpoxyAttribute
@@ -67,7 +66,7 @@ abstract class ProfileActionItem : VectorEpoxyModel()
@EpoxyAttribute
var destructive: Boolean = false
- @EpoxyAttribute
+ @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
var listener: ClickListener? = null
override fun bind(holder: Holder) {
@@ -78,14 +77,14 @@ abstract class ProfileActionItem : VectorEpoxyModel()
}
holder.title.text = title
val titleTintColor = if (destructive) {
- ContextCompat.getColor(holder.view.context, R.color.riotx_notice)
+ ThemeUtils.getColor(holder.view.context, R.attr.colorError)
} else {
- ThemeUtils.getColor(holder.view.context, R.attr.riotx_text_primary)
+ ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_primary)
}
val iconTintColor = if (destructive) {
- ContextCompat.getColor(holder.view.context, R.color.riotx_notice)
+ ThemeUtils.getColor(holder.view.context, R.attr.colorError)
} else {
- ThemeUtils.getColor(holder.view.context, R.attr.riotx_text_secondary)
+ ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_secondary)
}
holder.title.setTextColor(titleTintColor)
holder.subtitle.setTextOrHide(subtitle)
@@ -119,7 +118,7 @@ abstract class ProfileActionItem : VectorEpoxyModel()
val tintColorSecondary = if (destructive) {
titleTintColor
} else {
- ThemeUtils.getColor(holder.view.context, R.attr.riotx_text_secondary)
+ ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_secondary)
}
holder.editable.setImageResource(editableRes)
ImageViewCompat.setImageTintList(holder.editable, ColorStateList.valueOf(tintColorSecondary))
diff --git a/vector/src/main/java/im/vector/app/core/epoxy/profiles/ProfileItemExtensions.kt b/vector/src/main/java/im/vector/app/core/epoxy/profiles/ProfileItemExtensions.kt
index 99acd6cb36..dd24dea1ed 100644
--- a/vector/src/main/java/im/vector/app/core/epoxy/profiles/ProfileItemExtensions.kt
+++ b/vector/src/main/java/im/vector/app/core/epoxy/profiles/ProfileItemExtensions.kt
@@ -34,7 +34,6 @@ fun EpoxyController.buildProfileSection(title: String) {
fun EpoxyController.buildProfileAction(
id: String,
title: String,
- dividerColor: Int,
subtitle: String? = null,
editable: Boolean = true,
@DrawableRes icon: Int = 0,
@@ -65,7 +64,6 @@ fun EpoxyController.buildProfileAction(
if (divider) {
dividerItem {
id("divider_$title")
- color(dividerColor)
}
}
}
diff --git a/vector/src/main/java/im/vector/app/core/extensions/RecyclerView.kt b/vector/src/main/java/im/vector/app/core/extensions/RecyclerView.kt
index 03ce44f33f..84cce10d92 100644
--- a/vector/src/main/java/im/vector/app/core/extensions/RecyclerView.kt
+++ b/vector/src/main/java/im/vector/app/core/extensions/RecyclerView.kt
@@ -16,13 +16,13 @@
package im.vector.app.core.extensions
+import androidx.annotation.DrawableRes
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.airbnb.epoxy.EpoxyController
import com.airbnb.epoxy.EpoxyVisibilityTracker
-import im.vector.app.R
/**
* Apply a Vertical LinearLayout Manager to the recyclerView and set the adapter from the epoxy controller
@@ -30,7 +30,8 @@ import im.vector.app.R
fun RecyclerView.configureWith(epoxyController: EpoxyController,
itemAnimator: RecyclerView.ItemAnimator? = null,
viewPool: RecyclerView.RecycledViewPool? = null,
- showDivider: Boolean = false,
+ @DrawableRes
+ dividerDrawable: Int? = null,
hasFixedSize: Boolean = true,
disableItemAnimation: Boolean = false) {
layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false).apply {
@@ -42,10 +43,10 @@ fun RecyclerView.configureWith(epoxyController: EpoxyController,
} else {
itemAnimator?.let { this.itemAnimator = it }
}
- if (showDivider) {
+ dividerDrawable?.let { divider ->
addItemDecoration(
DividerItemDecoration(context, DividerItemDecoration.VERTICAL).apply {
- ContextCompat.getDrawable(context, R.drawable.divider_horizontal)?.let {
+ ContextCompat.getDrawable(context, divider)?.let {
setDrawable(it)
}
}
diff --git a/vector/src/main/java/im/vector/app/core/extensions/TextView.kt b/vector/src/main/java/im/vector/app/core/extensions/TextView.kt
index 6b3902deea..bb991ac32c 100644
--- a/vector/src/main/java/im/vector/app/core/extensions/TextView.kt
+++ b/vector/src/main/java/im/vector/app/core/extensions/TextView.kt
@@ -26,7 +26,6 @@ import android.text.style.UnderlineSpan
import android.view.View
import android.widget.TextView
import androidx.annotation.AttrRes
-import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.core.content.ContextCompat
@@ -54,13 +53,13 @@ fun TextView.setTextOrHide(newText: CharSequence?, hideWhenBlank: Boolean = true
* Set text with a colored part
* @param fullTextRes the resource id of the full text. Value MUST contains a parameter for string, which will be replaced by the colored part
* @param coloredTextRes the resource id of the colored part of the text
- * @param colorAttribute attribute of the color. Default to colorAccent
+ * @param colorAttribute attribute of the color. Default to colorPrimary
* @param underline true to also underline the text. Default to false
* @param onClick attributes to handle click on the colored part if needed
*/
fun TextView.setTextWithColoredPart(@StringRes fullTextRes: Int,
@StringRes coloredTextRes: Int,
- @AttrRes colorAttribute: Int = R.attr.colorAccent,
+ @AttrRes colorAttribute: Int = R.attr.colorPrimary,
underline: Boolean = false,
onClick: (() -> Unit)? = null) {
val coloredPart = resources.getString(coloredTextRes)
@@ -95,9 +94,9 @@ fun TextView.setTextWithColoredPart(@StringRes fullTextRes: Int,
}
}
-fun TextView.setLeftDrawable(@DrawableRes iconRes: Int, @ColorRes tintColor: Int? = null) {
+fun TextView.setLeftDrawable(@DrawableRes iconRes: Int, @AttrRes tintColor: Int? = null) {
val icon = if (tintColor != null) {
- val tint = ContextCompat.getColor(context, tintColor)
+ val tint = ThemeUtils.getColor(context, tintColor)
ContextCompat.getDrawable(context, iconRes)?.also {
DrawableCompat.setTint(it.mutate(), tint)
}
diff --git a/vector/src/main/java/im/vector/app/core/platform/BadgeFloatingActionButton.kt b/vector/src/main/java/im/vector/app/core/platform/BadgeFloatingActionButton.kt
index 088a535435..e2adc0993a 100644
--- a/vector/src/main/java/im/vector/app/core/platform/BadgeFloatingActionButton.kt
+++ b/vector/src/main/java/im/vector/app/core/platform/BadgeFloatingActionButton.kt
@@ -122,6 +122,10 @@ class BadgeFloatingActionButton @JvmOverloads constructor(
}
init {
+ if (isInEditMode) {
+ count = 3
+ }
+
countStr = countStr(count)
textPaint.getTextBounds(countStr, 0, countStr.length, counterTextBounds)
countMaxStr = "$maxCount+"
diff --git a/vector/src/main/java/im/vector/app/core/platform/ButtonStateView.kt b/vector/src/main/java/im/vector/app/core/platform/ButtonStateView.kt
index fe187a915e..ee2933f542 100755
--- a/vector/src/main/java/im/vector/app/core/platform/ButtonStateView.kt
+++ b/vector/src/main/java/im/vector/app/core/platform/ButtonStateView.kt
@@ -24,6 +24,8 @@ import android.widget.FrameLayout
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import im.vector.app.R
+import im.vector.app.core.epoxy.ClickListener
+import im.vector.app.core.epoxy.onClick
import im.vector.app.databinding.ViewButtonStateBinding
class ButtonStateView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0)
@@ -36,12 +38,9 @@ class ButtonStateView @JvmOverloads constructor(context: Context, attrs: Attribu
object Error : State()
}
- var callback: Callback? = null
-
- interface Callback {
- fun onButtonClicked()
- fun onRetryClicked()
- }
+ var commonClicked: ClickListener? = null
+ var buttonClicked: ClickListener? = null
+ var retryClicked: ClickListener? = null
// Big or Flat button
var button: Button
@@ -54,8 +53,9 @@ class ButtonStateView @JvmOverloads constructor(context: Context, attrs: Attribu
layoutParams = LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
- views.buttonStateRetry.setOnClickListener {
- callback?.onRetryClicked()
+ views.buttonStateRetry.onClick {
+ commonClicked?.invoke(it)
+ retryClicked?.invoke(it)
}
// Read attributes
@@ -80,8 +80,9 @@ class ButtonStateView @JvmOverloads constructor(context: Context, attrs: Attribu
}
}
- button.setOnClickListener {
- callback?.onButtonClicked()
+ button.onClick {
+ commonClicked?.invoke(it)
+ buttonClicked?.invoke(it)
}
}
diff --git a/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt b/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt
index b35d582a00..ddfb578e95 100644
--- a/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt
+++ b/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt
@@ -27,7 +27,6 @@ import android.view.View
import android.view.WindowInsetsController
import android.view.WindowManager
import android.widget.TextView
-import androidx.annotation.AttrRes
import androidx.annotation.CallSuper
import androidx.annotation.MainThread
import androidx.annotation.MenuRes
@@ -456,7 +455,6 @@ abstract class VectorBaseActivity : AppCompatActivity(), HasScr
if (menuRes != -1) {
menuInflater.inflate(menuRes, menu)
- ThemeUtils.tintMenuIcons(menu, ThemeUtils.getColor(this, getMenuTint()))
return true
}
@@ -584,9 +582,6 @@ abstract class VectorBaseActivity : AppCompatActivity(), HasScr
@MenuRes
open fun getMenuRes() = -1
- @AttrRes
- open fun getMenuTint() = R.attr.vctr_icon_tint_on_light_action_bar_color
-
/**
* Return a object containing other themes for this activity
*/
diff --git a/vector/src/main/java/im/vector/app/core/platform/VectorBaseFragment.kt b/vector/src/main/java/im/vector/app/core/platform/VectorBaseFragment.kt
index 258517aa39..b5b6937aad 100644
--- a/vector/src/main/java/im/vector/app/core/platform/VectorBaseFragment.kt
+++ b/vector/src/main/java/im/vector/app/core/platform/VectorBaseFragment.kt
@@ -29,12 +29,12 @@ import android.view.View
import android.view.ViewGroup
import androidx.annotation.CallSuper
import androidx.annotation.MainThread
-import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.Toolbar
import androidx.lifecycle.ViewModelProvider
import androidx.viewbinding.ViewBinding
import com.airbnb.mvrx.BaseMvRxFragment
import com.bumptech.glide.util.Util.assertMainThread
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.jakewharton.rxbinding3.view.clicks
import im.vector.app.R
import im.vector.app.core.di.DaggerScreenComponent
@@ -290,7 +290,7 @@ abstract class VectorBaseFragment : BaseMvRxFragment(), HasScre
* ========================================================================================== */
protected fun displayErrorDialog(throwable: Throwable) {
- AlertDialog.Builder(requireActivity())
+ MaterialAlertDialogBuilder(requireActivity())
.setTitle(R.string.dialog_title_error)
.setMessage(errorFormatter.toHumanReadable(throwable))
.setPositiveButton(R.string.ok, null)
diff --git a/vector/src/main/java/im/vector/app/core/preference/VectorPreference.kt b/vector/src/main/java/im/vector/app/core/preference/VectorPreference.kt
index a40ddef6ab..22fc1758f1 100755
--- a/vector/src/main/java/im/vector/app/core/preference/VectorPreference.kt
+++ b/vector/src/main/java/im/vector/app/core/preference/VectorPreference.kt
@@ -107,7 +107,7 @@ open class VectorPreference : Preference {
val icon = holder.findViewById(android.R.id.icon) as? ImageView
icon?.let {
- val color = ThemeUtils.getColor(context, R.attr.riotx_header_panel_text_secondary)
+ val color = ThemeUtils.getColor(context, R.attr.vctr_content_secondary)
ImageViewCompat.setImageTintList(it, ColorStateList.valueOf(color))
}
}
@@ -116,7 +116,7 @@ open class VectorPreference : Preference {
currentHighlightAnimator?.cancel()
if (isHighlighted) {
val colorFrom = Color.TRANSPARENT
- val colorTo = ThemeUtils.getColor(itemView.context, R.attr.colorAccent)
+ val colorTo = ThemeUtils.getColor(itemView.context, R.attr.colorPrimary)
currentHighlightAnimator = ValueAnimator.ofObject(ArgbEvaluator(), colorFrom, colorTo).apply {
duration = 250 // milliseconds
addUpdateListener { animator ->
diff --git a/vector/src/main/java/im/vector/app/core/preference/VectorPreferenceCategory.kt b/vector/src/main/java/im/vector/app/core/preference/VectorPreferenceCategory.kt
index eb59da640d..d074f0afd9 100644
--- a/vector/src/main/java/im/vector/app/core/preference/VectorPreferenceCategory.kt
+++ b/vector/src/main/java/im/vector/app/core/preference/VectorPreferenceCategory.kt
@@ -48,7 +48,7 @@ class VectorPreferenceCategory : PreferenceCategory {
val titleTextView = holder.findViewById(android.R.id.title) as? TextView
titleTextView?.setTypeface(null, Typeface.BOLD)
- titleTextView?.setTextColor(ThemeUtils.getColor(context, R.attr.riotx_text_primary))
+ titleTextView?.setTextColor(ThemeUtils.getColor(context, R.attr.vctr_content_primary))
// "isIconSpaceReserved = false" does not work for preference category, so remove the padding
if (!isIconSpaceReserved) {
diff --git a/vector/src/main/java/im/vector/app/core/ui/bottomsheet/BottomSheetGenericController.kt b/vector/src/main/java/im/vector/app/core/ui/bottomsheet/BottomSheetGenericController.kt
index 5edaa3400b..f0715e6bba 100644
--- a/vector/src/main/java/im/vector/app/core/ui/bottomsheet/BottomSheetGenericController.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/bottomsheet/BottomSheetGenericController.kt
@@ -15,7 +15,6 @@
*/
package im.vector.app.core.ui.bottomsheet
-import android.view.View
import com.airbnb.epoxy.TypedEpoxyController
/**
@@ -43,7 +42,7 @@ abstract class BottomSheetGenericController
action.toRadioBottomSheetItem()
- .listener(View.OnClickListener { listener?.didSelectAction(action) })
+ .listener { listener?.didSelectAction(action) }
.addTo(this)
}
}
diff --git a/vector/src/main/java/im/vector/app/core/ui/list/Action.kt b/vector/src/main/java/im/vector/app/core/ui/list/Action.kt
new file mode 100644
index 0000000000..f20ef84f54
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/ui/list/Action.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2021 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.core.ui.list
+
+import im.vector.app.core.epoxy.ClickListener
+
+data class Action(
+ val title: String,
+ val listener: ClickListener
+)
diff --git a/vector/src/main/java/im/vector/app/core/ui/list/GenericButtonItem.kt b/vector/src/main/java/im/vector/app/core/ui/list/GenericButtonItem.kt
index d1df785381..eb683631fd 100644
--- a/vector/src/main/java/im/vector/app/core/ui/list/GenericButtonItem.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/list/GenericButtonItem.kt
@@ -15,15 +15,16 @@
*/
package im.vector.app.core.ui.list
-import android.view.View
import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import com.google.android.material.button.MaterialButton
import im.vector.app.R
+import im.vector.app.core.epoxy.ClickListener
import im.vector.app.core.epoxy.VectorEpoxyHolder
import im.vector.app.core.epoxy.VectorEpoxyModel
+import im.vector.app.core.epoxy.onClick
import im.vector.app.features.themes.ThemeUtils
/**
@@ -35,8 +36,8 @@ abstract class GenericButtonItem : VectorEpoxyModel()
@EpoxyAttribute
var text: String? = null
- @EpoxyAttribute
- var buttonClickAction: View.OnClickListener? = null
+ @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
+ var buttonClickAction: ClickListener? = null
@EpoxyAttribute
@ColorInt
@@ -49,7 +50,7 @@ abstract class GenericButtonItem : VectorEpoxyModel()
override fun bind(holder: Holder) {
super.bind(holder)
holder.button.text = text
- val textColor = textColor ?: ThemeUtils.getColor(holder.view.context, R.attr.riotx_text_primary)
+ val textColor = textColor ?: ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_primary)
holder.button.setTextColor(textColor)
if (iconRes != null) {
holder.button.setIconResource(iconRes!!)
@@ -57,7 +58,7 @@ abstract class GenericButtonItem : VectorEpoxyModel()
holder.button.icon = null
}
- buttonClickAction?.let { holder.button.setOnClickListener(it) }
+ holder.button.onClick(buttonClickAction)
}
class Holder : VectorEpoxyHolder() {
diff --git a/vector/src/main/java/im/vector/app/core/ui/list/GenericEmptyWithActionItem.kt b/vector/src/main/java/im/vector/app/core/ui/list/GenericEmptyWithActionItem.kt
index f8eb968268..359488e3f4 100644
--- a/vector/src/main/java/im/vector/app/core/ui/list/GenericEmptyWithActionItem.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/list/GenericEmptyWithActionItem.kt
@@ -29,6 +29,7 @@ import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
import im.vector.app.core.epoxy.VectorEpoxyHolder
import im.vector.app.core.epoxy.VectorEpoxyModel
+import im.vector.app.core.epoxy.onClick
import im.vector.app.core.extensions.setTextOrHide
/**
@@ -37,10 +38,6 @@ import im.vector.app.core.extensions.setTextOrHide
@EpoxyModelClass(layout = R.layout.item_generic_empty_state)
abstract class GenericEmptyWithActionItem : VectorEpoxyModel() {
- class Action(var title: String) {
- var perform: Runnable? = null
- }
-
@EpoxyAttribute
var title: CharSequence? = null
@@ -77,9 +74,7 @@ abstract class GenericEmptyWithActionItem : VectorEpoxyModel()
@EpoxyAttribute
var style: ItemStyle = ItemStyle.NORMAL_TEXT
- @EpoxyAttribute
- var itemClickAction: GenericItem.Action? = null
+ @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
+ var itemClickAction: ClickListener? = null
@EpoxyAttribute
var centered: Boolean = true
@@ -62,12 +64,10 @@ abstract class GenericFooterItem : VectorEpoxyModel()
if (textColor != null) {
holder.text.setTextColor(textColor!!)
} else {
- holder.text.setTextColor(ThemeUtils.getColor(holder.view.context, R.attr.riotx_text_secondary))
+ holder.text.setTextColor(ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_secondary))
}
- holder.view.setOnClickListener {
- itemClickAction?.perform?.run()
- }
+ holder.view.onClick(itemClickAction)
}
class Holder : VectorEpoxyHolder() {
diff --git a/vector/src/main/java/im/vector/app/core/ui/list/GenericItemHeader.kt b/vector/src/main/java/im/vector/app/core/ui/list/GenericHeaderItem.kt
similarity index 95%
rename from vector/src/main/java/im/vector/app/core/ui/list/GenericItemHeader.kt
rename to vector/src/main/java/im/vector/app/core/ui/list/GenericHeaderItem.kt
index bc5446e836..b4b0211b91 100644
--- a/vector/src/main/java/im/vector/app/core/ui/list/GenericItemHeader.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/list/GenericHeaderItem.kt
@@ -29,7 +29,7 @@ import im.vector.app.features.themes.ThemeUtils
* A generic list item header left aligned with notice color.
*/
@EpoxyModelClass(layout = R.layout.item_generic_header)
-abstract class GenericItemHeader : VectorEpoxyModel() {
+abstract class GenericHeaderItem : VectorEpoxyModel() {
@EpoxyAttribute
var text: String? = null
diff --git a/vector/src/main/java/im/vector/app/core/ui/list/GenericItem.kt b/vector/src/main/java/im/vector/app/core/ui/list/GenericItem.kt
index 8a01183915..cdfd1d75fc 100644
--- a/vector/src/main/java/im/vector/app/core/ui/list/GenericItem.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/list/GenericItem.kt
@@ -25,8 +25,10 @@ import androidx.core.view.isVisible
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
+import im.vector.app.core.epoxy.ClickListener
import im.vector.app.core.epoxy.VectorEpoxyHolder
import im.vector.app.core.epoxy.VectorEpoxyModel
+import im.vector.app.core.epoxy.onClick
import im.vector.app.core.extensions.setTextOrHide
/**
@@ -38,10 +40,6 @@ import im.vector.app.core.extensions.setTextOrHide
@EpoxyModelClass(layout = R.layout.item_generic_list)
abstract class GenericItem : VectorEpoxyModel() {
- class Action(var title: String) {
- var perform: Runnable? = null
- }
-
@EpoxyAttribute
var title: CharSequence? = null
@@ -68,8 +66,8 @@ abstract class GenericItem : VectorEpoxyModel() {
@EpoxyAttribute
var destructiveButtonAction: Action? = null
- @EpoxyAttribute
- var itemClickAction: Action? = null
+ @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
+ var itemClickAction: ClickListener? = null
override fun bind(holder: Holder) {
super.bind(holder)
@@ -100,18 +98,12 @@ abstract class GenericItem : VectorEpoxyModel() {
}
holder.actionButton.setTextOrHide(buttonAction?.title)
- holder.actionButton.setOnClickListener {
- buttonAction?.perform?.run()
- }
+ holder.actionButton.onClick(buttonAction?.listener)
holder.destructiveButton.setTextOrHide(destructiveButtonAction?.title)
- holder.destructiveButton.setOnClickListener {
- destructiveButtonAction?.perform?.run()
- }
+ holder.destructiveButton.onClick(destructiveButtonAction?.listener)
- holder.root.setOnClickListener {
- itemClickAction?.perform?.run()
- }
+ holder.root.onClick(itemClickAction)
}
class Holder : VectorEpoxyHolder() {
diff --git a/vector/src/main/java/im/vector/app/core/ui/list/GenericPillItem.kt b/vector/src/main/java/im/vector/app/core/ui/list/GenericPillItem.kt
index ce9e35c007..451b7f086f 100644
--- a/vector/src/main/java/im/vector/app/core/ui/list/GenericPillItem.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/list/GenericPillItem.kt
@@ -25,8 +25,10 @@ import androidx.core.widget.ImageViewCompat
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
+import im.vector.app.core.epoxy.ClickListener
import im.vector.app.core.epoxy.VectorEpoxyHolder
import im.vector.app.core.epoxy.VectorEpoxyModel
+import im.vector.app.core.epoxy.onClick
import im.vector.app.core.extensions.setTextOrHide
import im.vector.app.features.themes.ThemeUtils
@@ -42,8 +44,8 @@ abstract class GenericPillItem : VectorEpoxyModel() {
@EpoxyAttribute
var style: ItemStyle = ItemStyle.NORMAL_TEXT
- @EpoxyAttribute
- var itemClickAction: GenericItem.Action? = null
+ @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
+ var itemClickAction: ClickListener? = null
@EpoxyAttribute
var centered: Boolean = false
@@ -70,15 +72,13 @@ abstract class GenericPillItem : VectorEpoxyModel() {
holder.imageView.isVisible = false
}
if (tintIcon) {
- val iconTintColor = ThemeUtils.getColor(holder.view.context, R.attr.riotx_text_secondary)
+ val iconTintColor = ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_secondary)
ImageViewCompat.setImageTintList(holder.imageView, ColorStateList.valueOf(iconTintColor))
} else {
ImageViewCompat.setImageTintList(holder.imageView, null)
}
- holder.view.setOnClickListener {
- itemClickAction?.perform?.run()
- }
+ holder.view.onClick(itemClickAction)
}
class Holder : VectorEpoxyHolder() {
diff --git a/vector/src/main/java/im/vector/app/core/ui/list/GenericPositiveButtonItem.kt b/vector/src/main/java/im/vector/app/core/ui/list/GenericPositiveButtonItem.kt
index d18adde4ba..753b085d99 100644
--- a/vector/src/main/java/im/vector/app/core/ui/list/GenericPositiveButtonItem.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/list/GenericPositiveButtonItem.kt
@@ -15,15 +15,16 @@
*/
package im.vector.app.core.ui.list
-import android.view.View
import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import com.google.android.material.button.MaterialButton
import im.vector.app.R
+import im.vector.app.core.epoxy.ClickListener
import im.vector.app.core.epoxy.VectorEpoxyHolder
import im.vector.app.core.epoxy.VectorEpoxyModel
+import im.vector.app.core.epoxy.onClick
/**
* A generic button list item.
@@ -34,8 +35,8 @@ abstract class GenericPositiveButtonItem : VectorEpoxyModel() {
+abstract class GenericWithValueItem : VectorEpoxyModel() {
@EpoxyAttribute
var title: CharSequence? = null
@@ -53,10 +54,10 @@ abstract class GenericItemWithValue : VectorEpoxyModel = emptyList()
@@ -83,16 +83,17 @@ class KnownCallsViewHolder {
}
}
- fun bind(activeCallPiP: SurfaceViewRenderer, activeCallView: CurrentCallsView, pipWrapper: CardView, interactionListener: CurrentCallsView.Callback) {
+ fun bind(activeCallPiP: SurfaceViewRenderer,
+ activeCallView: CurrentCallsView,
+ pipWrapper: MaterialCardView,
+ interactionListener: CurrentCallsView.Callback) {
this.activeCallPiP = activeCallPiP
this.currentCallsView = activeCallView
this.pipWrapper = pipWrapper
this.currentCallsView?.callback = interactionListener
- pipWrapper.setOnClickListener(
- DebouncedClickListener({
- interactionListener.onTapToReturnToCall()
- })
- )
+ pipWrapper.onClick {
+ interactionListener.onTapToReturnToCall()
+ }
this.currentCall?.addListener(tickListener)
}
diff --git a/vector/src/main/java/im/vector/app/core/ui/views/NotificationAreaView.kt b/vector/src/main/java/im/vector/app/core/ui/views/NotificationAreaView.kt
index 8986bc813f..ad2a4b8e0c 100644
--- a/vector/src/main/java/im/vector/app/core/ui/views/NotificationAreaView.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/views/NotificationAreaView.kt
@@ -102,7 +102,7 @@ class NotificationAreaView @JvmOverloads constructor(
}
}
views.roomNotificationMessage.text = message
- views.roomNotificationMessage.setTextColor(ThemeUtils.getColor(context, R.attr.riotx_text_secondary))
+ views.roomNotificationMessage.setTextColor(ThemeUtils.getColor(context, R.attr.vctr_content_secondary))
}
private fun renderResourceLimitExceededError(state: State.ResourceLimitExceededError) {
diff --git a/vector/src/main/java/im/vector/app/core/ui/views/ReadReceiptsView.kt b/vector/src/main/java/im/vector/app/core/ui/views/ReadReceiptsView.kt
index 8f8919fd47..02b351737e 100644
--- a/vector/src/main/java/im/vector/app/core/ui/views/ReadReceiptsView.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/views/ReadReceiptsView.kt
@@ -59,8 +59,7 @@ class ReadReceiptsView @JvmOverloads constructor(
contentDescription = context.getString(R.string.a11y_view_read_receipts)
}
- fun render(readReceipts: List, avatarRenderer: AvatarRenderer, clickListener: OnClickListener) {
- setOnClickListener(clickListener)
+ fun render(readReceipts: List, avatarRenderer: AvatarRenderer) {
if (readReceipts.isNotEmpty()) {
isVisible = true
for (index in 0 until MAX_RECEIPT_DISPLAYED) {
diff --git a/vector/src/main/java/im/vector/app/core/ui/views/SendStateImageView.kt b/vector/src/main/java/im/vector/app/core/ui/views/SendStateImageView.kt
index 308efe09b2..cb1d08d2e5 100644
--- a/vector/src/main/java/im/vector/app/core/ui/views/SendStateImageView.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/views/SendStateImageView.kt
@@ -41,13 +41,13 @@ class SendStateImageView @JvmOverloads constructor(
isVisible = when (sendState) {
SendStateDecoration.SENDING_NON_MEDIA -> {
setImageResource(R.drawable.ic_sending_message)
- imageTintList = ColorStateList.valueOf(ThemeUtils.getColor(context, R.attr.riotx_text_tertiary))
+ imageTintList = ColorStateList.valueOf(ThemeUtils.getColor(context, R.attr.vctr_content_tertiary))
contentDescription = context.getString(R.string.event_status_a11y_sending)
true
}
SendStateDecoration.SENT -> {
setImageResource(R.drawable.ic_message_sent)
- imageTintList = ColorStateList.valueOf(ThemeUtils.getColor(context, R.attr.riotx_text_tertiary))
+ imageTintList = ColorStateList.valueOf(ThemeUtils.getColor(context, R.attr.vctr_content_tertiary))
contentDescription = context.getString(R.string.event_status_a11y_sent)
true
}
diff --git a/vector/src/main/java/im/vector/app/core/utils/DebouncedClickListener.kt b/vector/src/main/java/im/vector/app/core/utils/DebouncedClickListener.kt
index 8f96a286d9..f7c3eec112 100644
--- a/vector/src/main/java/im/vector/app/core/utils/DebouncedClickListener.kt
+++ b/vector/src/main/java/im/vector/app/core/utils/DebouncedClickListener.kt
@@ -15,24 +15,30 @@
*/
package im.vector.app.core.utils
+import android.os.SystemClock
import android.view.View
+import timber.log.Timber
import java.util.WeakHashMap
/**
* Simple Debounced OnClickListener
* Safe to use in different views
*/
-class DebouncedClickListener(val original: View.OnClickListener, private val minimumInterval: Long = 400) : View.OnClickListener {
+class DebouncedClickListener(
+ val original: View.OnClickListener,
+ private val minimumInterval: Long = 400
+) : View.OnClickListener {
private val lastClickMap = WeakHashMap()
- override fun onClick(clickedView: View) {
- val previousClickTimestamp = lastClickMap[clickedView]
- val currentTimestamp = System.currentTimeMillis()
+ override fun onClick(v: View) {
+ val previousClickTimestamp = lastClickMap[v] ?: 0
+ val currentTimestamp = SystemClock.elapsedRealtime()
+ lastClickMap[v] = currentTimestamp
- lastClickMap[clickedView] = currentTimestamp
-
- if (previousClickTimestamp == null || currentTimestamp - previousClickTimestamp.toLong() > minimumInterval) {
- original.onClick(clickedView)
+ if (currentTimestamp > previousClickTimestamp + minimumInterval) {
+ original.onClick(v)
+ } else {
+ Timber.v("Debounced click!")
}
}
}
diff --git a/vector/src/main/java/im/vector/app/core/utils/Dialogs.kt b/vector/src/main/java/im/vector/app/core/utils/Dialogs.kt
index 7b5417c18a..7806f2603d 100644
--- a/vector/src/main/java/im/vector/app/core/utils/Dialogs.kt
+++ b/vector/src/main/java/im/vector/app/core/utils/Dialogs.kt
@@ -19,7 +19,7 @@ package im.vector.app.core.utils
import android.content.Context
import android.webkit.WebView
import android.webkit.WebViewClient
-import androidx.appcompat.app.AlertDialog
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
/**
* Open a web view above the current activity.
@@ -33,7 +33,7 @@ fun Context.displayInWebView(url: String) {
wv.webViewClient = WebViewClient()
wv.loadUrl(url)
- AlertDialog.Builder(this)
+ MaterialAlertDialogBuilder(this)
.setView(wv)
.setPositiveButton(android.R.string.ok, null)
.show()
diff --git a/vector/src/main/java/im/vector/app/core/utils/ExternalApplicationsUtil.kt b/vector/src/main/java/im/vector/app/core/utils/ExternalApplicationsUtil.kt
index d82de1b4ed..d0535b667f 100644
--- a/vector/src/main/java/im/vector/app/core/utils/ExternalApplicationsUtil.kt
+++ b/vector/src/main/java/im/vector/app/core/utils/ExternalApplicationsUtil.kt
@@ -56,7 +56,6 @@ import timber.log.Timber
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
-import java.lang.IllegalStateException
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
@@ -100,8 +99,8 @@ fun openUrlInChromeCustomTab(context: Context,
CustomTabsIntent.Builder()
.setDefaultColorSchemeParams(
CustomTabColorSchemeParams.Builder()
- .setToolbarColor(ThemeUtils.getColor(context, R.attr.riotx_background))
- .setNavigationBarColor(ThemeUtils.getColor(context, R.attr.riotx_background))
+ .setToolbarColor(ThemeUtils.getColor(context, android.R.attr.colorBackground))
+ .setNavigationBarColor(ThemeUtils.getColor(context, android.R.attr.colorBackground))
.build()
)
.setColorScheme(
diff --git a/vector/src/main/java/im/vector/app/core/utils/JsonViewerStyler.kt b/vector/src/main/java/im/vector/app/core/utils/JsonViewerStyler.kt
index ab203e2fa0..070b382e99 100644
--- a/vector/src/main/java/im/vector/app/core/utils/JsonViewerStyler.kt
+++ b/vector/src/main/java/im/vector/app/core/utils/JsonViewerStyler.kt
@@ -22,10 +22,10 @@ import org.billcarsonfr.jsonviewer.JSonViewerStyleProvider
fun createJSonViewerStyleProvider(colorProvider: ColorProvider): JSonViewerStyleProvider {
return JSonViewerStyleProvider(
- keyColor = colorProvider.getColor(R.color.riotx_accent),
- secondaryColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary),
+ keyColor = colorProvider.getColorFromAttribute(R.attr.colorPrimary),
+ secondaryColor = colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary),
stringColor = colorProvider.getColorFromAttribute(R.attr.vctr_notice_text_color),
- baseColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_primary),
+ baseColor = colorProvider.getColorFromAttribute(R.attr.vctr_content_primary),
booleanColor = colorProvider.getColorFromAttribute(R.attr.vctr_notice_text_color),
numberColor = colorProvider.getColorFromAttribute(R.attr.vctr_notice_text_color)
)
diff --git a/vector/src/main/java/im/vector/app/core/utils/PermissionsTools.kt b/vector/src/main/java/im/vector/app/core/utils/PermissionsTools.kt
index 9760ec257f..b6566b4ce9 100644
--- a/vector/src/main/java/im/vector/app/core/utils/PermissionsTools.kt
+++ b/vector/src/main/java/im/vector/app/core/utils/PermissionsTools.kt
@@ -25,10 +25,10 @@ import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.StringRes
-import androidx.appcompat.app.AlertDialog
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.platform.VectorBaseActivity
import timber.log.Timber
@@ -222,7 +222,7 @@ private fun checkPermissions(permissionsToBeGrantedBitMap: Int,
// if some permissions were already denied: display a dialog to the user before asking again.
if (permissionListAlreadyDenied.isNotEmpty() && rationaleMessage != 0) {
// display the dialog with the info text
- AlertDialog.Builder(activity)
+ MaterialAlertDialogBuilder(activity)
.setTitle(R.string.permissions_rationale_popup_title)
.setMessage(rationaleMessage)
.setOnCancelListener { Toast.makeText(activity, R.string.missing_permissions_warning, Toast.LENGTH_SHORT).show() }
@@ -246,7 +246,7 @@ private fun checkPermissions(permissionsToBeGrantedBitMap: Int,
&& Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
TODO()
/*
- AlertDialog.Builder(activity)
+ MaterialAlertDialogBuilder(activity)
.setIcon(android.R.drawable.ic_dialog_info)
.setTitle(R.string.permissions_rationale_popup_title)
.setMessage(R.string.permissions_msg_contacts_warning_other_androids)
diff --git a/vector/src/main/java/im/vector/app/features/MainActivity.kt b/vector/src/main/java/im/vector/app/features/MainActivity.kt
index 054b1bcff1..583aae260b 100644
--- a/vector/src/main/java/im/vector/app/features/MainActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/MainActivity.kt
@@ -20,10 +20,10 @@ import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.os.Parcelable
-import androidx.appcompat.app.AlertDialog
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import com.bumptech.glide.Glide
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.di.ScreenComponent
@@ -208,7 +208,7 @@ class MainActivity : VectorBaseActivity(), UnlockedActivity
private fun displayError(failure: Throwable) {
if (lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) {
- AlertDialog.Builder(this)
+ MaterialAlertDialogBuilder(this)
.setTitle(R.string.dialog_title_error)
.setMessage(errorFormatter.toHumanReadable(failure))
.setPositiveButton(R.string.global_retry) { _, _ -> doCleanUp() }
diff --git a/vector/src/main/java/im/vector/app/features/autocomplete/AutocompleteMatrixItem.kt b/vector/src/main/java/im/vector/app/features/autocomplete/AutocompleteMatrixItem.kt
index 28ea5234a7..3d70615abf 100644
--- a/vector/src/main/java/im/vector/app/features/autocomplete/AutocompleteMatrixItem.kt
+++ b/vector/src/main/java/im/vector/app/features/autocomplete/AutocompleteMatrixItem.kt
@@ -16,14 +16,15 @@
package im.vector.app.features.autocomplete
-import android.view.View
import android.widget.ImageView
import android.widget.TextView
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
+import im.vector.app.core.epoxy.ClickListener
import im.vector.app.core.epoxy.VectorEpoxyHolder
import im.vector.app.core.epoxy.VectorEpoxyModel
+import im.vector.app.core.epoxy.onClick
import im.vector.app.core.extensions.setTextOrHide
import im.vector.app.features.home.AvatarRenderer
import org.matrix.android.sdk.api.util.MatrixItem
@@ -34,11 +35,11 @@ abstract class AutocompleteMatrixItem : VectorEpoxyModel
- host.listener?.onItemClick(command)
- }
+ clickListener { host.listener?.onItemClick(command) }
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/autocomplete/command/AutocompleteCommandItem.kt b/vector/src/main/java/im/vector/app/features/autocomplete/command/AutocompleteCommandItem.kt
index 0f24b866bf..b978612685 100644
--- a/vector/src/main/java/im/vector/app/features/autocomplete/command/AutocompleteCommandItem.kt
+++ b/vector/src/main/java/im/vector/app/features/autocomplete/command/AutocompleteCommandItem.kt
@@ -16,13 +16,14 @@
package im.vector.app.features.autocomplete.command
-import android.view.View
import android.widget.TextView
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
+import im.vector.app.core.epoxy.ClickListener
import im.vector.app.core.epoxy.VectorEpoxyHolder
import im.vector.app.core.epoxy.VectorEpoxyModel
+import im.vector.app.core.epoxy.onClick
@EpoxyModelClass(layout = R.layout.item_autocomplete_command)
abstract class AutocompleteCommandItem : VectorEpoxyModel() {
@@ -36,13 +37,12 @@ abstract class AutocompleteCommandItem : VectorEpoxyModel
- host.listener?.onItemClick(groupSummary)
- }
+ clickListener { host.listener?.onItemClick(groupSummary) }
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberController.kt b/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberController.kt
index 66c6705d14..9b4bd78504 100644
--- a/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberController.kt
+++ b/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberController.kt
@@ -40,9 +40,7 @@ class AutocompleteMemberController @Inject constructor() : TypedEpoxyController<
id(user.userId)
matrixItem(user.toMatrixItem())
avatarRenderer(host.avatarRenderer)
- clickListener { _ ->
- host.listener?.onItemClick(user)
- }
+ clickListener { host.listener?.onItemClick(user) }
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/autocomplete/room/AutocompleteRoomController.kt b/vector/src/main/java/im/vector/app/features/autocomplete/room/AutocompleteRoomController.kt
index 309c194272..cdc30938e7 100644
--- a/vector/src/main/java/im/vector/app/features/autocomplete/room/AutocompleteRoomController.kt
+++ b/vector/src/main/java/im/vector/app/features/autocomplete/room/AutocompleteRoomController.kt
@@ -39,9 +39,7 @@ class AutocompleteRoomController @Inject constructor(private val avatarRenderer:
matrixItem(roomSummary.toMatrixItem())
subName(roomSummary.canonicalAlias)
avatarRenderer(host.avatarRenderer)
- clickListener { _ ->
- host.listener?.onItemClick(roomSummary)
- }
+ clickListener { host.listener?.onItemClick(roomSummary) }
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/call/CallControlsBottomSheet.kt b/vector/src/main/java/im/vector/app/features/call/CallControlsBottomSheet.kt
index 84658a830c..f23b26883a 100644
--- a/vector/src/main/java/im/vector/app/features/call/CallControlsBottomSheet.kt
+++ b/vector/src/main/java/im/vector/app/features/call/CallControlsBottomSheet.kt
@@ -20,10 +20,10 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import com.airbnb.mvrx.activityViewModel
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
import im.vector.app.databinding.BottomSheetCallControlsBinding
@@ -105,7 +105,7 @@ class CallControlsBottomSheet : VectorBaseBottomSheetDialogFragment
d.cancel()
when (soundDevices[n].toString()) {
diff --git a/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt b/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt
index ad04e33414..11b3a51c6f 100644
--- a/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt
@@ -26,7 +26,6 @@ import android.os.Bundle
import android.os.Parcelable
import android.view.View
import android.view.WindowManager
-import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat
import androidx.core.content.getSystemService
import androidx.core.view.isInvisible
@@ -35,6 +34,7 @@ import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.MvRx
import com.airbnb.mvrx.viewModel
import com.airbnb.mvrx.withState
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.platform.VectorBaseActivity
@@ -359,8 +359,7 @@ class VectorCallActivity : VectorBaseActivity(), CallContro
private fun onErrorTimoutConnect(turn: TurnServerResponse?) {
Timber.d("## VOIP onErrorTimoutConnect $turn")
// TODO ask to use default stun, etc...
- AlertDialog
- .Builder(this)
+ MaterialAlertDialogBuilder(this)
.setTitle(R.string.call_failed_no_connection)
.setMessage(getString(R.string.call_failed_no_connection_description))
.setNegativeButton(R.string.ok) { _, _ ->
diff --git a/vector/src/main/java/im/vector/app/features/call/conference/VectorJitsiActivity.kt b/vector/src/main/java/im/vector/app/features/call/conference/VectorJitsiActivity.kt
index 15346422a6..11b84f4f44 100644
--- a/vector/src/main/java/im/vector/app/features/call/conference/VectorJitsiActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/call/conference/VectorJitsiActivity.kt
@@ -26,7 +26,6 @@ import android.os.Bundle
import android.os.Parcelable
import android.widget.FrameLayout
import android.widget.Toast
-import androidx.appcompat.app.AlertDialog
import androidx.core.view.isVisible
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.airbnb.mvrx.Fail
@@ -34,6 +33,7 @@ import com.airbnb.mvrx.MvRx
import com.airbnb.mvrx.Success
import com.airbnb.mvrx.viewModel
import com.facebook.react.modules.core.PermissionListener
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.extensions.exhaustive
@@ -103,7 +103,7 @@ class VectorJitsiActivity : VectorBaseActivity(), JitsiMee
}
private fun handleConfirmSwitching(action: JitsiCallViewEvents.ConfirmSwitchingConference) {
- AlertDialog.Builder(this)
+ MaterialAlertDialogBuilder(this)
.setTitle(R.string.dialog_title_warning)
.setMessage(R.string.jitsi_leave_conf_to_join_another_one_content)
.setPositiveButton(R.string.action_switch) { _, _ ->
diff --git a/vector/src/main/java/im/vector/app/features/call/dialpad/DialPadFragment.kt b/vector/src/main/java/im/vector/app/features/call/dialpad/DialPadFragment.kt
index 11c3af9394..fe0afc166d 100644
--- a/vector/src/main/java/im/vector/app/features/call/dialpad/DialPadFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/call/dialpad/DialPadFragment.kt
@@ -57,7 +57,7 @@ class DialPadFragment : Fragment() {
dialpadView.findViewById(R.id.dialpad_key_voicemail).isVisible = false
digits = dialpadView.digits as? DigitsEditText
digits?.isCursorVisible = cursorVisible
- digits?.setTextColor(ThemeUtils.getColor(requireContext(), im.vector.app.R.attr.riotx_text_primary))
+ digits?.setTextColor(ThemeUtils.getColor(requireContext(), im.vector.app.R.attr.vctr_content_primary))
dialpadView.findViewById(R.id.zero).setOnClickListener { append('0') }
if (enablePlus) {
dialpadView.findViewById(R.id.zero).setOnLongClickListener {
@@ -91,7 +91,7 @@ class DialPadFragment : Fragment() {
clear()
true
}
- val tintColor = ThemeUtils.getColor(requireContext(), im.vector.app.R.attr.riotx_text_secondary)
+ val tintColor = ThemeUtils.getColor(requireContext(), im.vector.app.R.attr.vctr_content_secondary)
ImageViewCompat.setImageTintList(dialpadView.deleteButton, ColorStateList.valueOf(tintColor))
} else {
dialpadView.deleteButton.isVisible = false
diff --git a/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCall.kt b/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCall.kt
index f2a008feb7..c688c48429 100644
--- a/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCall.kt
+++ b/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCall.kt
@@ -618,7 +618,7 @@ class WebRtcCall(
wasLocalOnHold = isLocalOnHold
remoteOnHold = true
isLocalOnHold = true
- direction = RtpTransceiver.RtpTransceiverDirection.INACTIVE
+ direction = RtpTransceiver.RtpTransceiverDirection.SEND_ONLY
timer.pause()
} else {
remoteOnHold = false
diff --git a/vector/src/main/java/im/vector/app/features/consent/ConsentNotGivenHelper.kt b/vector/src/main/java/im/vector/app/features/consent/ConsentNotGivenHelper.kt
index dbcc2c1820..9f6aa8cdd8 100644
--- a/vector/src/main/java/im/vector/app/features/consent/ConsentNotGivenHelper.kt
+++ b/vector/src/main/java/im/vector/app/features/consent/ConsentNotGivenHelper.kt
@@ -17,7 +17,7 @@
package im.vector.app.features.consent
import android.app.Activity
-import androidx.appcompat.app.AlertDialog
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.dialogs.DialogLocker
import im.vector.app.core.platform.Restorable
@@ -37,7 +37,7 @@ class ConsentNotGivenHelper(private val activity: Activity,
*/
fun displayDialog(consentUri: String, homeServerHost: String) {
dialogLocker.displayDialog {
- AlertDialog.Builder(activity)
+ MaterialAlertDialogBuilder(activity)
.setTitle(R.string.settings_app_term_conditions)
.setMessage(activity.getString(R.string.dialog_user_consent_content, homeServerHost))
.setPositiveButton(R.string.dialog_user_consent_submit) { _, _ ->
diff --git a/vector/src/main/java/im/vector/app/features/contactsbook/ContactDetailItem.kt b/vector/src/main/java/im/vector/app/features/contactsbook/ContactDetailItem.kt
index aba530b2fb..fbf404b74d 100644
--- a/vector/src/main/java/im/vector/app/features/contactsbook/ContactDetailItem.kt
+++ b/vector/src/main/java/im/vector/app/features/contactsbook/ContactDetailItem.kt
@@ -31,7 +31,9 @@ abstract class ContactDetailItem : VectorEpoxyModel()
@EpoxyAttribute lateinit var threePid: String
@EpoxyAttribute var matrixId: String? = null
- @EpoxyAttribute var clickListener: ClickListener? = null
+
+ @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
+ var clickListener: ClickListener? = null
override fun bind(holder: Holder) {
super.bind(holder)
diff --git a/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookController.kt b/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookController.kt
index 5da66661fd..05a2bf641b 100644
--- a/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookController.kt
+++ b/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookController.kt
@@ -95,35 +95,35 @@ class ContactsBookController @Inject constructor(
avatarRenderer(host.avatarRenderer)
}
mappedContact.emails
- .forEachIndexed { index, it ->
- if (onlyBoundContacts && it.matrixId == null) return@forEachIndexed
+ .forEachIndexed { index, email ->
+ if (onlyBoundContacts && email.matrixId == null) return@forEachIndexed
contactDetailItem {
- id("${mappedContact.id}-e-$index-${it.email}")
- threePid(it.email)
- matrixId(it.matrixId)
+ id("${mappedContact.id}-e-$index-${email.email}")
+ threePid(email.email)
+ matrixId(email.matrixId)
clickListener {
- if (it.matrixId != null) {
- host.callback?.onMatrixIdClick(it.matrixId)
+ if (email.matrixId != null) {
+ host.callback?.onMatrixIdClick(email.matrixId)
} else {
- host.callback?.onThreePidClick(ThreePid.Email(it.email))
+ host.callback?.onThreePidClick(ThreePid.Email(email.email))
}
}
}
}
mappedContact.msisdns
- .forEachIndexed { index, it ->
- if (onlyBoundContacts && it.matrixId == null) return@forEachIndexed
+ .forEachIndexed { index, msisdn ->
+ if (onlyBoundContacts && msisdn.matrixId == null) return@forEachIndexed
contactDetailItem {
- id("${mappedContact.id}-m-$index-${it.phoneNumber}")
- threePid(it.phoneNumber)
- matrixId(it.matrixId)
+ id("${mappedContact.id}-m-$index-${msisdn.phoneNumber}")
+ threePid(msisdn.phoneNumber)
+ matrixId(msisdn.matrixId)
clickListener {
- if (it.matrixId != null) {
- host.callback?.onMatrixIdClick(it.matrixId)
+ if (msisdn.matrixId != null) {
+ host.callback?.onMatrixIdClick(msisdn.matrixId)
} else {
- host.callback?.onThreePidClick(ThreePid.Msisdn(it.phoneNumber))
+ host.callback?.onThreePidClick(ThreePid.Msisdn(msisdn.phoneNumber))
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookFragment.kt b/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookFragment.kt
index 68e169b8c5..9291352821 100644
--- a/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookFragment.kt
@@ -20,10 +20,10 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import androidx.appcompat.app.AlertDialog
import androidx.core.view.isVisible
import com.airbnb.mvrx.activityViewModel
import com.airbnb.mvrx.withState
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.jakewharton.rxbinding3.widget.checkedChanges
import com.jakewharton.rxbinding3.widget.textChanges
import im.vector.app.R
@@ -76,7 +76,7 @@ class ContactsBookFragment @Inject constructor(
private fun setupConsentView() {
views.phoneBookSearchForMatrixContacts.setOnClickListener {
withState(contactsBookViewModel) { state ->
- AlertDialog.Builder(requireActivity())
+ MaterialAlertDialogBuilder(requireActivity())
.setTitle(R.string.identity_server_consent_dialog_title)
.setMessage(getString(R.string.identity_server_consent_dialog_content, state.identityServerUrl ?: ""))
.setPositiveButton(R.string.yes) { _, _ ->
diff --git a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt
index 4f81841b73..4aa5f023c4 100644
--- a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt
@@ -22,12 +22,12 @@ import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.View
-import androidx.appcompat.app.AlertDialog
import com.airbnb.mvrx.Async
import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.Success
import com.airbnb.mvrx.viewModel
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.error.ErrorFormatter
@@ -171,7 +171,7 @@ class CreateDirectRoomActivity : SimpleFragmentActivity(), UserListViewModel.Fac
finish()
}
is CreateRoomFailure.CreatedWithFederationFailure -> {
- AlertDialog.Builder(this)
+ MaterialAlertDialogBuilder(this)
.setMessage(getString(R.string.create_room_federation_error, error.matrixError.message))
.setCancelable(false)
.setPositiveButton(R.string.ok) { _, _ -> finish() }
@@ -184,7 +184,7 @@ class CreateDirectRoomActivity : SimpleFragmentActivity(), UserListViewModel.Fac
} else {
errorFormatter.toHumanReadable(error)
}
- AlertDialog.Builder(this)
+ MaterialAlertDialogBuilder(this)
.setMessage(message)
.setPositiveButton(R.string.ok, null)
.show()
diff --git a/vector/src/main/java/im/vector/app/features/crypto/keys/KeysExporter.kt b/vector/src/main/java/im/vector/app/features/crypto/keys/KeysExporter.kt
index c7e4c26385..2c66a14cb4 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/keys/KeysExporter.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/keys/KeysExporter.kt
@@ -18,35 +18,24 @@ package im.vector.app.features.crypto.keys
import android.content.Context
import android.net.Uri
-import im.vector.app.features.session.coroutineScope
import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
-import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.session.Session
-import org.matrix.android.sdk.internal.extensions.foldToCallback
-import org.matrix.android.sdk.internal.util.awaitCallback
-
-class KeysExporter(private val session: Session) {
+import javax.inject.Inject
+class KeysExporter @Inject constructor(
+ private val session: Session,
+ private val context: Context
+) {
/**
- * Export keys and return the file path with the callback
+ * Export keys and write them to the provided uri
*/
- fun export(context: Context, password: String, uri: Uri, callback: MatrixCallback) {
- session.coroutineScope.launch(Dispatchers.Main) {
- runCatching {
- withContext(Dispatchers.IO) {
- val data = awaitCallback { session.cryptoService().exportRoomKeys(password, it) }
- val os = context.contentResolver?.openOutputStream(uri)
- if (os == null) {
- false
- } else {
- os.write(data)
- os.flush()
- true
- }
- }
- }.foldToCallback(callback)
+ suspend fun export(password: String, uri: Uri) {
+ return withContext(Dispatchers.IO) {
+ val data = session.cryptoService().exportRoomKeys(password)
+ context.contentResolver.openOutputStream(uri)
+ ?.use { it.write(data) }
+ ?: throw IllegalStateException("Unable to open file for writting")
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/crypto/keys/KeysImporter.kt b/vector/src/main/java/im/vector/app/features/crypto/keys/KeysImporter.kt
index 3d93b26edd..50c85c3e5f 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/keys/KeysImporter.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/keys/KeysImporter.kt
@@ -20,49 +20,27 @@ import android.content.Context
import android.net.Uri
import im.vector.app.core.intent.getMimeTypeFromUri
import im.vector.app.core.resources.openResource
-import im.vector.app.features.session.coroutineScope
import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
-import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult
-import org.matrix.android.sdk.internal.extensions.foldToCallback
-import org.matrix.android.sdk.internal.util.awaitCallback
-import timber.log.Timber
-
-class KeysImporter(private val session: Session) {
+import javax.inject.Inject
+class KeysImporter @Inject constructor(
+ private val context: Context,
+ private val session: Session
+) {
/**
* Import keys from provided Uri
*/
- fun import(context: Context,
- uri: Uri,
- mimetype: String?,
- password: String,
- callback: MatrixCallback) {
- session.coroutineScope.launch(Dispatchers.Main) {
- runCatching {
- withContext(Dispatchers.IO) {
- val resource = openResource(context, uri, mimetype ?: getMimeTypeFromUri(context, uri))
-
- if (resource?.mContentStream == null) {
- throw Exception("Error")
- }
-
- val data: ByteArray
- try {
- data = resource.mContentStream!!.use { it.readBytes() }
- } catch (e: Exception) {
- Timber.e(e, "## importKeys()")
- throw e
- }
-
- awaitCallback {
- session.cryptoService().importRoomKeys(data, password, null, it)
- }
- }
- }.foldToCallback(callback)
+ suspend fun import(uri: Uri,
+ mimetype: String?,
+ password: String): ImportRoomKeysResult {
+ return withContext(Dispatchers.IO) {
+ val resource = openResource(context, uri, mimetype ?: getMimeTypeFromUri(context, uri))
+ val stream = resource?.mContentStream ?: throw Exception("Error")
+ val data = stream.use { it.readBytes() }
+ session.cryptoService().importRoomKeys(data, password, null)
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreActivity.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreActivity.kt
index 20ecbb4e5a..e80853b035 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreActivity.kt
@@ -18,7 +18,7 @@ package im.vector.app.features.crypto.keysbackup.restore
import android.app.Activity
import android.content.Context
import android.content.Intent
-import androidx.appcompat.app.AlertDialog
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.extensions.addFragmentToBackstack
import im.vector.app.core.extensions.observeEvent
@@ -66,7 +66,7 @@ class KeysBackupRestoreActivity : SimpleFragmentActivity() {
}
viewModel.keyVersionResultError.observeEvent(this) { message ->
- AlertDialog.Builder(this)
+ MaterialAlertDialogBuilder(this)
.setTitle(R.string.unknown_error)
.setMessage(message)
.setCancelable(false)
@@ -97,7 +97,7 @@ class KeysBackupRestoreActivity : SimpleFragmentActivity() {
launch4SActivity()
}
KeysBackupRestoreSharedViewModel.NAVIGATE_FAILED_TO_LOAD_4S -> {
- AlertDialog.Builder(this)
+ MaterialAlertDialogBuilder(this)
.setTitle(R.string.unknown_error)
.setMessage(R.string.error_failed_to_import_keys)
.setCancelable(false)
diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreSharedViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreSharedViewModel.kt
index f8290c0321..c323024bd9 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreSharedViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreSharedViewModel.kt
@@ -252,7 +252,7 @@ class KeysBackupRestoreSharedViewModel @Inject constructor(
}
private fun isBackupKeyInQuadS(): Boolean {
- val sssBackupSecret = session.userAccountDataService().getAccountDataEvent(KEYBACKUP_SECRET_SSSS_NAME)
+ val sssBackupSecret = session.accountDataService().getUserAccountDataEvent(KEYBACKUP_SECRET_SSSS_NAME)
?: return false
// Some sanity ?
diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupManageActivity.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupManageActivity.kt
index c4a4e06fcf..d78fa37d62 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupManageActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupManageActivity.kt
@@ -17,10 +17,10 @@ package im.vector.app.features.crypto.keysbackup.settings
import android.content.Context
import android.content.Intent
-import androidx.appcompat.app.AlertDialog
import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.viewModel
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.extensions.replaceFragment
@@ -60,7 +60,7 @@ class KeysBackupManageActivity : SimpleFragmentActivity() {
is Fail -> {
updateWaitingView(null)
- AlertDialog.Builder(this)
+ MaterialAlertDialogBuilder(this)
.setTitle(R.string.unknown_error)
.setMessage(getString(R.string.keys_backup_get_version_error, asyncDelete.error.localizedMessage))
.setCancelable(false)
diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingFooterItem.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingFooterItem.kt
index 0489f18abe..69551cac93 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingFooterItem.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingFooterItem.kt
@@ -16,14 +16,15 @@
package im.vector.app.features.crypto.keysbackup.settings
-import android.view.View
import android.widget.Button
import android.widget.TextView
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
+import im.vector.app.core.epoxy.ClickListener
import im.vector.app.core.epoxy.VectorEpoxyHolder
import im.vector.app.core.epoxy.VectorEpoxyModel
+import im.vector.app.core.epoxy.onClick
import im.vector.app.core.extensions.setTextOrHide
@EpoxyModelClass(layout = R.layout.item_keys_backup_settings_button_footer)
@@ -32,22 +33,22 @@ abstract class KeysBackupSettingFooterItem : VectorEpoxyModel {
- AlertDialog.Builder(this)
+ MaterialAlertDialogBuilder(this)
.setTitle(R.string.keys_backup_setup_override_backup_prompt_tile)
.setMessage(R.string.keys_backup_setup_override_backup_prompt_description)
.setPositiveButton(R.string.keys_backup_setup_override_replace) { _, _ ->
@@ -100,7 +111,7 @@ class KeysBackupSetupActivity : SimpleFragmentActivity() {
viewModel.prepareRecoverFailError.observe(this) { error ->
if (error != null) {
- AlertDialog.Builder(this)
+ MaterialAlertDialogBuilder(this)
.setTitle(R.string.unknown_error)
.setMessage(error.localizedMessage)
.setPositiveButton(R.string.ok) { _, _ ->
@@ -113,7 +124,7 @@ class KeysBackupSetupActivity : SimpleFragmentActivity() {
viewModel.creatingBackupError.observe(this) { error ->
if (error != null) {
- AlertDialog.Builder(this)
+ MaterialAlertDialogBuilder(this)
.setTitle(R.string.unexpected_error)
.setMessage(error.localizedMessage)
.setPositiveButton(R.string.ok) { _, _ ->
@@ -132,30 +143,7 @@ class KeysBackupSetupActivity : SimpleFragmentActivity() {
ExportKeysDialog().show(this, object : ExportKeysDialog.ExportKeyDialogListener {
override fun onPassphrase(passphrase: String) {
showWaitingView()
-
- KeysExporter(session)
- .export(this@KeysBackupSetupActivity,
- passphrase,
- uri,
- object : MatrixCallback {
- override fun onSuccess(data: Boolean) {
- if (data) {
- toast(getString(R.string.encryption_exported_successfully))
- Intent().apply {
- putExtra(MANUAL_EXPORT, true)
- }.let {
- setResult(Activity.RESULT_OK, it)
- finish()
- }
- }
- hideWaitingView()
- }
-
- override fun onFailure(failure: Throwable) {
- toast(failure.localizedMessage ?: getString(R.string.unexpected_error))
- hideWaitingView()
- }
- })
+ export(passphrase, uri)
}
})
} else {
@@ -165,12 +153,26 @@ class KeysBackupSetupActivity : SimpleFragmentActivity() {
}
}
+ private fun export(passphrase: String, uri: Uri) {
+ lifecycleScope.launch {
+ try {
+ keysExporter.export(passphrase, uri)
+ toast(getString(R.string.encryption_exported_successfully))
+ setResult(Activity.RESULT_OK, Intent().apply { putExtra(MANUAL_EXPORT, true) })
+ finish()
+ } catch (failure: Throwable) {
+ toast(failure.localizedMessage ?: getString(R.string.unexpected_error))
+ }
+ hideWaitingView()
+ }
+ }
+
override fun onBackPressed() {
if (viewModel.shouldPromptOnBack) {
if (waitingView?.isVisible == true) {
return
}
- AlertDialog.Builder(this)
+ MaterialAlertDialogBuilder(this)
.setTitle(R.string.keys_backup_setup_skip_title)
.setMessage(R.string.keys_backup_setup_skip_msg)
.setNegativeButton(R.string.cancel, null)
diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupStep3Fragment.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupStep3Fragment.kt
index 8833702e35..5739da11bb 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupStep3Fragment.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupStep3Fragment.kt
@@ -23,11 +23,11 @@ import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import android.widget.Toast
-import androidx.appcompat.app.AlertDialog
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import arrow.core.Try
import com.google.android.material.bottomsheet.BottomSheetDialog
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.platform.VectorBaseFragment
@@ -177,7 +177,7 @@ class KeysBackupSetupStep3Fragment @Inject constructor() : VectorBaseFragment
activity?.let {
- AlertDialog.Builder(it)
+ MaterialAlertDialogBuilder(it)
.setTitle(R.string.dialog_title_error)
.setMessage(errorFormatter.toHumanReadable(throwable))
}
@@ -185,7 +185,7 @@ class KeysBackupSetupStep3Fragment @Inject constructor() : VectorBaseFragment {
- AlertDialog.Builder(this)
+ MaterialAlertDialogBuilder(this)
.setTitle(getString(R.string.dialog_title_error))
.setMessage(it.message)
.setCancelable(false)
diff --git a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModel.kt
index f55b482124..d246d33f40 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModel.kt
@@ -218,7 +218,7 @@ class SharedSecureStorageViewModel @AssistedInject constructor(
withContext(Dispatchers.IO) {
args.requestedSecrets.forEach {
- if (session.userAccountDataService().getAccountDataEvent(it) != null) {
+ if (session.accountDataService().getUserAccountDataEvent(it) != null) {
val res = session.sharedSecretStorageService.getSecret(
name = it,
keyId = keyInfo.id,
@@ -287,7 +287,7 @@ class SharedSecureStorageViewModel @AssistedInject constructor(
withContext(Dispatchers.IO) {
args.requestedSecrets.forEach {
- if (session.userAccountDataService().getAccountDataEvent(it) != null) {
+ if (session.accountDataService().getUserAccountDataEvent(it) != null) {
val res = session.sharedSecretStorageService.getSecret(
name = it,
keyId = keyInfo.id,
diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapBottomSheet.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapBottomSheet.kt
index 5cc86fdf15..a42c3d2dda 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapBottomSheet.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapBottomSheet.kt
@@ -26,13 +26,13 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
-import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.extensions.commitTransaction
@@ -96,7 +96,7 @@ class BootstrapBottomSheet : VectorBaseBottomSheetDialogFragment {
- AlertDialog.Builder(requireActivity())
+ MaterialAlertDialogBuilder(requireActivity())
.setTitle(R.string.dialog_title_error)
.setMessage(event.error)
.setPositiveButton(R.string.ok, null)
@@ -121,7 +121,7 @@ class BootstrapBottomSheet : VectorBaseBottomSheetDialogFragment {
return mutableListOf(
- // RiotX supports SAS verification
+ // Element supports SAS verification
VerificationMethod.SAS,
- // RiotX is able to show QR codes
+ // Element is able to show QR codes
VerificationMethod.QR_CODE_SHOW)
.apply {
if (hardwareInfo.hasBackCamera()) {
- // RiotX is able to scan QR codes, and a Camera is available
+ // Element is able to scan QR codes, and a Camera is available
add(VerificationMethod.QR_CODE_SCAN)
} else {
// This quite uncommon
diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheet.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheet.kt
index 8d15249c11..47033199f4 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheet.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheet.kt
@@ -23,11 +23,11 @@ import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.Fragment
import com.airbnb.mvrx.MvRx
import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.extensions.commitTransaction
@@ -109,7 +109,7 @@ class VerificationBottomSheet : VectorBaseBottomSheetDialogFragment {
- AlertDialog.Builder(requireContext())
+ MaterialAlertDialogBuilder(requireContext())
.setTitle(getString(R.string.dialog_title_error))
.setMessage(it.errorMessage)
.setCancelable(false)
diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationCancelController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationCancelController.kt
index b36b2e2baa..f10aa3421f 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationCancelController.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationCancelController.kt
@@ -19,7 +19,7 @@ package im.vector.app.features.crypto.verification.cancel
import androidx.core.text.toSpannable
import com.airbnb.epoxy.EpoxyController
import im.vector.app.R
-import im.vector.app.core.epoxy.dividerItem
+import im.vector.app.core.epoxy.bottomSheetDividerItem
import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.utils.colorizeMatchingText
@@ -70,29 +70,29 @@ class VerificationCancelController @Inject constructor(
}
}
- dividerItem {
+ bottomSheetDividerItem {
id("sep0")
}
bottomSheetVerificationActionItem {
id("cancel")
title(host.stringProvider.getString(R.string.skip))
- titleColor(host.colorProvider.getColor(R.color.riotx_destructive_accent))
+ titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorError))
iconRes(R.drawable.ic_arrow_right)
- iconColor(host.colorProvider.getColor(R.color.riotx_destructive_accent))
+ iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorError))
listener { host.listener?.onTapCancel() }
}
- dividerItem {
+ bottomSheetDividerItem {
id("sep1")
}
bottomSheetVerificationActionItem {
id("continue")
title(host.stringProvider.getString(R.string._continue))
- titleColor(host.colorProvider.getColor(R.color.riotx_positive_accent))
+ titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary))
iconRes(R.drawable.ic_arrow_right)
- iconColor(host.colorProvider.getColor(R.color.riotx_positive_accent))
+ iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary))
listener { host.listener?.onTapContinue() }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationNotMeController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationNotMeController.kt
index 97ff79c933..d816f3d134 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationNotMeController.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationNotMeController.kt
@@ -18,7 +18,7 @@ package im.vector.app.features.crypto.verification.cancel
import com.airbnb.epoxy.EpoxyController
import im.vector.app.R
-import im.vector.app.core.epoxy.dividerItem
+import im.vector.app.core.epoxy.bottomSheetDividerItem
import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.crypto.verification.VerificationBottomSheetViewState
@@ -49,29 +49,29 @@ class VerificationNotMeController @Inject constructor(
notice(host.eventHtmlRenderer.render(host.stringProvider.getString(R.string.verify_not_me_self_verification)))
}
- dividerItem {
+ bottomSheetDividerItem {
id("sep0")
}
bottomSheetVerificationActionItem {
id("skip")
title(host.stringProvider.getString(R.string.skip))
- titleColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
+ titleColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary))
iconRes(R.drawable.ic_arrow_right)
- iconColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
+ iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary))
listener { host.listener?.onTapSkip() }
}
- dividerItem {
+ bottomSheetDividerItem {
id("sep1")
}
bottomSheetVerificationActionItem {
id("settings")
title(host.stringProvider.getString(R.string.settings))
- titleColor(host.colorProvider.getColor(R.color.riotx_positive_accent))
+ titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary))
iconRes(R.drawable.ic_arrow_right)
- iconColor(host.colorProvider.getColor(R.color.riotx_positive_accent))
+ iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary))
listener { host.listener?.onTapSettings() }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodController.kt
index be727a3243..1202a22042 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodController.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodController.kt
@@ -18,7 +18,7 @@ package im.vector.app.features.crypto.verification.choose
import com.airbnb.epoxy.EpoxyController
import im.vector.app.R
-import im.vector.app.core.epoxy.dividerItem
+import im.vector.app.core.epoxy.bottomSheetDividerItem
import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem
@@ -56,7 +56,7 @@ class VerificationChooseMethodController @Inject constructor(
data(state.qrCodeText)
}
- dividerItem {
+ bottomSheetDividerItem {
id("sep0")
}
}
@@ -65,13 +65,13 @@ class VerificationChooseMethodController @Inject constructor(
bottomSheetVerificationActionItem {
id("openCamera")
title(host.stringProvider.getString(R.string.verification_scan_their_code))
- titleColor(host.colorProvider.getColor(R.color.riotx_accent))
+ titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary))
iconRes(R.drawable.ic_camera)
- iconColor(host.colorProvider.getColor(R.color.riotx_accent))
+ iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary))
listener { host.listener?.openCamera() }
}
- dividerItem {
+ bottomSheetDividerItem {
id("sep1")
}
}
@@ -79,35 +79,35 @@ class VerificationChooseMethodController @Inject constructor(
bottomSheetVerificationActionItem {
id("openEmoji")
title(host.stringProvider.getString(R.string.verification_scan_emoji_title))
- titleColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
+ titleColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary))
subTitle(host.stringProvider.getString(R.string.verification_scan_emoji_subtitle))
iconRes(R.drawable.ic_arrow_right)
- iconColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
+ iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary))
listener { host.listener?.doVerifyBySas() }
}
} else if (state.sasModeAvailable) {
bottomSheetVerificationActionItem {
id("openEmoji")
title(host.stringProvider.getString(R.string.verification_no_scan_emoji_title))
- titleColor(host.colorProvider.getColor(R.color.riotx_accent))
+ titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary))
iconRes(R.drawable.ic_arrow_right)
- iconColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
+ iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary))
listener { host.listener?.doVerifyBySas() }
}
}
if (state.isMe && state.canCrossSign) {
- dividerItem {
+ bottomSheetDividerItem {
id("sep_notMe")
}
bottomSheetVerificationActionItem {
id("wasnote")
title(host.stringProvider.getString(R.string.verify_new_session_was_not_me))
- titleColor(host.colorProvider.getColor(R.color.riotx_destructive_accent))
+ titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorError))
subTitle(host.stringProvider.getString(R.string.verify_new_session_compromized))
iconRes(R.drawable.ic_arrow_right)
- iconColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
+ iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary))
listener { host.listener?.onClickOnWasNotMe() }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/conclusion/VerificationConclusionController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/conclusion/VerificationConclusionController.kt
index 49b3c07e78..1984a70345 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/verification/conclusion/VerificationConclusionController.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/verification/conclusion/VerificationConclusionController.kt
@@ -18,7 +18,7 @@ package im.vector.app.features.crypto.verification.conclusion
import com.airbnb.epoxy.EpoxyController
import im.vector.app.R
-import im.vector.app.core.epoxy.dividerItem
+import im.vector.app.core.epoxy.bottomSheetDividerItem
import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem
@@ -87,16 +87,16 @@ class VerificationConclusionController @Inject constructor(
notice(host.stringProvider.getString(R.string.verify_cancelled_notice))
}
- dividerItem {
+ bottomSheetDividerItem {
id("sep0")
}
bottomSheetVerificationActionItem {
id("got_it")
title(host.stringProvider.getString(R.string.sas_got_it))
- titleColor(host.colorProvider.getColor(R.color.riotx_accent))
+ titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary))
iconRes(R.drawable.ic_arrow_right)
- iconColor(host.colorProvider.getColor(R.color.riotx_accent))
+ iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary))
listener { host.listener?.onButtonTapped() }
}
}
@@ -105,16 +105,16 @@ class VerificationConclusionController @Inject constructor(
private fun bottomDone() {
val host = this
- dividerItem {
+ bottomSheetDividerItem {
id("sep0")
}
bottomSheetVerificationActionItem {
id("done")
title(host.stringProvider.getString(R.string.done))
- titleColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
+ titleColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary))
iconRes(R.drawable.ic_arrow_right)
- iconColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
+ iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary))
listener { host.listener?.onButtonTapped() }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeController.kt
index fd939fe11f..5159a69090 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeController.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeController.kt
@@ -20,7 +20,7 @@ import com.airbnb.epoxy.EpoxyController
import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Success
import im.vector.app.R
-import im.vector.app.core.epoxy.dividerItem
+import im.vector.app.core.epoxy.bottomSheetDividerItem
import im.vector.app.core.epoxy.errorWithRetryItem
import im.vector.app.core.error.ErrorFormatter
import im.vector.app.core.resources.ColorProvider
@@ -127,7 +127,7 @@ class VerificationEmojiCodeController @Inject constructor(
private fun buildActions(state: VerificationEmojiCodeViewState) {
val host = this
- dividerItem {
+ bottomSheetDividerItem {
id("sep0")
}
@@ -140,20 +140,20 @@ class VerificationEmojiCodeController @Inject constructor(
bottomSheetVerificationActionItem {
id("ko")
title(host.stringProvider.getString(R.string.verification_sas_do_not_match))
- titleColor(host.colorProvider.getColor(R.color.vector_error_color))
+ titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorError))
iconRes(R.drawable.ic_check_off)
- iconColor(host.colorProvider.getColor(R.color.vector_error_color))
+ iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorError))
listener { host.listener?.onDoNotMatchButtonTapped() }
}
- dividerItem {
+ bottomSheetDividerItem {
id("sep1")
}
bottomSheetVerificationActionItem {
id("ok")
title(host.stringProvider.getString(R.string.verification_sas_match))
- titleColor(host.colorProvider.getColor(R.color.riotx_accent))
+ titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary))
iconRes(R.drawable.ic_check_on)
- iconColor(host.colorProvider.getColor(R.color.riotx_accent))
+ iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary))
listener { host.listener?.onMatchButtonTapped() }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/epoxy/BottomSheetVerificationActionItem.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/epoxy/BottomSheetVerificationActionItem.kt
index d738efe3ba..093eddb45e 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/verification/epoxy/BottomSheetVerificationActionItem.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/verification/epoxy/BottomSheetVerificationActionItem.kt
@@ -25,8 +25,10 @@ import androidx.core.widget.ImageViewCompat
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
+import im.vector.app.core.epoxy.ClickListener
import im.vector.app.core.epoxy.VectorEpoxyHolder
import im.vector.app.core.epoxy.VectorEpoxyModel
+import im.vector.app.core.epoxy.onClick
import im.vector.app.core.extensions.setTextOrHide
/**
@@ -51,15 +53,12 @@ abstract class BottomSheetVerificationActionItem : VectorEpoxyModel Unit
+ @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
+ lateinit var listener: ClickListener
override fun bind(holder: Holder) {
super.bind(holder)
- holder.view.setOnClickListener {
- listener.invoke()
- }
-
+ holder.view.onClick(listener)
holder.title.text = title
holder.title.setTextColor(titleColor)
diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt
index d617b70c67..01862a5ab4 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt
@@ -18,7 +18,7 @@ package im.vector.app.features.crypto.verification.qrconfirmation
import com.airbnb.epoxy.EpoxyController
import im.vector.app.R
-import im.vector.app.core.epoxy.dividerItem
+import im.vector.app.core.epoxy.bottomSheetDividerItem
import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.crypto.verification.VerificationBottomSheetViewState
@@ -63,29 +63,29 @@ class VerificationQrScannedByOtherController @Inject constructor(
roomEncryptionTrustLevel(RoomEncryptionTrustLevel.Trusted)
}
- dividerItem {
+ bottomSheetDividerItem {
id("sep0")
}
bottomSheetVerificationActionItem {
id("deny")
title(host.stringProvider.getString(R.string.qr_code_scanned_by_other_no))
- titleColor(host.colorProvider.getColor(R.color.vector_error_color))
+ titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorError))
iconRes(R.drawable.ic_check_off)
- iconColor(host.colorProvider.getColor(R.color.vector_error_color))
+ iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorError))
listener { host.listener?.onUserDeniesQrCodeScanned() }
}
- dividerItem {
+ bottomSheetDividerItem {
id("sep1")
}
bottomSheetVerificationActionItem {
id("confirm")
title(host.stringProvider.getString(R.string.qr_code_scanned_by_other_yes))
- titleColor(host.colorProvider.getColor(R.color.riotx_accent))
+ titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary))
iconRes(R.drawable.ic_check_on)
- iconColor(host.colorProvider.getColor(R.color.riotx_accent))
+ iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary))
listener { host.listener?.onUserConfirmsQrCodeScanned() }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestController.kt
index ac063f2545..260bcf597e 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestController.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestController.kt
@@ -22,7 +22,7 @@ import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.Success
import com.airbnb.mvrx.Uninitialized
import im.vector.app.R
-import im.vector.app.core.epoxy.dividerItem
+import im.vector.app.core.epoxy.bottomSheetDividerItem
import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.utils.colorizeMatchingText
@@ -63,7 +63,7 @@ class VerificationRequestController @Inject constructor(
id("waiting")
}
- dividerItem {
+ bottomSheetDividerItem {
id("sep")
}
}
@@ -77,24 +77,24 @@ class VerificationRequestController @Inject constructor(
bottomSheetVerificationActionItem {
id("passphrase")
title(host.stringProvider.getString(R.string.verification_cannot_access_other_session))
- titleColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
+ titleColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary))
subTitle(subtitle)
iconRes(R.drawable.ic_arrow_right)
- iconColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
+ iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary))
listener { host.listener?.onClickRecoverFromPassphrase() }
}
}
- dividerItem {
+ bottomSheetDividerItem {
id("sep1")
}
bottomSheetVerificationActionItem {
id("skip")
title(host.stringProvider.getString(R.string.skip))
- titleColor(host.colorProvider.getColor(R.color.riotx_destructive_accent))
+ titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorError))
iconRes(R.drawable.ic_arrow_right)
- iconColor(host.colorProvider.getColor(R.color.riotx_destructive_accent))
+ iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorError))
listener { host.listener?.onClickSkip() }
}
} else {
@@ -114,7 +114,7 @@ class VerificationRequestController @Inject constructor(
notice(styledText)
}
- dividerItem {
+ bottomSheetDividerItem {
id("sep")
}
@@ -123,10 +123,10 @@ class VerificationRequestController @Inject constructor(
bottomSheetVerificationActionItem {
id("start")
title(host.stringProvider.getString(R.string.start_verification))
- titleColor(host.colorProvider.getColor(R.color.riotx_accent))
+ titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary))
subTitle(host.stringProvider.getString(R.string.verification_request_start_notice))
iconRes(R.drawable.ic_arrow_right)
- iconColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
+ iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary))
listener { host.listener?.onClickOnVerificationStart() }
}
}
@@ -155,17 +155,17 @@ class VerificationRequestController @Inject constructor(
}
if (state.isMe && state.currentDeviceCanCrossSign && !state.selfVerificationMode) {
- dividerItem {
+ bottomSheetDividerItem {
id("sep_notMe")
}
bottomSheetVerificationActionItem {
id("wasnote")
title(host.stringProvider.getString(R.string.verify_new_session_was_not_me))
- titleColor(host.colorProvider.getColor(R.color.riotx_destructive_accent))
+ titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorError))
subTitle(host.stringProvider.getString(R.string.verify_new_session_compromized))
iconRes(R.drawable.ic_arrow_right)
- iconColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
+ iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary))
listener { host.listener?.onClickOnWasNotMe() }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolActivity.kt b/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolActivity.kt
index 31b495a4d4..c502d92a4c 100644
--- a/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolActivity.kt
@@ -22,7 +22,6 @@ import android.os.Bundle
import android.os.Parcelable
import android.view.Menu
import android.view.MenuItem
-import androidx.appcompat.app.AlertDialog
import androidx.core.view.forEach
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
@@ -33,6 +32,7 @@ import com.airbnb.mvrx.Success
import com.airbnb.mvrx.Uninitialized
import com.airbnb.mvrx.viewModel
import com.airbnb.mvrx.withState
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.extensions.exhaustive
@@ -84,7 +84,7 @@ class RoomDevToolActivity : SimpleFragmentActivity(), RoomDevToolViewModel.Facto
when (it) {
DevToolsViewEvents.Dismiss -> finish()
is DevToolsViewEvents.ShowAlertMessage -> {
- AlertDialog.Builder(this)
+ MaterialAlertDialogBuilder(this)
.setMessage(it.message)
.setPositiveButton(R.string.ok, null)
.show()
diff --git a/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolFragment.kt b/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolFragment.kt
index 0cc2a69bcf..0e1a2418b8 100644
--- a/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolFragment.kt
@@ -21,6 +21,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.airbnb.mvrx.activityViewModel
+import im.vector.app.R
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
import im.vector.app.core.platform.VectorBaseFragment
@@ -40,7 +41,7 @@ class RoomDevToolFragment @Inject constructor(
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- views.genericRecyclerView.configureWith(epoxyController, showDivider = true)
+ views.genericRecyclerView.configureWith(epoxyController, dividerDrawable = R.drawable.divider_horizontal)
epoxyController.interactionListener = this
// sharedViewModel.observeViewEvents {
diff --git a/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolRootController.kt b/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolRootController.kt
index ed0a58231e..ed52deeade 100644
--- a/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolRootController.kt
+++ b/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolRootController.kt
@@ -16,7 +16,6 @@
package im.vector.app.features.devtools
-import android.view.View
import com.airbnb.epoxy.EpoxyController
import im.vector.app.R
import im.vector.app.core.resources.StringProvider
@@ -38,23 +37,23 @@ class RoomDevToolRootController @Inject constructor(
genericButtonItem {
id("explore")
text(host.stringProvider.getString(R.string.dev_tools_explore_room_state))
- buttonClickAction(View.OnClickListener {
+ buttonClickAction {
host.interactionListener?.processAction(RoomDevToolAction.ExploreRoomState)
- })
+ }
}
genericButtonItem {
id("send")
text(host.stringProvider.getString(R.string.dev_tools_send_custom_event))
- buttonClickAction(View.OnClickListener {
+ buttonClickAction {
host.interactionListener?.processAction(RoomDevToolAction.SendCustomEvent(false))
- })
+ }
}
genericButtonItem {
id("send_state")
text(host.stringProvider.getString(R.string.dev_tools_send_state_event))
- buttonClickAction(View.OnClickListener {
+ buttonClickAction {
host.interactionListener?.processAction(RoomDevToolAction.SendCustomEvent(true))
- })
+ }
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolSendFormController.kt b/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolSendFormController.kt
index 8f8b8257b1..75fcf43292 100644
--- a/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolSendFormController.kt
+++ b/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolSendFormController.kt
@@ -43,7 +43,6 @@ class RoomDevToolSendFormController @Inject constructor(
enabled(true)
value(data.sendEventDraft?.type)
hint(host.stringProvider.getString(R.string.dev_tools_form_hint_type))
- showBottomSeparator(false)
onTextChange { text ->
host.interactionListener?.processAction(RoomDevToolAction.CustomEventTypeChange(text))
}
@@ -55,7 +54,6 @@ class RoomDevToolSendFormController @Inject constructor(
enabled(true)
value(data.sendEventDraft?.stateKey)
hint(host.stringProvider.getString(R.string.dev_tools_form_hint_state_key))
- showBottomSeparator(false)
onTextChange { text ->
host.interactionListener?.processAction(RoomDevToolAction.CustomEventStateKeyChange(text))
}
@@ -67,7 +65,6 @@ class RoomDevToolSendFormController @Inject constructor(
enabled(true)
value(data.sendEventDraft?.content)
hint(host.stringProvider.getString(R.string.dev_tools_form_hint_event_content))
- showBottomSeparator(false)
onTextChange { text ->
host.interactionListener?.processAction(RoomDevToolAction.CustomEventContentChange(text))
}
diff --git a/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolSendFormFragment.kt b/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolSendFormFragment.kt
index abda6104cd..6b7dea7d53 100644
--- a/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolSendFormFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolSendFormFragment.kt
@@ -40,7 +40,7 @@ class RoomDevToolSendFormFragment @Inject constructor(
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- views.genericRecyclerView.configureWith(epoxyController, showDivider = false)
+ views.genericRecyclerView.configureWith(epoxyController)
epoxyController.interactionListener = this
}
diff --git a/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolStateEventListFragment.kt b/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolStateEventListFragment.kt
index 600464bb6d..728fb62d66 100644
--- a/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolStateEventListFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolStateEventListFragment.kt
@@ -22,6 +22,7 @@ import android.view.View
import android.view.ViewGroup
import com.airbnb.mvrx.activityViewModel
import com.airbnb.mvrx.withState
+import im.vector.app.R
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
import im.vector.app.core.platform.VectorBaseFragment
@@ -40,7 +41,7 @@ class RoomDevToolStateEventListFragment @Inject constructor(
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- views.genericRecyclerView.configureWith(epoxyController, showDivider = true)
+ views.genericRecyclerView.configureWith(epoxyController, dividerDrawable = R.drawable.divider_horizontal)
epoxyController.interactionListener = this
}
diff --git a/vector/src/main/java/im/vector/app/features/devtools/RoomStateListController.kt b/vector/src/main/java/im/vector/app/features/devtools/RoomStateListController.kt
index 25cd2f129f..08aa119a1e 100644
--- a/vector/src/main/java/im/vector/app/features/devtools/RoomStateListController.kt
+++ b/vector/src/main/java/im/vector/app/features/devtools/RoomStateListController.kt
@@ -21,7 +21,6 @@ import im.vector.app.R
import im.vector.app.core.epoxy.noResultItem
import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.resources.StringProvider
-import im.vector.app.core.ui.list.GenericItem
import im.vector.app.core.ui.list.genericItem
import me.gujun.android.span.span
import org.json.JSONObject
@@ -51,11 +50,9 @@ class RoomStateListController @Inject constructor(
id(entry.key)
title(entry.key)
description(host.stringProvider.getQuantityString(R.plurals.entries, entry.value.size, entry.value.size))
- itemClickAction(GenericItem.Action("view").apply {
- perform = Runnable {
- host.interactionListener?.processAction(RoomDevToolAction.ShowStateEventType(entry.key))
- }
- })
+ itemClickAction {
+ host.interactionListener?.processAction(RoomDevToolAction.ShowStateEventType(entry.key))
+ }
}
}
}
@@ -81,23 +78,21 @@ class RoomStateListController @Inject constructor(
title(span {
+"Type: "
span {
- textColor = host.colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
+ textColor = host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary)
text = "\"${stateEvent.type}\""
textStyle = "normal"
}
+"\nState Key: "
span {
- textColor = host.colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
+ textColor = host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary)
text = stateEvent.stateKey.let { "\"$it\"" }
textStyle = "normal"
}
})
description(contentJson)
- itemClickAction(GenericItem.Action("view").apply {
- perform = Runnable {
- host.interactionListener?.processAction(RoomDevToolAction.ShowStateEvent(stateEvent))
- }
- })
+ itemClickAction {
+ host.interactionListener?.processAction(RoomDevToolAction.ShowStateEvent(stateEvent))
+ }
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/disclaimer/DisclaimerDialog.kt b/vector/src/main/java/im/vector/app/features/disclaimer/DisclaimerDialog.kt
index 8ea3365cf9..1c6afb30b2 100644
--- a/vector/src/main/java/im/vector/app/features/disclaimer/DisclaimerDialog.kt
+++ b/vector/src/main/java/im/vector/app/features/disclaimer/DisclaimerDialog.kt
@@ -18,8 +18,8 @@ package im.vector.app.features.disclaimer
import android.app.Activity
import android.content.Context
-import androidx.appcompat.app.AlertDialog
import androidx.core.content.edit
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.di.DefaultSharedPreferences
import im.vector.app.core.utils.openUrlInChromeCustomTab
@@ -40,7 +40,7 @@ fun showDisclaimerDialog(activity: Activity) {
val dialogLayout = activity.layoutInflater.inflate(R.layout.dialog_disclaimer_content, null)
- AlertDialog.Builder(activity)
+ MaterialAlertDialogBuilder(activity)
.setView(dialogLayout)
.setCancelable(false)
.setNegativeButton(R.string.disclaimer_negative_button, null)
diff --git a/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsController.kt b/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsController.kt
index 25cb3ce8dd..1e8db2571d 100644
--- a/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsController.kt
+++ b/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsController.kt
@@ -15,7 +15,6 @@
*/
package im.vector.app.features.discovery
-import android.view.View
import com.airbnb.epoxy.TypedEpoxyController
import com.airbnb.mvrx.Async
import com.airbnb.mvrx.Fail
@@ -125,7 +124,7 @@ class DiscoverySettingsController @Inject constructor(
id("idServerFooter")
helperText(host.stringProvider.getString(R.string.settings_agree_to_terms, identityServer))
showCompoundDrawable(true)
- itemClickListener(View.OnClickListener { host.listener?.openIdentityServerTerms() })
+ itemClickListener { host.listener?.openIdentityServerTerms() }
}
settingsButtonItem {
id("seeTerms")
@@ -214,15 +213,14 @@ class DiscoverySettingsController @Inject constructor(
is Loading ->
settingsInformationItem {
id("info${pidInfo.threePid.value}")
- colorProvider(host.colorProvider)
message(host.stringProvider.getString(R.string.settings_discovery_confirm_mail, pidInfo.threePid.value))
+ textColor(host.colorProvider.getColor(R.color.vector_info_color))
}
is Fail ->
settingsInformationItem {
id("info${pidInfo.threePid.value}")
- colorProvider(host.colorProvider)
message(host.stringProvider.getString(R.string.settings_discovery_confirm_mail_not_clicked, pidInfo.threePid.value))
- textColorId(R.color.riotx_destructive_accent)
+ textColor(host.colorProvider.getColorFromAttribute(R.attr.colorError))
}
is Success -> Unit /* Cannot happen */
}
@@ -363,9 +361,8 @@ class DiscoverySettingsController @Inject constructor(
val host = this
settingsInformationItem {
id("info${pidInfo.threePid.value}")
- colorProvider(host.colorProvider)
- textColorId(R.color.vector_error_color)
message((pidInfo.isShared as? Fail)?.error?.message ?: "")
+ textColor(host.colorProvider.getColorFromAttribute(R.attr.colorError))
}
}
diff --git a/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsFragment.kt b/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsFragment.kt
index ca1132c584..0b8674ec6f 100644
--- a/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsFragment.kt
@@ -20,10 +20,10 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
@@ -143,7 +143,7 @@ class DiscoverySettingsFragment @Inject constructor(
if (hasBoundIds) {
// we should prompt
- AlertDialog.Builder(requireActivity())
+ MaterialAlertDialogBuilder(requireActivity())
.setTitle(R.string.change_identity_server)
.setMessage(getString(R.string.settings_discovery_disconnect_with_bound_pid, state.identityServer(), state.identityServer()))
.setPositiveButton(R.string._continue) { _, _ -> navigateToChangeIdentityServerFragment() }
@@ -167,7 +167,7 @@ class DiscoverySettingsFragment @Inject constructor(
getString(R.string.disconnect_identity_server_dialog_content, state.identityServer())
}
- AlertDialog.Builder(requireActivity())
+ MaterialAlertDialogBuilder(requireActivity())
.setTitle(R.string.disconnect_identity_server)
.setMessage(message)
.setPositiveButton(R.string.disconnect) { _, _ -> viewModel.handle(DiscoverySettingsAction.DisconnectIdentityServer) }
@@ -179,7 +179,7 @@ class DiscoverySettingsFragment @Inject constructor(
override fun onTapUpdateUserConsent(newValue: Boolean) {
if (newValue) {
withState(viewModel) { state ->
- AlertDialog.Builder(requireActivity())
+ MaterialAlertDialogBuilder(requireActivity())
.setTitle(R.string.identity_server_consent_dialog_title)
.setMessage(getString(R.string.identity_server_consent_dialog_content, state.identityServer.invoke()))
.setPositiveButton(R.string.yes) { _, _ ->
diff --git a/vector/src/main/java/im/vector/app/features/discovery/SettingsButtonItem.kt b/vector/src/main/java/im/vector/app/features/discovery/SettingsButtonItem.kt
index 38f2343316..5a32616c06 100644
--- a/vector/src/main/java/im/vector/app/features/discovery/SettingsButtonItem.kt
+++ b/vector/src/main/java/im/vector/app/features/discovery/SettingsButtonItem.kt
@@ -44,7 +44,7 @@ abstract class SettingsButtonItem : EpoxyModelWithHolder {
- holder.button.setTextColor(colorProvider.getColor(R.color.riotx_accent))
+ holder.button.setTextColor(colorProvider.getColorFromAttribute(R.attr.colorPrimary))
}
ButtonStyle.DESTRUCTIVE -> {
- holder.button.setTextColor(colorProvider.getColor(R.color.riotx_destructive_accent))
+ holder.button.setTextColor(colorProvider.getColorFromAttribute(R.attr.colorError))
}
}
diff --git a/vector/src/main/java/im/vector/app/features/discovery/SettingsContinueCancelItem.kt b/vector/src/main/java/im/vector/app/features/discovery/SettingsContinueCancelItem.kt
index 47059128a1..1f19523202 100644
--- a/vector/src/main/java/im/vector/app/features/discovery/SettingsContinueCancelItem.kt
+++ b/vector/src/main/java/im/vector/app/features/discovery/SettingsContinueCancelItem.kt
@@ -30,13 +30,13 @@ abstract class SettingsContinueCancelItem : EpoxyModelWithHolder(
@StringRes
var helperTextResId: Int? = null
- @EpoxyAttribute
- var itemClickListener: View.OnClickListener? = null
+ @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
+ var itemClickListener: ClickListener? = null
@EpoxyAttribute
@DrawableRes
@@ -55,7 +56,7 @@ abstract class SettingsInfoItem : EpoxyModelWithHolder(
holder.text.setTextOrHide(helperText)
}
- holder.view.setOnClickListener(itemClickListener)
+ holder.view.onClick(itemClickListener)
if (showCompoundDrawable) {
holder.text.setCompoundDrawablesWithIntrinsicBounds(compoundDrawable, 0, 0, 0)
diff --git a/vector/src/main/java/im/vector/app/features/discovery/SettingsInformationItem.kt b/vector/src/main/java/im/vector/app/features/discovery/SettingsInformationItem.kt
index 5748df711e..71eab5115e 100644
--- a/vector/src/main/java/im/vector/app/features/discovery/SettingsInformationItem.kt
+++ b/vector/src/main/java/im/vector/app/features/discovery/SettingsInformationItem.kt
@@ -16,32 +16,28 @@
package im.vector.app.features.discovery
import android.widget.TextView
-import androidx.annotation.ColorRes
+import androidx.annotation.ColorInt
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import com.airbnb.epoxy.EpoxyModelWithHolder
import im.vector.app.R
import im.vector.app.core.epoxy.VectorEpoxyHolder
-import im.vector.app.core.resources.ColorProvider
@EpoxyModelClass(layout = R.layout.item_settings_information)
abstract class SettingsInformationItem : EpoxyModelWithHolder() {
- @EpoxyAttribute
- lateinit var colorProvider: ColorProvider
-
@EpoxyAttribute
lateinit var message: String
@EpoxyAttribute
- @ColorRes
- var textColorId: Int = R.color.vector_info_color
+ @ColorInt
+ var textColor: Int = 0
override fun bind(holder: Holder) {
super.bind(holder)
holder.textView.text = message
- holder.textView.setTextColor(colorProvider.getColor(textColorId))
+ holder.textView.setTextColor(textColor)
}
class Holder : VectorEpoxyHolder() {
diff --git a/vector/src/main/java/im/vector/app/features/discovery/SettingsItem.kt b/vector/src/main/java/im/vector/app/features/discovery/SettingsItem.kt
index 3471a3ab56..9726e63d39 100644
--- a/vector/src/main/java/im/vector/app/features/discovery/SettingsItem.kt
+++ b/vector/src/main/java/im/vector/app/features/discovery/SettingsItem.kt
@@ -15,7 +15,6 @@
*/
package im.vector.app.features.discovery
-import android.view.View
import android.widget.TextView
import androidx.annotation.StringRes
import androidx.core.view.isVisible
@@ -24,7 +23,9 @@ import com.airbnb.epoxy.EpoxyModelClass
import com.airbnb.epoxy.EpoxyModelWithHolder
import com.google.android.material.switchmaterial.SwitchMaterial
import im.vector.app.R
+import im.vector.app.core.epoxy.ClickListener
import im.vector.app.core.epoxy.VectorEpoxyHolder
+import im.vector.app.core.epoxy.onClick
import im.vector.app.core.extensions.setTextOrHide
@EpoxyModelClass(layout = R.layout.item_settings_simple_item)
@@ -44,8 +45,8 @@ abstract class SettingsItem : EpoxyModelWithHolder() {
@EpoxyAttribute
var description: CharSequence? = null
- @EpoxyAttribute
- var itemClickListener: View.OnClickListener? = null
+ @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
+ var itemClickListener: ClickListener? = null
override fun bind(holder: Holder) {
super.bind(holder)
@@ -63,7 +64,7 @@ abstract class SettingsItem : EpoxyModelWithHolder() {
holder.switchButton.isVisible = false
- holder.view.setOnClickListener(itemClickListener)
+ holder.view.onClick(itemClickListener)
}
class Holder : VectorEpoxyHolder() {
diff --git a/vector/src/main/java/im/vector/app/features/discovery/SettingsTextButtonSingleLineItem.kt b/vector/src/main/java/im/vector/app/features/discovery/SettingsTextButtonSingleLineItem.kt
index 9f64a68d4f..527d28dfad 100644
--- a/vector/src/main/java/im/vector/app/features/discovery/SettingsTextButtonSingleLineItem.kt
+++ b/vector/src/main/java/im/vector/app/features/discovery/SettingsTextButtonSingleLineItem.kt
@@ -78,7 +78,7 @@ abstract class SettingsTextButtonSingleLineItem : EpoxyModelWithHolder {
- holder.mainButton.setTextColor(colorProvider.getColorFromAttribute(R.attr.colorAccent))
+ holder.mainButton.setTextColor(colorProvider.getColorFromAttribute(R.attr.colorPrimary))
}
ButtonStyle.DESTRUCTIVE -> {
- holder.mainButton.setTextColor(colorProvider.getColor(R.color.vector_error_color))
+ holder.mainButton.setTextColor(colorProvider.getColorFromAttribute(R.attr.colorError))
}
}.exhaustive
holder.mainButton.onClick(buttonClickListener)
@@ -148,7 +148,7 @@ abstract class SettingsTextButtonSingleLineItem : EpoxyModelWithHolder {
- val errorColor = colorProvider.getColor(R.color.vector_error_color)
+ val errorColor = colorProvider.getColorFromAttribute(R.attr.colorError)
ContextCompat.getDrawable(holder.view.context, R.drawable.ic_notification_privacy_warning)?.apply {
ThemeUtils.tintDrawableWithColor(this, errorColor)
holder.textView.setCompoundDrawablesWithIntrinsicBounds(this, null, null, null)
diff --git a/vector/src/main/java/im/vector/app/features/discovery/change/SetIdentityServerFragment.kt b/vector/src/main/java/im/vector/app/features/discovery/change/SetIdentityServerFragment.kt
index 934c6fcaca..36e77fb6a0 100644
--- a/vector/src/main/java/im/vector/app/features/discovery/change/SetIdentityServerFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/discovery/change/SetIdentityServerFragment.kt
@@ -21,12 +21,12 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
-import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.text.toSpannable
import androidx.core.view.isVisible
import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.jakewharton.rxbinding3.widget.textChanges
import im.vector.app.R
import im.vector.app.core.extensions.exhaustive
@@ -68,7 +68,7 @@ class SetIdentityServerFragment @Inject constructor(
)
.toSpannable()
.colorizeMatchingText(state.defaultIdentityServerUrl.toReducedUrl(),
- colorProvider.getColorFromAttribute(R.attr.riotx_text_primary_body_contrast))
+ colorProvider.getColorFromAttribute(R.attr.vctr_content_tertiary))
views.identityServerSetDefaultNotice.isVisible = true
views.identityServerSetDefaultSubmit.isVisible = true
@@ -112,7 +112,7 @@ class SetIdentityServerFragment @Inject constructor(
is SetIdentityServerViewEvents.Failure -> handleFailure(it)
is SetIdentityServerViewEvents.OtherFailure -> showFailure(it.failure)
is SetIdentityServerViewEvents.NoTerms -> {
- AlertDialog.Builder(requireActivity())
+ MaterialAlertDialogBuilder(requireActivity())
.setTitle(R.string.settings_discovery_no_terms_title)
.setMessage(R.string.settings_discovery_no_terms)
.setPositiveButton(R.string._continue) { _, _ ->
@@ -139,7 +139,7 @@ class SetIdentityServerFragment @Inject constructor(
val message = getString(failure.errorMessageId)
if (failure.forDefault) {
// Display the error in a dialog
- AlertDialog.Builder(requireActivity())
+ MaterialAlertDialogBuilder(requireActivity())
.setTitle(R.string.dialog_title_error)
.setMessage(message)
.setPositiveButton(R.string.ok, null)
diff --git a/vector/src/main/java/im/vector/app/features/form/FormAdvancedToggleItem.kt b/vector/src/main/java/im/vector/app/features/form/FormAdvancedToggleItem.kt
index 2d6535758e..08ed29b4eb 100644
--- a/vector/src/main/java/im/vector/app/features/form/FormAdvancedToggleItem.kt
+++ b/vector/src/main/java/im/vector/app/features/form/FormAdvancedToggleItem.kt
@@ -22,8 +22,10 @@ import androidx.core.graphics.drawable.DrawableCompat
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
+import im.vector.app.core.epoxy.ClickListener
import im.vector.app.core.epoxy.VectorEpoxyHolder
import im.vector.app.core.epoxy.VectorEpoxyModel
+import im.vector.app.core.epoxy.onClick
import im.vector.app.features.themes.ThemeUtils
@EpoxyModelClass(layout = R.layout.item_form_advanced_toggle)
@@ -31,18 +33,18 @@ abstract class FormAdvancedToggleItem : VectorEpoxyModel Unit)? = null
+ @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var listener: ClickListener? = null
override fun bind(holder: Holder) {
super.bind(holder)
- val tintColor = ThemeUtils.getColor(holder.view.context, R.attr.riotx_text_secondary)
- val expandedArrowDrawableRes = if (expanded) R.drawable.ic_expand_more_white else R.drawable.ic_expand_less_white
+ val tintColor = ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_secondary)
+ val expandedArrowDrawableRes = if (expanded) R.drawable.ic_expand_more else R.drawable.ic_expand_less
val expandedArrowDrawable = ContextCompat.getDrawable(holder.view.context, expandedArrowDrawableRes)?.also {
DrawableCompat.setTint(it, tintColor)
}
holder.titleView.setCompoundDrawablesWithIntrinsicBounds(null, null, expandedArrowDrawable, null)
holder.titleView.text = title
- holder.view.setOnClickListener { listener?.invoke() }
+ holder.view.onClick(listener)
}
class Holder : VectorEpoxyHolder() {
diff --git a/vector/src/main/java/im/vector/app/features/form/FormEditTextItem.kt b/vector/src/main/java/im/vector/app/features/form/FormEditTextItem.kt
index 8e9b72d2d8..e2203057ab 100644
--- a/vector/src/main/java/im/vector/app/features/form/FormEditTextItem.kt
+++ b/vector/src/main/java/im/vector/app/features/form/FormEditTextItem.kt
@@ -17,17 +17,17 @@
package im.vector.app.features.form
import android.text.Editable
-import android.view.View
import android.view.inputmethod.EditorInfo
import android.widget.TextView
-import androidx.core.view.isVisible
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import com.google.android.material.textfield.TextInputEditText
import com.google.android.material.textfield.TextInputLayout
import im.vector.app.R
+import im.vector.app.core.epoxy.TextListener
import im.vector.app.core.epoxy.VectorEpoxyHolder
import im.vector.app.core.epoxy.VectorEpoxyModel
+import im.vector.app.core.epoxy.addTextChangedListenerOnce
import im.vector.app.core.epoxy.setValueOnce
import im.vector.app.core.platform.SimpleTextWatcher
@@ -40,9 +40,6 @@ abstract class FormEditTextItem : VectorEpoxyModel() {
@EpoxyAttribute
var value: String? = null
- @EpoxyAttribute
- var showBottomSeparator: Boolean = true
-
@EpoxyAttribute
var errorMessage: String? = null
@@ -61,11 +58,10 @@ abstract class FormEditTextItem : VectorEpoxyModel() {
@EpoxyAttribute
var endIconMode: Int? = null
- // FIXME restore EpoxyAttribute.Option.DoNotHash and fix that properly
- @EpoxyAttribute
- var onTextChange: ((String) -> Unit)? = null
+ @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
+ var onTextChange: TextListener? = null
- @EpoxyAttribute
+ @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
var editorActionListener: TextView.OnEditorActionListener? = null
private val onTextChangeListener = object : SimpleTextWatcher() {
@@ -88,9 +84,8 @@ abstract class FormEditTextItem : VectorEpoxyModel() {
holder.textInputEditText.isSingleLine = singleLine
holder.textInputEditText.imeOptions = imeOptions ?: EditorInfo.IME_ACTION_NONE
- holder.textInputEditText.addTextChangedListener(onTextChangeListener)
+ holder.textInputEditText.addTextChangedListenerOnce(onTextChangeListener)
holder.textInputEditText.setOnEditorActionListener(editorActionListener)
- holder.bottomSeparator.isVisible = showBottomSeparator
}
override fun shouldSaveViewState(): Boolean {
@@ -105,6 +100,5 @@ abstract class FormEditTextItem : VectorEpoxyModel() {
class Holder : VectorEpoxyHolder() {
val textInputLayout by bind(R.id.formTextInputTextInputLayout)
val textInputEditText by bind(R.id.formTextInputTextInputEditText)
- val bottomSeparator by bind(R.id.formTextInputDivider)
}
}
diff --git a/vector/src/main/java/im/vector/app/features/form/FormEditTextWithButtonItem.kt b/vector/src/main/java/im/vector/app/features/form/FormEditTextWithButtonItem.kt
index 6cf862b10b..dd059ec658 100644
--- a/vector/src/main/java/im/vector/app/features/form/FormEditTextWithButtonItem.kt
+++ b/vector/src/main/java/im/vector/app/features/form/FormEditTextWithButtonItem.kt
@@ -17,15 +17,18 @@
package im.vector.app.features.form
import android.text.Editable
-import android.view.View
-import androidx.appcompat.widget.AppCompatButton
+import android.widget.Button
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import com.google.android.material.textfield.TextInputEditText
import com.google.android.material.textfield.TextInputLayout
import im.vector.app.R
+import im.vector.app.core.epoxy.ClickListener
+import im.vector.app.core.epoxy.TextListener
import im.vector.app.core.epoxy.VectorEpoxyHolder
import im.vector.app.core.epoxy.VectorEpoxyModel
+import im.vector.app.core.epoxy.addTextChangedListenerOnce
+import im.vector.app.core.epoxy.onClick
import im.vector.app.core.epoxy.setValueOnce
import im.vector.app.core.platform.SimpleTextWatcher
@@ -44,11 +47,11 @@ abstract class FormEditTextWithButtonItem : VectorEpoxyModel Unit)? = null
+ @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
+ var onTextChange: TextListener? = null
- @EpoxyAttribute
- var onButtonClicked: ((View) -> Unit)? = null
+ @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
+ var onButtonClicked: ClickListener? = null
private val onTextChangeListener = object : SimpleTextWatcher() {
override fun afterTextChanged(s: Editable) {
@@ -65,11 +68,10 @@ abstract class FormEditTextWithButtonItem : VectorEpoxyModel(R.id.formTextInputTextInputLayout)
val textInputEditText by bind(R.id.formTextInputTextInputEditText)
- val textInputButton by bind(R.id.formTextInputButton)
+ val textInputButton by bind(R.id.formTextInputButton)
}
}
diff --git a/vector/src/main/java/im/vector/app/features/form/FormEditableAvatarItem.kt b/vector/src/main/java/im/vector/app/features/form/FormEditableAvatarItem.kt
index c5a45d8f1b..b81a731260 100644
--- a/vector/src/main/java/im/vector/app/features/form/FormEditableAvatarItem.kt
+++ b/vector/src/main/java/im/vector/app/features/form/FormEditableAvatarItem.kt
@@ -46,10 +46,10 @@ abstract class FormEditableAvatarItem : EpoxyModelWithHolder Unit)? = null
+ var onTextChange: TextListener? = null
private val onTextChangeListener = object : SimpleTextWatcher() {
override fun afterTextChanged(s: Editable) {
@@ -80,8 +77,7 @@ abstract class FormMultiLineEditTextItem : VectorEpoxyModel(R.id.formMultiLineTextInputLayout)
val textInputEditText by bind(R.id.formMultiLineEditText)
- val bottomSeparator by bind(R.id.formTextInputDivider)
}
}
diff --git a/vector/src/main/java/im/vector/app/features/form/FormSubmitButtonItem.kt b/vector/src/main/java/im/vector/app/features/form/FormSubmitButtonItem.kt
index 2d2a5e7aec..41e1bc95a7 100644
--- a/vector/src/main/java/im/vector/app/features/form/FormSubmitButtonItem.kt
+++ b/vector/src/main/java/im/vector/app/features/form/FormSubmitButtonItem.kt
@@ -39,7 +39,7 @@ abstract class FormSubmitButtonItem : EpoxyModelWithHolder() {
@EpoxyAttribute
var summary: String? = null
- @EpoxyAttribute
- var showDivider: Boolean = true
-
override fun bind(holder: Holder) {
super.bind(holder)
holder.view.setOnClickListener {
@@ -65,8 +60,6 @@ abstract class FormSwitchItem : VectorEpoxyModel() {
holder.setValueOnce(holder.switchView, switchChecked) { _, isChecked ->
listener?.invoke(isChecked)
}
-
- holder.divider.isVisible = showDivider
}
override fun shouldSaveViewState(): Boolean {
@@ -83,6 +76,5 @@ abstract class FormSwitchItem : VectorEpoxyModel() {
val titleView by bind(R.id.formSwitchTitle)
val summaryView by bind(R.id.formSwitchSummary)
val switchView by bind(R.id.formSwitchSwitch)
- val divider by bind(R.id.formSwitchDivider)
}
}
diff --git a/vector/src/main/java/im/vector/app/features/grouplist/GroupSummaryItem.kt b/vector/src/main/java/im/vector/app/features/grouplist/GroupSummaryItem.kt
index b74b30a059..4256e2d808 100644
--- a/vector/src/main/java/im/vector/app/features/grouplist/GroupSummaryItem.kt
+++ b/vector/src/main/java/im/vector/app/features/grouplist/GroupSummaryItem.kt
@@ -22,8 +22,10 @@ import android.widget.TextView
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
+import im.vector.app.core.epoxy.ClickListener
import im.vector.app.core.epoxy.VectorEpoxyHolder
import im.vector.app.core.epoxy.VectorEpoxyModel
+import im.vector.app.core.epoxy.onClick
import im.vector.app.core.platform.CheckableConstraintLayout
import im.vector.app.features.home.AvatarRenderer
import org.matrix.android.sdk.api.util.MatrixItem
@@ -34,11 +36,11 @@ abstract class GroupSummaryItem : VectorEpoxyModel() {
@EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer
@EpoxyAttribute lateinit var matrixItem: MatrixItem
@EpoxyAttribute var selected: Boolean = false
- @EpoxyAttribute var listener: (() -> Unit)? = null
+ @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var listener: ClickListener? = null
override fun bind(holder: Holder) {
super.bind(holder)
- holder.rootView.setOnClickListener { listener?.invoke() }
+ holder.rootView.onClick(listener)
holder.groupNameView.text = matrixItem.displayName
holder.rootView.isChecked = selected
avatarRenderer.render(matrixItem, holder.avatarImageView)
diff --git a/vector/src/main/java/im/vector/app/features/grouplist/HomeSpaceSummaryItem.kt b/vector/src/main/java/im/vector/app/features/grouplist/HomeSpaceSummaryItem.kt
index ddda38aa9c..bbced2e8e1 100644
--- a/vector/src/main/java/im/vector/app/features/grouplist/HomeSpaceSummaryItem.kt
+++ b/vector/src/main/java/im/vector/app/features/grouplist/HomeSpaceSummaryItem.kt
@@ -26,8 +26,10 @@ import androidx.core.view.isVisible
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
+import im.vector.app.core.epoxy.ClickListener
import im.vector.app.core.epoxy.VectorEpoxyHolder
import im.vector.app.core.epoxy.VectorEpoxyModel
+import im.vector.app.core.epoxy.onClick
import im.vector.app.core.platform.CheckableConstraintLayout
import im.vector.app.features.home.room.list.UnreadCounterBadgeView
import im.vector.app.features.themes.ThemeUtils
@@ -36,7 +38,7 @@ import im.vector.app.features.themes.ThemeUtils
abstract class HomeSpaceSummaryItem : VectorEpoxyModel() {
@EpoxyAttribute var selected: Boolean = false
- @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var listener: (() -> Unit)? = null
+ @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var listener: ClickListener? = null
@EpoxyAttribute var countState : UnreadCounterBadgeView.State = UnreadCounterBadgeView.State(0, false)
@EpoxyAttribute var showSeparator: Boolean = false
@@ -47,13 +49,13 @@ abstract class HomeSpaceSummaryItem : VectorEpoxyModel
if (!isHandled) {
- AlertDialog.Builder(this)
+ MaterialAlertDialogBuilder(this)
.setTitle(R.string.dialog_title_error)
.setMessage(R.string.permalink_malformed)
.setPositiveButton(R.string.ok, null)
@@ -394,7 +393,7 @@ class HomeActivity :
iconId = R.drawable.ic_shield_warning
).apply {
viewBinder = VerificationVectorAlert.ViewBinder(userItem, avatarRenderer)
- colorInt = ContextCompat.getColor(this@HomeActivity, R.color.riotx_positive_accent)
+ colorInt = ThemeUtils.getColor(this@HomeActivity, R.attr.colorPrimary)
contentAction = Runnable {
(weakCurrentActivity?.get() as? VectorBaseActivity<*>)?.let {
action(it)
@@ -424,7 +423,7 @@ class HomeActivity :
if (vectorUncaughtExceptionHandler.didAppCrash(this)) {
vectorUncaughtExceptionHandler.clearAppCrashStatus(this)
- AlertDialog.Builder(this)
+ MaterialAlertDialogBuilder(this)
.setMessage(R.string.send_bug_report_app_crashed)
.setCancelable(false)
.setPositiveButton(R.string.yes) { _, _ -> bugReporter.openBugReportScreen(this) }
diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt
index 291a4218b9..488e42c7ef 100644
--- a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt
@@ -22,7 +22,6 @@ import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
-import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import com.airbnb.mvrx.activityViewModel
import com.airbnb.mvrx.fragmentViewModel
@@ -35,6 +34,7 @@ import im.vector.app.core.extensions.toMvRxBundle
import im.vector.app.core.platform.ToolbarConfigurable
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.core.platform.VectorBaseFragment
+import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.ui.views.CurrentCallsView
import im.vector.app.core.ui.views.KeysBackupBanner
import im.vector.app.core.ui.views.KnownCallsViewHolder
@@ -62,6 +62,7 @@ class HomeDetailFragment @Inject constructor(
val homeDetailViewModelFactory: HomeDetailViewModel.Factory,
private val serverBackupStatusViewModelFactory: ServerBackupStatusViewModel.Factory,
private val avatarRenderer: AvatarRenderer,
+ private val colorProvider: ColorProvider,
private val alertManager: PopupAlertManager,
private val callManager: WebRtcCallManager,
private val vectorPreferences: VectorPreferences
@@ -130,7 +131,7 @@ class HomeDetailFragment @Inject constructor(
is RoomGroupingMethod.ByLegacyGroup -> {
onGroupChange(roomGroupingMethod.groupSummary)
}
- is RoomGroupingMethod.BySpace -> {
+ is RoomGroupingMethod.BySpace -> {
onSpaceChange(roomGroupingMethod.spaceSummary)
}
}
@@ -204,7 +205,7 @@ class HomeDetailFragment @Inject constructor(
iconId = R.drawable.ic_shield_warning
).apply {
viewBinder = VerificationVectorAlert.ViewBinder(user, avatarRenderer)
- colorInt = ContextCompat.getColor(requireActivity(), R.color.riotx_accent)
+ colorInt = colorProvider.getColorFromAttribute(R.attr.colorPrimary)
contentAction = Runnable {
(weakCurrentActivity?.get() as? VectorBaseActivity<*>)
?.navigator
@@ -232,7 +233,7 @@ class HomeDetailFragment @Inject constructor(
iconId = R.drawable.ic_shield_warning
).apply {
viewBinder = VerificationVectorAlert.ViewBinder(user, avatarRenderer)
- colorInt = ContextCompat.getColor(requireActivity(), R.color.riotx_accent)
+ colorInt = colorProvider.getColorFromAttribute(R.attr.colorPrimary)
contentAction = Runnable {
(weakCurrentActivity?.get() as? VectorBaseActivity<*>)?.let {
// mark as ignored to avoid showing it again
@@ -273,10 +274,10 @@ class HomeDetailFragment @Inject constructor(
serverBackupStatusViewModel
.subscribe(this) {
when (val banState = it.bannerState.invoke()) {
- is BannerState.Setup -> views.homeKeysBackupBanner.render(KeysBackupBanner.State.Setup(banState.numberOfKeys), false)
+ is BannerState.Setup -> views.homeKeysBackupBanner.render(KeysBackupBanner.State.Setup(banState.numberOfKeys), false)
BannerState.BackingUp -> views.homeKeysBackupBanner.render(KeysBackupBanner.State.BackingUp, false)
null,
- BannerState.Hidden -> views.homeKeysBackupBanner.render(KeysBackupBanner.State.Hidden, false)
+ BannerState.Hidden -> views.homeKeysBackupBanner.render(KeysBackupBanner.State.Hidden, false)
}
}
views.homeKeysBackupBanner.delegate = this
@@ -307,7 +308,7 @@ class HomeDetailFragment @Inject constructor(
is RoomGroupingMethod.ByLegacyGroup -> {
// nothing do far
}
- is RoomGroupingMethod.BySpace -> {
+ is RoomGroupingMethod.BySpace -> {
it.roomGroupingMethod.spaceSummary?.let {
sharedActionViewModel.post(HomeActivitySharedAction.ShowSpaceSettings(it.roomId))
}
@@ -322,7 +323,7 @@ class HomeDetailFragment @Inject constructor(
views.bottomNavigationView.setOnNavigationItemSelectedListener {
val displayMode = when (it.itemId) {
R.id.bottom_action_people -> RoomListDisplayMode.PEOPLE
- R.id.bottom_action_rooms -> RoomListDisplayMode.ROOMS
+ R.id.bottom_action_rooms -> RoomListDisplayMode.ROOMS
else -> RoomListDisplayMode.NOTIFICATIONS
}
viewModel.handle(HomeDetailAction.SwitchDisplayMode(displayMode))
@@ -390,17 +391,17 @@ class HomeDetailFragment @Inject constructor(
isVisible = count > 0
number = count
maxCharacterCount = 3
- badgeTextColor = ContextCompat.getColor(requireContext(), R.color.white)
+ badgeTextColor = ThemeUtils.getColor(requireContext(), R.attr.colorOnPrimary)
backgroundColor = if (highlight) {
- ContextCompat.getColor(requireContext(), R.color.riotx_notice)
+ ThemeUtils.getColor(requireContext(), R.attr.colorError)
} else {
- ThemeUtils.getColor(requireContext(), R.attr.riotx_unread_room_badge)
+ ThemeUtils.getColor(requireContext(), R.attr.vctr_unread_room_badge)
}
}
private fun RoomListDisplayMode.toMenuId() = when (this) {
RoomListDisplayMode.PEOPLE -> R.id.bottom_action_people
- RoomListDisplayMode.ROOMS -> R.id.bottom_action_rooms
+ RoomListDisplayMode.ROOMS -> R.id.bottom_action_rooms
else -> R.id.bottom_action_notification
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/breadcrumbs/BreadcrumbsController.kt b/vector/src/main/java/im/vector/app/features/home/room/breadcrumbs/BreadcrumbsController.kt
index 655b3dced6..50d5478ba1 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/breadcrumbs/BreadcrumbsController.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/breadcrumbs/BreadcrumbsController.kt
@@ -18,7 +18,6 @@ package im.vector.app.features.home.room.breadcrumbs
import com.airbnb.epoxy.EpoxyController
import im.vector.app.core.epoxy.zeroItem
-import im.vector.app.core.utils.DebouncedClickListener
import im.vector.app.features.home.AvatarRenderer
import org.matrix.android.sdk.api.util.toMatrixItem
import javax.inject.Inject
@@ -53,21 +52,19 @@ class BreadcrumbsController @Inject constructor(
// An empty breadcrumbs list can only be temporary because when entering in a room,
// this one is added to the breadcrumbs
safeViewState.asyncBreadcrumbs.invoke()
- ?.forEach {
+ ?.forEach { roomSummary ->
breadcrumbsItem {
- id(it.roomId)
- hasTypingUsers(it.typingUsers.isNotEmpty())
+ id(roomSummary.roomId)
+ hasTypingUsers(roomSummary.typingUsers.isNotEmpty())
avatarRenderer(host.avatarRenderer)
- matrixItem(it.toMatrixItem())
- unreadNotificationCount(it.notificationCount)
- showHighlighted(it.highlightCount > 0)
- hasUnreadMessage(it.hasUnreadMessages)
- hasDraft(it.userDrafts.isNotEmpty())
- itemClickListener(
- DebouncedClickListener({ _ ->
- host.listener?.onBreadcrumbClicked(it.roomId)
- })
- )
+ matrixItem(roomSummary.toMatrixItem())
+ unreadNotificationCount(roomSummary.notificationCount)
+ showHighlighted(roomSummary.highlightCount > 0)
+ hasUnreadMessage(roomSummary.hasUnreadMessages)
+ hasDraft(roomSummary.userDrafts.isNotEmpty())
+ itemClickListener {
+ host.listener?.onBreadcrumbClicked(roomSummary.roomId)
+ }
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/breadcrumbs/BreadcrumbsItem.kt b/vector/src/main/java/im/vector/app/features/home/room/breadcrumbs/BreadcrumbsItem.kt
index f39b7b6d0a..fd912a4953 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/breadcrumbs/BreadcrumbsItem.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/breadcrumbs/BreadcrumbsItem.kt
@@ -23,8 +23,10 @@ import androidx.core.view.isVisible
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
+import im.vector.app.core.epoxy.ClickListener
import im.vector.app.core.epoxy.VectorEpoxyHolder
import im.vector.app.core.epoxy.VectorEpoxyModel
+import im.vector.app.core.epoxy.onClick
import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.home.room.list.UnreadCounterBadgeView
import org.matrix.android.sdk.api.util.MatrixItem
@@ -39,11 +41,11 @@ abstract class BreadcrumbsItem : VectorEpoxyModel() {
@EpoxyAttribute var showHighlighted: Boolean = false
@EpoxyAttribute var hasUnreadMessage: Boolean = false
@EpoxyAttribute var hasDraft: Boolean = false
- @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var itemClickListener: View.OnClickListener? = null
+ @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var itemClickListener: ClickListener? = null
override fun bind(holder: Holder) {
super.bind(holder)
- holder.rootView.setOnClickListener(itemClickListener)
+ holder.rootView.onClick(itemClickListener)
holder.unreadIndentIndicator.isVisible = hasUnreadMessage
avatarRenderer.render(matrixItem, holder.avatarImageView)
holder.avatarImageView.contentDescription = matrixItem.getBestName()
@@ -52,11 +54,6 @@ abstract class BreadcrumbsItem : VectorEpoxyModel() {
holder.typingIndicator.isVisible = hasTypingUsers
}
- override fun unbind(holder: Holder) {
- holder.rootView.setOnClickListener(null)
- super.unbind(holder)
- }
-
class Holder : VectorEpoxyHolder() {
val unreadCounterBadgeView by bind(R.id.breadcrumbsUnreadCounterBadgeView)
val unreadIndentIndicator by bind(R.id.breadcrumbsUnreadIndicator)
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/AutoCompleter.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/AutoCompleter.kt
index ec2ff82e67..8e6343519a 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/AutoCompleter.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/AutoCompleter.kt
@@ -25,9 +25,8 @@ import com.otaliastudios.autocomplete.Autocomplete
import com.otaliastudios.autocomplete.AutocompleteCallback
import com.otaliastudios.autocomplete.CharPolicy
import dagger.assisted.Assisted
-import dagger.assisted.AssistedInject
import dagger.assisted.AssistedFactory
-import im.vector.app.R
+import dagger.assisted.AssistedInject
import im.vector.app.core.glide.GlideApp
import im.vector.app.core.glide.GlideRequests
import im.vector.app.features.autocomplete.command.AutocompleteCommandPresenter
@@ -80,7 +79,7 @@ class AutoCompleter @AssistedInject constructor(
fun setup(editText: EditText) {
this.editText = editText
glideRequests = GlideApp.with(editText)
- val backgroundDrawable = ColorDrawable(ThemeUtils.getColor(editText.context, R.attr.riotx_background))
+ val backgroundDrawable = ColorDrawable(ThemeUtils.getColor(editText.context, android.R.attr.colorBackground))
setupCommands(backgroundDrawable, editText)
setupMembers(backgroundDrawable, editText)
setupGroups(backgroundDrawable, editText)
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt
index 7fa36a39d7..9ed4feebc4 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt
@@ -42,7 +42,6 @@ import android.widget.TextView
import android.widget.Toast
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
-import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat
import androidx.core.net.toUri
import androidx.core.text.buildSpannedString
@@ -69,6 +68,7 @@ import com.airbnb.mvrx.Success
import com.airbnb.mvrx.args
import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.jakewharton.rxbinding3.view.focusChanges
import com.jakewharton.rxbinding3.widget.textChanges
import com.vanniktech.emoji.EmojiPopup
@@ -547,15 +547,15 @@ class RoomDetailFragment @Inject constructor(
.fromRootView(views.rootConstraintLayout)
.setKeyboardAnimationStyle(R.style.emoji_fade_animation_style)
.setOnEmojiPopupShownListener {
- views.composerLayout.views.composerEmojiButton.let {
- it.setImageResource(R.drawable.ic_keyboard)
- it.contentDescription = getString(R.string.a11y_close_emoji_picker)
+ views.composerLayout.views.composerEmojiButton.apply {
+ contentDescription = getString(R.string.a11y_close_emoji_picker)
+ setImageResource(R.drawable.ic_keyboard)
}
}
.setOnEmojiPopupDismissListener {
- views.composerLayout.views.composerEmojiButton.let {
- it.setImageResource(R.drawable.ic_insert_emoji)
- it.contentDescription = getString(R.string.a11y_open_emoji_picker)
+ views.composerLayout.views.composerEmojiButton.apply {
+ contentDescription = getString(R.string.a11y_open_emoji_picker)
+ setImageResource(R.drawable.ic_insert_emoji)
}
}
.build(views.composerLayout.views.composerEditText)
@@ -568,7 +568,7 @@ class RoomDetailFragment @Inject constructor(
private fun setupFailedMessagesWarningView() {
views.failedMessagesWarningView.callback = object : FailedMessagesWarningView.Callback {
override fun onDeleteAllClicked() {
- AlertDialog.Builder(requireContext())
+ MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.event_status_delete_all_failed_dialog_title)
.setMessage(getString(R.string.event_status_delete_all_failed_dialog_message))
.setNegativeButton(R.string.no, null)
@@ -642,7 +642,7 @@ class RoomDetailFragment @Inject constructor(
private fun displayPromptForIntegrationManager() {
// The Sticker picker widget is not installed yet. Propose the user to install it
- val builder = AlertDialog.Builder(requireContext())
+ val builder = MaterialAlertDialogBuilder(requireContext())
val v: View = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_no_sticker_pack, null)
builder
.setView(v)
@@ -808,7 +808,7 @@ class RoomDetailFragment @Inject constructor(
val actionView = matrixAppsMenuItem.actionView
actionView
.findViewById(R.id.action_view_icon_image)
- .setColorFilter(ContextCompat.getColor(requireContext(), R.color.riotx_accent))
+ .setColorFilter(colorProvider.getColorFromAttribute(R.attr.colorPrimary))
actionView.findViewById(R.id.cart_badge).setTextOrHide("$widgetsCount")
matrixAppsMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
} else {
@@ -816,7 +816,7 @@ class RoomDetailFragment @Inject constructor(
val actionView = matrixAppsMenuItem.actionView
actionView
.findViewById(R.id.action_view_icon_image)
- .setColorFilter(ThemeUtils.getColor(requireContext(), R.attr.riotx_text_secondary))
+ .setColorFilter(ThemeUtils.getColor(requireContext(), R.attr.vctr_content_secondary))
actionView.findViewById(R.id.cart_badge).isVisible = false
matrixAppsMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER)
}
@@ -870,7 +870,7 @@ class RoomDetailFragment @Inject constructor(
}
private fun displayDisabledIntegrationDialog() {
- AlertDialog.Builder(requireActivity())
+ MaterialAlertDialogBuilder(requireActivity())
.setTitle(R.string.disabled_integration_dialog_title)
.setMessage(R.string.disabled_integration_dialog_content)
.setPositiveButton(R.string.settings) { _, _ ->
@@ -1188,6 +1188,10 @@ class RoomDetailFragment @Inject constructor(
override fun onRichContentSelected(contentUri: Uri): Boolean {
return sendUri(contentUri)
}
+
+ override fun onTextEmptyStateChanged(isEmpty: Boolean) {
+ // No op
+ }
}
}
@@ -1201,6 +1205,7 @@ class RoomDetailFragment @Inject constructor(
views.composerLayout.collapse(true)
lockSendButton = true
roomDetailViewModel.handle(RoomDetailAction.SendMessage(text, vectorPreferences.isMarkdownEnabled()))
+ emojiPopup.dismiss()
}
}
@@ -1250,7 +1255,7 @@ class RoomDetailFragment @Inject constructor(
if (state.tombstoneEvent == null) {
if (state.canSendMessage) {
views.composerLayout.visibility = View.VISIBLE
- views.composerLayout.setRoomEncrypted(summary.isEncrypted, summary.roomEncryptionTrustLevel)
+ views.composerLayout.setRoomEncrypted(summary.isEncrypted)
views.notificationAreaView.render(NotificationAreaView.State.Hidden)
} else {
views.composerLayout.visibility = View.GONE
@@ -1289,10 +1294,10 @@ class RoomDetailFragment @Inject constructor(
views.roomToolbarSubtitleView.apply {
setTextOrHide(subtitle)
if (typingMessage.isNullOrBlank()) {
- setTextColor(ThemeUtils.getColor(requireContext(), R.attr.vctr_toolbar_secondary_text_color))
+ setTextColor(colorProvider.getColorFromAttribute(R.attr.vctr_content_primary))
setTypeface(null, Typeface.NORMAL)
} else {
- setTextColor(ContextCompat.getColor(requireContext(), R.color.riotx_accent))
+ setTextColor(colorProvider.getColorFromAttribute(R.attr.colorPrimary))
setTypeface(null, Typeface.BOLD)
}
}
@@ -1341,7 +1346,7 @@ class RoomDetailFragment @Inject constructor(
}
private fun displayCommandError(message: String) {
- AlertDialog.Builder(requireActivity())
+ MaterialAlertDialogBuilder(requireActivity())
.setTitle(R.string.command_error)
.setMessage(message)
.setPositiveButton(R.string.ok, null)
@@ -1356,7 +1361,7 @@ class RoomDetailFragment @Inject constructor(
WithHeldCode.UNAVAILABLE -> R.string.crypto_error_withheld_generic
else -> R.string.notice_crypto_unable_to_decrypt_friendly_desc
}
- AlertDialog.Builder(requireActivity())
+ MaterialAlertDialogBuilder(requireActivity())
.setMessage(msgId)
.setPositiveButton(R.string.ok, null)
.show()
@@ -1367,7 +1372,7 @@ class RoomDetailFragment @Inject constructor(
val layout = inflater.inflate(R.layout.dialog_report_content, null)
val views = DialogReportContentBinding.bind(layout)
- AlertDialog.Builder(requireActivity())
+ MaterialAlertDialogBuilder(requireActivity())
.setTitle(R.string.report_content_custom_title)
.setView(layout)
.setPositiveButton(R.string.report_content_custom_submit) { _, _ ->
@@ -1393,7 +1398,7 @@ class RoomDetailFragment @Inject constructor(
}
private fun displayRoomDetailActionFailure(result: RoomDetailViewEvents.ActionFailure) {
- AlertDialog.Builder(requireActivity())
+ MaterialAlertDialogBuilder(requireActivity())
.setTitle(R.string.dialog_title_error)
.setMessage(errorFormatter.toHumanReadable(result.throwable))
.setPositiveButton(R.string.ok, null)
@@ -1405,7 +1410,7 @@ class RoomDetailFragment @Inject constructor(
is RoomDetailAction.ReportContent -> {
when {
data.spam -> {
- AlertDialog.Builder(requireActivity())
+ MaterialAlertDialogBuilder(requireActivity())
.setTitle(R.string.content_reported_as_spam_title)
.setMessage(R.string.content_reported_as_spam_content)
.setPositiveButton(R.string.ok, null)
@@ -1416,7 +1421,7 @@ class RoomDetailFragment @Inject constructor(
.withColoredButton(DialogInterface.BUTTON_NEGATIVE)
}
data.inappropriate -> {
- AlertDialog.Builder(requireActivity())
+ MaterialAlertDialogBuilder(requireActivity())
.setTitle(R.string.content_reported_as_inappropriate_title)
.setMessage(R.string.content_reported_as_inappropriate_content)
.setPositiveButton(R.string.ok, null)
@@ -1427,7 +1432,7 @@ class RoomDetailFragment @Inject constructor(
.withColoredButton(DialogInterface.BUTTON_NEGATIVE)
}
else -> {
- AlertDialog.Builder(requireActivity())
+ MaterialAlertDialogBuilder(requireActivity())
.setTitle(R.string.content_reported_title)
.setMessage(R.string.content_reported_content)
.setPositiveButton(R.string.ok, null)
@@ -1497,13 +1502,13 @@ class RoomDetailFragment @Inject constructor(
.subscribe { managed ->
if (!managed) {
if (title.isValidUrl() && url.isValidUrl() && URL(title).host != URL(url).host) {
- AlertDialog.Builder(requireActivity())
+ MaterialAlertDialogBuilder(requireActivity())
.setTitle(R.string.external_link_confirmation_title)
.setMessage(
getString(R.string.external_link_confirmation_message, title, url)
.toSpannable()
- .colorizeMatchingText(url, colorProvider.getColorFromAttribute(R.attr.riotx_text_primary_body_contrast))
- .colorizeMatchingText(title, colorProvider.getColorFromAttribute(R.attr.riotx_text_primary_body_contrast))
+ .colorizeMatchingText(url, colorProvider.getColorFromAttribute(R.attr.vctr_content_tertiary))
+ .colorizeMatchingText(title, colorProvider.getColorFromAttribute(R.attr.vctr_content_tertiary))
)
.setPositiveButton(R.string._continue) { _, _ ->
openUrlInExternalBrowser(requireContext(), url)
@@ -1624,7 +1629,7 @@ class RoomDetailFragment @Inject constructor(
if (action.force) {
roomDetailViewModel.handle(RoomDetailAction.CancelSend(action.eventId, true))
} else {
- AlertDialog.Builder(requireContext())
+ MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.dialog_title_confirmation)
.setMessage(getString(R.string.event_status_cancel_sending_dialog_message))
.setNegativeButton(R.string.no, null)
@@ -1863,7 +1868,7 @@ class RoomDetailFragment @Inject constructor(
}
private fun askConfirmationToIgnoreUser(senderId: String) {
- AlertDialog.Builder(requireContext())
+ MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.room_participants_action_ignore_title)
.setMessage(R.string.room_participants_action_ignore_prompt_msg)
.setNegativeButton(R.string.cancel, null)
@@ -1936,7 +1941,7 @@ class RoomDetailFragment @Inject constructor(
}
private fun showDialogWithMessage(message: String) {
- AlertDialog.Builder(requireContext())
+ MaterialAlertDialogBuilder(requireContext())
.setMessage(message)
.setPositiveButton(getString(R.string.ok), null)
.show()
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomMessageTouchHelperCallback.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomMessageTouchHelperCallback.kt
index 25b2685ffb..9f10805f95 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomMessageTouchHelperCallback.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomMessageTouchHelperCallback.kt
@@ -62,7 +62,7 @@ class RoomMessageTouchHelperCallback(private val context: Context,
init {
DrawableCompat.setTint(
imageDrawable,
- ThemeUtils.getColor(context, R.attr.riotx_text_primary)
+ ThemeUtils.getColor(context, R.attr.vctr_content_primary)
)
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/StartCallActionsHandler.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/StartCallActionsHandler.kt
index cf508a2dab..6f9a4fa651 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/StartCallActionsHandler.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/StartCallActionsHandler.kt
@@ -18,9 +18,9 @@ package im.vector.app.features.home.room.detail
import android.os.Bundle
import androidx.activity.result.ActivityResultLauncher
-import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.Fragment
import com.airbnb.mvrx.withState
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.platform.Restorable
import im.vector.app.core.utils.PERMISSIONS_FOR_AUDIO_IP_CALL
@@ -140,7 +140,7 @@ class StartCallActionsHandler(
// A conference is already in progress!
showDialogWithMessage(fragment.getString(R.string.conference_call_in_progress))
} else {
- AlertDialog.Builder(fragment.requireContext())
+ MaterialAlertDialogBuilder(fragment.requireContext())
.setTitle(if (isVideoCall) R.string.video_meeting else R.string.audio_meeting)
.setMessage(R.string.audio_video_meeting_description)
.setPositiveButton(fragment.getString(R.string.create)) { _, _ ->
@@ -157,7 +157,7 @@ class StartCallActionsHandler(
private fun safeStartCall(isVideoCall: Boolean) {
if (vectorPreferences.preventAccidentalCall()) {
- AlertDialog.Builder(fragment.requireActivity())
+ MaterialAlertDialogBuilder(fragment.requireActivity())
.setMessage(if (isVideoCall) R.string.start_video_call_prompt_msg else R.string.start_voice_call_prompt_msg)
.setPositiveButton(if (isVideoCall) R.string.start_video_call else R.string.start_voice_call) { _, _ ->
safeStartCall2(isVideoCall)
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/ComposerEditText.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/ComposerEditText.kt
index 45c937ca5e..2a2ae56c4c 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/ComposerEditText.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/ComposerEditText.kt
@@ -37,9 +37,11 @@ class ComposerEditText @JvmOverloads constructor(context: Context, attrs: Attrib
interface Callback {
fun onRichContentSelected(contentUri: Uri): Boolean
+ fun onTextEmptyStateChanged(isEmpty: Boolean)
}
var callback: Callback? = null
+ private var isEmptyText = true
override fun onCreateInputConnection(editorInfo: EditorInfo): InputConnection? {
val ic = super.onCreateInputConnection(editorInfo) ?: return null
@@ -93,6 +95,11 @@ class ComposerEditText @JvmOverloads constructor(context: Context, attrs: Attrib
}
spanToRemove = null
}
+ // Report blank status of EditText to be able to arrange other elements of the composer
+ if (s.isEmpty() != isEmptyText) {
+ isEmptyText = !isEmptyText
+ callback?.onTextEmptyStateChanged(isEmptyText)
+ }
}
}
)
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/TextComposerView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/TextComposerView.kt
index 6c7721ca02..d5e24dbb6b 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/TextComposerView.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/TextComposerView.kt
@@ -24,6 +24,7 @@ import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.core.text.toSpannable
+import androidx.core.view.isVisible
import androidx.transition.ChangeBounds
import androidx.transition.Fade
import androidx.transition.Transition
@@ -32,8 +33,6 @@ import androidx.transition.TransitionSet
import im.vector.app.R
import im.vector.app.databinding.ComposerLayoutBinding
-import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel
-
/**
* Encapsulate the timeline composer UX.
*
@@ -70,6 +69,10 @@ class TextComposerView @JvmOverloads constructor(
override fun onRichContentSelected(contentUri: Uri): Boolean {
return callback?.onRichContentSelected(contentUri) ?: false
}
+
+ override fun onTextEmptyStateChanged(isEmpty: Boolean) {
+ views.sendButton.isVisible = currentConstraintSetId == R.layout.composer_layout_constraint_set_expanded || !isEmpty
+ }
}
views.composerRelatedMessageCloseButton.setOnClickListener {
collapse()
@@ -93,6 +96,7 @@ class TextComposerView @JvmOverloads constructor(
}
currentConstraintSetId = R.layout.composer_layout_constraint_set_compact
applyNewConstraintSet(animate, transitionComplete)
+ views.sendButton.isVisible = !views.composerEditText.text.isNullOrEmpty()
}
fun expand(animate: Boolean = true, transitionComplete: (() -> Unit)? = null) {
@@ -102,6 +106,7 @@ class TextComposerView @JvmOverloads constructor(
}
currentConstraintSetId = R.layout.composer_layout_constraint_set_expanded
applyNewConstraintSet(animate, transitionComplete)
+ views.sendButton.isVisible = true
}
private fun applyNewConstraintSet(animate: Boolean, transitionComplete: (() -> Unit)?) {
@@ -110,8 +115,6 @@ class TextComposerView @JvmOverloads constructor(
}
ConstraintSet().also {
it.clone(context, currentConstraintSetId)
- // in case shield is hidden, we will have glitch without this
- it.getConstraint(R.id.composerShieldImageView).propertySet.visibility = views.composerShieldImageView.visibility
it.applyTo(this)
}
}
@@ -139,13 +142,11 @@ class TextComposerView @JvmOverloads constructor(
TransitionManager.beginDelayedTransition((parent as? ViewGroup ?: this), transition)
}
- fun setRoomEncrypted(isEncrypted: Boolean, roomEncryptionTrustLevel: RoomEncryptionTrustLevel?) {
+ fun setRoomEncrypted(isEncrypted: Boolean) {
if (isEncrypted) {
views.composerEditText.setHint(R.string.room_message_placeholder)
- views.composerShieldImageView.render(roomEncryptionTrustLevel)
} else {
views.composerEditText.setHint(R.string.room_message_placeholder)
- views.composerShieldImageView.render(null)
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/readreceipts/DisplayReadReceiptItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/readreceipts/DisplayReadReceiptItem.kt
index b95239df44..c097b9adb5 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/readreceipts/DisplayReadReceiptItem.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/readreceipts/DisplayReadReceiptItem.kt
@@ -23,7 +23,9 @@ import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import com.airbnb.epoxy.EpoxyModelWithHolder
import im.vector.app.R
+import im.vector.app.core.epoxy.ClickListener
import im.vector.app.core.epoxy.VectorEpoxyHolder
+import im.vector.app.core.epoxy.onClick
import im.vector.app.features.home.AvatarRenderer
import org.matrix.android.sdk.api.util.MatrixItem
@@ -33,7 +35,7 @@ abstract class DisplayReadReceiptItem : EpoxyModelWithHolder Unit)? = null
+ @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var userClicked: ClickListener? = null
override fun bind(holder: Holder) {
super.bind(holder)
@@ -45,7 +47,7 @@ abstract class DisplayReadReceiptItem : EpoxyModelWithHolder) {
- readReceipts.forEach {
- val timestamp = dateFormatter.format(it.timestamp, DateFormatKind.DEFAULT_DATE_AND_TIME)
+ readReceipts.forEach { readReceiptData ->
+ val timestamp = dateFormatter.format(readReceiptData.timestamp, DateFormatKind.DEFAULT_DATE_AND_TIME)
DisplayReadReceiptItem_()
- .id(it.userId)
- .matrixItem(it.toMatrixItem())
+ .id(readReceiptData.userId)
+ .matrixItem(readReceiptData.toMatrixItem())
.avatarRenderer(avatarRender)
.timestamp(timestamp)
- .userClicked { listener?.didSelectUser(it.userId) }
- .addIf(session.myUserId != it.userId, this)
+ .userClicked { listener?.didSelectUser(readReceiptData.userId) }
+ .addIf(session.myUserId != readReceiptData.userId, this)
}
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchFragment.kt
index 9a57d9480c..9f34cdd679 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchFragment.kt
@@ -71,7 +71,7 @@ class SearchFragment @Inject constructor(
private fun configureRecyclerView() {
views.searchResultRecycler.trackItemsVisibilityChange()
- views.searchResultRecycler.configureWith(controller, showDivider = false)
+ views.searchResultRecycler.configureWith(controller)
(views.searchResultRecycler.layoutManager as? LinearLayoutManager)?.stackFromEnd = true
controller.listener = this
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultController.kt
index 74bd168d09..1debf32104 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultController.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultController.kt
@@ -29,7 +29,7 @@ import im.vector.app.core.date.VectorDateFormatter
import im.vector.app.core.epoxy.loadingItem
import im.vector.app.core.epoxy.noResultItem
import im.vector.app.core.resources.StringProvider
-import im.vector.app.core.ui.list.GenericItemHeader_
+import im.vector.app.core.ui.list.GenericHeaderItem_
import im.vector.app.features.home.AvatarRenderer
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.events.model.Content
@@ -111,7 +111,7 @@ class SearchResultController @Inject constructor(
timeInMillis = eventAndSender.event.originServerTs ?: System.currentTimeMillis()
}
if (lastDate?.get(Calendar.DAY_OF_YEAR) != eventDate.get(Calendar.DAY_OF_YEAR)) {
- GenericItemHeader_()
+ GenericHeaderItem_()
.id(eventDate.hashCode())
.text(dateFormatter.format(eventDate.timeInMillis, DateFormatKind.EDIT_HISTORY_HEADER))
.let { result.add(it) }
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultItem.kt
index a3e5983c3a..14ea94ffd5 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultItem.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultItem.kt
@@ -36,7 +36,7 @@ abstract class SearchResultItem : VectorEpoxyModel() {
@EpoxyAttribute var formattedDate: String? = null
@EpoxyAttribute lateinit var spannable: CharSequence
@EpoxyAttribute var sender: MatrixItem? = null
- @EpoxyAttribute var listener: ClickListener? = null
+ @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var listener: ClickListener? = null
override fun bind(holder: Holder) {
super.bind(holder)
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt
index e7c48739fc..414bf3cca1 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt
@@ -15,19 +15,18 @@
*/
package im.vector.app.features.home.room.detail.timeline.action
-import android.view.View
import com.airbnb.epoxy.TypedEpoxyController
import com.airbnb.mvrx.Success
import im.vector.app.EmojiCompatFontProvider
import im.vector.app.R
import im.vector.app.core.date.DateFormatKind
import im.vector.app.core.date.VectorDateFormatter
+import im.vector.app.core.epoxy.bottomSheetDividerItem
import im.vector.app.core.epoxy.bottomsheet.BottomSheetQuickReactionsItem
import im.vector.app.core.epoxy.bottomsheet.bottomSheetActionItem
import im.vector.app.core.epoxy.bottomsheet.bottomSheetMessagePreviewItem
import im.vector.app.core.epoxy.bottomsheet.bottomSheetQuickReactionsItem
import im.vector.app.core.epoxy.bottomsheet.bottomSheetSendStateItem
-import im.vector.app.core.epoxy.dividerItem
import im.vector.app.core.error.ErrorFormatter
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.utils.DimensionConverter
@@ -107,7 +106,7 @@ class MessageActionsEpoxyController @Inject constructor(
}
when (state.informationData.e2eDecoration) {
- E2EDecoration.WARN_IN_CLEAR -> {
+ E2EDecoration.WARN_IN_CLEAR -> {
bottomSheetSendStateItem {
id("e2e_clear")
showProgress(false)
@@ -132,7 +131,7 @@ class MessageActionsEpoxyController @Inject constructor(
// Quick reactions
if (state.canReact() && state.quickStates is Success) {
// Separator
- dividerItem {
+ bottomSheetDividerItem {
id("reaction_separator")
}
@@ -151,7 +150,7 @@ class MessageActionsEpoxyController @Inject constructor(
if (state.actions.isNotEmpty()) {
// Separator
- dividerItem {
+ bottomSheetDividerItem {
id("actions_separator")
}
}
@@ -159,7 +158,7 @@ class MessageActionsEpoxyController @Inject constructor(
// Action
state.actions.forEachIndexed { index, action ->
if (action is EventSharedAction.Separator) {
- dividerItem {
+ bottomSheetDividerItem {
id("separator_$index")
}
} else {
@@ -169,7 +168,7 @@ class MessageActionsEpoxyController @Inject constructor(
textRes(action.titleRes)
showExpand(action is EventSharedAction.ReportContent)
expanded(state.expendedReportContentMenu)
- listener(View.OnClickListener { host.listener?.didSelectMenuAction(action) })
+ listener { host.listener?.didSelectMenuAction(action) }
destructive(action.destructive)
}
@@ -185,7 +184,7 @@ class MessageActionsEpoxyController @Inject constructor(
subMenuItem(true)
iconRes(actionReport.iconResId)
textRes(actionReport.titleRes)
- listener(View.OnClickListener { host.listener?.didSelectMenuAction(actionReport) })
+ listener { host.listener?.didSelectMenuAction(actionReport) }
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryBottomSheet.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryBottomSheet.kt
index 63dfe97d7e..7be4be4b57 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryBottomSheet.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryBottomSheet.kt
@@ -56,7 +56,7 @@ class ViewEditHistoryBottomSheet:
super.onViewCreated(view, savedInstanceState)
views.bottomSheetRecyclerView.configureWith(
epoxyController,
- showDivider = true,
+ dividerDrawable = R.drawable.divider_horizontal_on_secondary,
hasFixedSize = false)
views.bottomSheetTitle.text = context?.getString(R.string.message_edits)
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryEpoxyController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryEpoxyController.kt
index c3c53084ed..ed9f831018 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryEpoxyController.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryEpoxyController.kt
@@ -26,8 +26,8 @@ import im.vector.app.core.date.VectorDateFormatter
import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.ui.list.genericFooterItem
+import im.vector.app.core.ui.list.genericHeaderItem
import im.vector.app.core.ui.list.genericItem
-import im.vector.app.core.ui.list.genericItemHeader
import im.vector.app.core.ui.list.genericLoaderItem
import im.vector.app.features.html.EventHtmlRenderer
import me.gujun.android.span.span
@@ -87,7 +87,7 @@ class ViewEditHistoryEpoxyController @Inject constructor(
}
if (lastDate?.get(Calendar.DAY_OF_YEAR) != evDate.get(Calendar.DAY_OF_YEAR)) {
// need to display header with day
- genericItemHeader {
+ genericHeaderItem {
id(evDate.hashCode())
text(host.dateFormatter.format(evDate.timeInMillis, DateFormatKind.EDIT_HISTORY_HEADER))
}
@@ -112,14 +112,14 @@ class ViewEditHistoryEpoxyController @Inject constructor(
diff_match_patch.Operation.DELETE -> {
span {
text = it.text.replace("\n", " ")
- textColor = colorProvider.getColor(R.color.vector_error_color)
+ textColor = colorProvider.getColorFromAttribute(R.attr.colorError)
textDecorationLine = "line-through"
}
}
diff_match_patch.Operation.INSERT -> {
span {
text = it.text
- textColor = colorProvider.getColor(R.color.vector_success_color)
+ textColor = colorProvider.getColor(R.color.palette_element_green)
}
}
else -> {
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt
index 82d3dea311..662846704c 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt
@@ -65,10 +65,10 @@ class EncryptedItemFactory @Inject constructor(private val messageInformationDat
?: stringProvider.getString(R.string.notice_crypto_unable_to_decrypt, errorDescription)
span(message) {
textStyle = "italic"
- textColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
+ textColor = colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary)
}
} else {
- val colorFromAttribute = colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
+ val colorFromAttribute = colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary)
if (cryptoError == null) {
span(stringProvider.getString(R.string.encrypted_message)) {
textStyle = "italic"
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt
index 7b9601ad33..b1bac3378e 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt
@@ -29,7 +29,6 @@ import im.vector.app.core.epoxy.VectorEpoxyModel
import im.vector.app.core.files.LocalFilesHelper
import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.resources.StringProvider
-import im.vector.app.core.utils.DebouncedClickListener
import im.vector.app.core.utils.DimensionConverter
import im.vector.app.core.utils.containsOnlyEmojis
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
@@ -322,10 +321,9 @@ class MessageItemFactory @Inject constructor(
if (messageContent.msgType == MessageType.MSGTYPE_STICKER_LOCAL) {
mode(ImageContentRenderer.Mode.STICKER)
} else {
- clickListener(
- DebouncedClickListener({ view ->
- callback?.onImageMessageClicked(messageContent, data, view)
- }))
+ clickListener { view ->
+ callback?.onImageMessageClicked(messageContent, data, view)
+ }
}
}
}
@@ -470,7 +468,7 @@ class MessageItemFactory @Inject constructor(
spannable.append(linkifiedBody)
val editedSuffix = stringProvider.getString(R.string.edited_suffix)
spannable.append(" ").append(editedSuffix)
- val color = colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
+ val color = colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary)
val editStart = spannable.lastIndexOf(editedSuffix)
val editEnd = editStart + editedSuffix.length
spannable.setSpan(
@@ -510,7 +508,7 @@ class MessageItemFactory @Inject constructor(
val htmlBody = messageContent.getHtmlBody()
val formattedBody = span {
text = htmlBody
- textColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
+ textColor = colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary)
textStyle = "italic"
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/ReadReceiptsItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/ReadReceiptsItemFactory.kt
index 1d015d1bca..8a74a6d207 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/ReadReceiptsItemFactory.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/ReadReceiptsItemFactory.kt
@@ -16,7 +16,6 @@
package im.vector.app.features.home.room.detail.timeline.factory
-import im.vector.app.core.utils.DebouncedClickListener
import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
import im.vector.app.features.home.room.detail.timeline.item.ReadReceiptData
@@ -42,8 +41,8 @@ class ReadReceiptsItemFactory @Inject constructor(private val avatarRenderer: Av
.eventId(eventId)
.readReceipts(readReceiptsData)
.avatarRenderer(avatarRenderer)
- .clickListener(DebouncedClickListener({ _ ->
+ .clickListener {
callback?.onReadReceiptsClicked(readReceiptsData)
- }))
+ }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/DisplayableEventFormatter.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/DisplayableEventFormatter.kt
index 499e27f838..b4fe593ea3 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/DisplayableEventFormatter.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/DisplayableEventFormatter.kt
@@ -143,7 +143,7 @@ class DisplayableEventFormatter @Inject constructor(
return if (appendAuthor) {
span {
text = senderName
- textColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_primary)
+ textColor = colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)
}
.append(": ")
.append(body)
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/MatrixItemColorProvider.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/MatrixItemColorProvider.kt
index ed343d52ef..bdd95e4d09 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/MatrixItemColorProvider.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/MatrixItemColorProvider.kt
@@ -53,23 +53,23 @@ class MatrixItemColorProvider @Inject constructor(
userId?.toList()?.map { chr -> hash = (hash shl 5) - hash + chr.code }
return when (abs(hash) % 8) {
- 1 -> R.color.riotx_username_2
- 2 -> R.color.riotx_username_3
- 3 -> R.color.riotx_username_4
- 4 -> R.color.riotx_username_5
- 5 -> R.color.riotx_username_6
- 6 -> R.color.riotx_username_7
- 7 -> R.color.riotx_username_8
- else -> R.color.riotx_username_1
+ 1 -> R.color.element_name_02
+ 2 -> R.color.element_name_03
+ 3 -> R.color.element_name_04
+ 4 -> R.color.element_name_05
+ 5 -> R.color.element_name_06
+ 6 -> R.color.element_name_07
+ 7 -> R.color.element_name_08
+ else -> R.color.element_name_01
}
}
@ColorRes
private fun getColorFromRoomId(roomId: String?): Int {
return when ((roomId?.toList()?.sumOf { it.code } ?: 0) % 3) {
- 1 -> R.color.riotx_avatar_fill_2
- 2 -> R.color.riotx_avatar_fill_3
- else -> R.color.riotx_avatar_fill_1
+ 1 -> R.color.element_room_02
+ 2 -> R.color.element_room_03
+ else -> R.color.element_room_01
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/MessageItemAttributesFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/MessageItemAttributesFactory.kt
index 043fd9e896..679613d262 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/MessageItemAttributesFactory.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/MessageItemAttributesFactory.kt
@@ -16,7 +16,6 @@
package im.vector.app.features.home.room.detail.timeline.helper
import im.vector.app.EmojiCompatFontProvider
-import im.vector.app.core.utils.DebouncedClickListener
import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.home.room.detail.timeline.MessageColorProvider
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
@@ -41,12 +40,12 @@ class MessageItemAttributesFactory @Inject constructor(
itemLongClickListener = { view ->
callback?.onEventLongClicked(informationData, messageContent, view) ?: false
},
- itemClickListener = DebouncedClickListener({ view ->
+ itemClickListener = { view ->
callback?.onEventCellClicked(informationData, messageContent, view)
- }),
- memberClickListener = DebouncedClickListener({
+ },
+ memberClickListener = {
callback?.onMemberNameClicked(informationData)
- }),
+ },
reactionPillCallback = callback,
avatarCallback = callback,
readReceiptsCallback = callback,
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsBaseMessageItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsBaseMessageItem.kt
index 39c04af089..080b766258 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsBaseMessageItem.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsBaseMessageItem.kt
@@ -23,6 +23,8 @@ import android.widget.TextView
import androidx.annotation.IdRes
import androidx.core.view.isVisible
import im.vector.app.R
+import im.vector.app.core.epoxy.ClickListener
+import im.vector.app.core.epoxy.onClick
import im.vector.app.core.ui.views.ShieldImageView
import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.home.room.detail.timeline.MessageColorProvider
@@ -94,7 +96,7 @@ abstract class AbsBaseMessageItem : BaseEventItem
}
}
- holder.view.setOnClickListener(baseAttributes.itemClickListener)
+ holder.view.onClick(baseAttributes.itemClickListener)
holder.view.setOnLongClickListener(baseAttributes.itemLongClickListener)
}
@@ -124,9 +126,9 @@ abstract class AbsBaseMessageItem : BaseEventItem
val avatarRenderer: AvatarRenderer
val messageColorProvider: MessageColorProvider
val itemLongClickListener: View.OnLongClickListener?
- val itemClickListener: View.OnClickListener?
+ val itemClickListener: ClickListener?
- // val memberClickListener: View.OnClickListener?
+ // val memberClickListener: ClickListener?
val reactionPillCallback: TimelineEventController.ReactionPillCallback?
// val avatarCallback: TimelineEventController.AvatarCallback?
@@ -139,7 +141,7 @@ abstract class AbsBaseMessageItem : BaseEventItem
// override val avatarRenderer: AvatarRenderer,
// override val colorProvider: ColorProvider,
// override val itemLongClickListener: View.OnLongClickListener? = null,
-// override val itemClickListener: View.OnClickListener? = null,
+// override val itemClickListener: ClickListener? = null,
// override val reactionPillCallback: TimelineEventController.ReactionPillCallback? = null,
// override val readReceiptsCallback: TimelineEventController.ReadReceiptsCallback? = null
// ) : Attributes
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsMessageItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsMessageItem.kt
index ed61abcf6e..fd5eea1b49 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsMessageItem.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsMessageItem.kt
@@ -26,8 +26,9 @@ import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import com.airbnb.epoxy.EpoxyAttribute
import im.vector.app.R
+import im.vector.app.core.epoxy.ClickListener
+import im.vector.app.core.epoxy.onClick
import im.vector.app.core.ui.views.SendStateImageView
-import im.vector.app.core.utils.DebouncedClickListener
import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.home.room.detail.timeline.MessageColorProvider
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
@@ -44,12 +45,17 @@ abstract class AbsMessageItem : AbsBaseMessageItem
@EpoxyAttribute
lateinit var attributes: Attributes
- private val _avatarClickListener = DebouncedClickListener({
- attributes.avatarCallback?.onAvatarClicked(attributes.informationData)
- })
- private val _memberNameClickListener = DebouncedClickListener({
- attributes.avatarCallback?.onMemberNameClicked(attributes.informationData)
- })
+ private val _avatarClickListener = object : ClickListener {
+ override fun invoke(p1: View) {
+ attributes.avatarCallback?.onAvatarClicked(attributes.informationData)
+ }
+ }
+
+ private val _memberNameClickListener = object : ClickListener {
+ override fun invoke(p1: View) {
+ attributes.avatarCallback?.onMemberNameClicked(attributes.informationData)
+ }
+ }
override fun bind(holder: H) {
super.bind(holder)
@@ -59,9 +65,9 @@ abstract class AbsMessageItem : AbsBaseMessageItem
width = attributes.avatarSize
}
holder.avatarImageView.visibility = View.VISIBLE
- holder.avatarImageView.setOnClickListener(_avatarClickListener)
+ holder.avatarImageView.onClick(_avatarClickListener)
holder.memberNameView.visibility = View.VISIBLE
- holder.memberNameView.setOnClickListener(_memberNameClickListener)
+ holder.memberNameView.onClick(_memberNameClickListener)
holder.timeView.visibility = View.VISIBLE
holder.timeView.text = attributes.informationData.time
holder.memberNameView.text = attributes.informationData.memberName
@@ -118,8 +124,8 @@ abstract class AbsMessageItem : AbsBaseMessageItem
override val avatarRenderer: AvatarRenderer,
override val messageColorProvider: MessageColorProvider,
override val itemLongClickListener: View.OnLongClickListener? = null,
- override val itemClickListener: View.OnClickListener? = null,
- val memberClickListener: View.OnClickListener? = null,
+ override val itemClickListener: ClickListener? = null,
+ val memberClickListener: ClickListener? = null,
override val reactionPillCallback: TimelineEventController.ReactionPillCallback? = null,
val avatarCallback: TimelineEventController.AvatarCallback? = null,
override val readReceiptsCallback: TimelineEventController.ReadReceiptsCallback? = null,
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/CallTileTimelineItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/CallTileTimelineItem.kt
index 2d40035df1..a9b6bbf0aa 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/CallTileTimelineItem.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/CallTileTimelineItem.kt
@@ -28,6 +28,8 @@ import androidx.core.view.updateLayoutParams
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
+import im.vector.app.core.epoxy.ClickListener
+import im.vector.app.core.epoxy.onClick
import im.vector.app.core.extensions.setLeftDrawable
import im.vector.app.core.extensions.setTextWithColoredPart
import im.vector.app.features.home.AvatarRenderer
@@ -64,11 +66,11 @@ abstract class CallTileTimelineItem : AbsBaseMessageItem {
holder.rejectView.setText(R.string.ignore)
holder.acceptView.setText(R.string.join)
- holder.acceptView.setLeftDrawable(R.drawable.ic_call_audio_small, R.color.riotx_accent)
+ holder.acceptView.setLeftDrawable(R.drawable.ic_call_audio_small, R.attr.colorPrimary)
}
CallKind.AUDIO -> {
holder.rejectView.setText(R.string.call_notification_reject)
holder.acceptView.setText(R.string.call_notification_answer)
- holder.acceptView.setLeftDrawable(R.drawable.ic_call_audio_small, R.color.riotx_accent)
+ holder.acceptView.setLeftDrawable(R.drawable.ic_call_audio_small, R.attr.colorPrimary)
}
CallKind.VIDEO -> {
holder.rejectView.setText(R.string.call_notification_reject)
holder.acceptView.setText(R.string.call_notification_answer)
- holder.acceptView.setLeftDrawable(R.drawable.ic_call_video_small, R.color.riotx_accent)
+ holder.acceptView.setLeftDrawable(R.drawable.ic_call_video_small, R.attr.colorPrimary)
}
else -> {
Timber.w("Shouldn't be in that state")
@@ -147,7 +149,7 @@ abstract class CallTileTimelineItem : AbsBaseMessageItem
+ holder.roomAvatarImageView.onClick { view ->
if (shouldSetAvatar) {
attributes.callback?.onTimelineItemAction(RoomDetailAction.QuickActionSetAvatar)
} else {
// Note: this is no op if there is no avatar on the room
attributes.callback?.onTimelineItemAction(RoomDetailAction.ShowRoomAvatarFullScreen(roomItem, view))
}
- }))
+ }
}
holder.setAvatarButton.isVisible = shouldSetAvatar
if (shouldSetAvatar) {
- holder.setAvatarButton.setOnClickListener(DebouncedClickListener({
+ holder.setAvatarButton.onClick {
attributes.callback?.onTimelineItemAction(RoomDetailAction.QuickActionSetAvatar)
- }))
+ }
}
holder.addPeopleButton.isVisible = !isDirect
if (!isDirect) {
- holder.addPeopleButton.setOnClickListener(DebouncedClickListener({
+ holder.addPeopleButton.onClick {
attributes.callback?.onTimelineItemAction(RoomDetailAction.QuickActionInvitePeople)
- }))
+ }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageBlockCodeItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageBlockCodeItem.kt
index def79e4fe6..3f6add5699 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageBlockCodeItem.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageBlockCodeItem.kt
@@ -20,6 +20,7 @@ import android.widget.TextView
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
+import im.vector.app.core.epoxy.onClick
import im.vector.app.core.extensions.setTextOrHide
import me.saket.bettermovementmethod.BetterLinkMovementMethod
@@ -36,7 +37,7 @@ abstract class MessageBlockCodeItem : AbsMessageItem() {
var iconRes: Int = 0
// @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
-// var clickListener: View.OnClickListener? = null
+// var clickListener: ClickListener? = null
@EpoxyAttribute
var izLocalFile = false
@@ -81,9 +82,9 @@ abstract class MessageFileItem : AbsMessageItem() {
}
// holder.view.setOnClickListener(clickListener)
- holder.filenameView.setOnClickListener(attributes.itemClickListener)
+ holder.filenameView.onClick(attributes.itemClickListener)
holder.filenameView.setOnLongClickListener(attributes.itemLongClickListener)
- holder.fileImageWrapper.setOnClickListener(attributes.itemClickListener)
+ holder.fileImageWrapper.onClick(attributes.itemClickListener)
holder.fileImageWrapper.setOnLongClickListener(attributes.itemLongClickListener)
holder.filenameView.paintFlags = (holder.filenameView.paintFlags or Paint.UNDERLINE_TEXT_FLAG)
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageImageVideoItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageImageVideoItem.kt
index 2c0d1fcfbd..3ae91db97c 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageImageVideoItem.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageImageVideoItem.kt
@@ -24,6 +24,8 @@ import androidx.core.view.isVisible
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
+import im.vector.app.core.epoxy.ClickListener
+import im.vector.app.core.epoxy.onClick
import im.vector.app.core.files.LocalFilesHelper
import im.vector.app.core.glide.GlideApp
import im.vector.app.features.home.room.detail.timeline.helper.ContentUploadStateTrackerBinder
@@ -42,7 +44,7 @@ abstract class MessageImageVideoItem : AbsMessageItem()
as MaterialButton
holder.buttonContainer.addView(materialButton, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
materialButton.text = option.label
- materialButton.setOnClickListener {
+ materialButton.onClick {
callback?.onTimelineItemAction(RoomDetailAction.ReplyToOptions(relatedEventId, index, option.value ?: "$index"))
}
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessagePollItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessagePollItem.kt
index ca5c3b2dea..2178843c28 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessagePollItem.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessagePollItem.kt
@@ -24,8 +24,9 @@ import androidx.core.view.isVisible
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
+import im.vector.app.core.epoxy.ClickListener
+import im.vector.app.core.epoxy.onClick
import im.vector.app.core.extensions.setTextOrHide
-import im.vector.app.core.utils.DebouncedClickListener
import im.vector.app.features.home.room.detail.RoomDetailAction
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
import org.matrix.android.sdk.api.session.room.model.message.MessageOptionsContent
@@ -143,14 +144,16 @@ abstract class MessagePollItem : AbsMessageItem() {
override fun bindView(itemView: View) {
super.bindView(itemView)
val buttons = listOf(button1, button2, button3, button4, button5)
- val clickListener = DebouncedClickListener({
- val optionIndex = buttons.indexOf(it)
- if (optionIndex != -1 && pollId != null) {
- val compatValue = if (optionIndex < optionValues?.size ?: 0) optionValues?.get(optionIndex) else null
- callback?.onTimelineItemAction(RoomDetailAction.ReplyToOptions(pollId!!, optionIndex, compatValue ?: "$optionIndex"))
+ val clickListener = object : ClickListener {
+ override fun invoke(p1: View) {
+ val optionIndex = buttons.indexOf(p1)
+ if (optionIndex != -1 && pollId != null) {
+ val compatValue = if (optionIndex < optionValues?.size ?: 0) optionValues?.get(optionIndex) else null
+ callback?.onTimelineItemAction(RoomDetailAction.ReplyToOptions(pollId!!, optionIndex, compatValue ?: "$optionIndex"))
+ }
}
- })
- buttons.forEach { it.setOnClickListener(clickListener) }
+ }
+ buttons.forEach { it.onClick(clickListener) }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageTextItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageTextItem.kt
index 86b83cbe47..c6dce5a9ce 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageTextItem.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageTextItem.kt
@@ -24,6 +24,7 @@ import androidx.core.widget.TextViewCompat
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
+import im.vector.app.core.epoxy.onClick
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
import im.vector.app.features.home.room.detail.timeline.tools.findPillsAndProcess
import im.vector.app.features.home.room.detail.timeline.url.PreviewUrlRetriever
@@ -95,7 +96,7 @@ abstract class MessageTextItem : AbsMessageItem