Merge branch 'develop' into feature/fga/dial_pad_tab
# Conflicts: # vector/src/main/java/im/vector/app/features/call/dialpad/DialPadFragment.kt # vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt
This commit is contained in:
commit
880da9ecd5
|
@ -37,6 +37,7 @@
|
||||||
<w>threepid</w>
|
<w>threepid</w>
|
||||||
<w>unpublish</w>
|
<w>unpublish</w>
|
||||||
<w>unwedging</w>
|
<w>unwedging</w>
|
||||||
|
<w>vctr</w>
|
||||||
</words>
|
</words>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
</component>
|
</component>
|
|
@ -44,6 +44,9 @@ Other changes:
|
||||||
- Add documentation on LoginWizard and RegistrationWizard (#3303)
|
- Add documentation on LoginWizard and RegistrationWizard (#3303)
|
||||||
- Setup towncrier tool (#3293)
|
- Setup towncrier tool (#3293)
|
||||||
|
|
||||||
|
Security:
|
||||||
|
- Element Android shares name of E2EE files with homeserver (#3387)
|
||||||
|
|
||||||
Changes in Element 1.1.7 (2021-05-12)
|
Changes in Element 1.1.7 (2021-05-12)
|
||||||
===================================================
|
===================================================
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ To install the template (to be done only once):
|
||||||
|
|
||||||
To create a new screen:
|
To create a new screen:
|
||||||
- First create a new package in your code.
|
- 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.
|
- Follow the Wizard, especially replace `Main` by something more relevant to your feature.
|
||||||
- Click on `Finish`.
|
- Click on `Finish`.
|
||||||
- Remaining steps are described as TODO in the generated files, or will be pointed out by the compiler, or at runtime :)
|
- Remaining steps are described as TODO in the generated files, or will be pointed out by the compiler, or at runtime :)
|
||||||
|
|
|
@ -55,7 +55,7 @@ dependencies {
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||||
implementation 'androidx.core:core-ktx:1.5.0'
|
implementation 'androidx.core:core-ktx:1.5.0'
|
||||||
implementation 'androidx.appcompat:appcompat:1.3.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'
|
implementation 'com.google.android.material:material:1.3.0'
|
||||||
}
|
}
|
|
@ -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
|
|
@ -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í
|
<b>Mezi funkce aplikace Element patří:</b>
|
||||||
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
|
- Pokročilé nástroje pro online komunikaci
|
||||||
3. Ochrání vás před inzercí, dataminingem a uzavřenými zahradami
|
- Plně šifrované zprávy umožňující bezpečnější firemní komunikaci i pro pracovníky na dálku
|
||||||
4. Zabezpečí vás end-to-end šifrováním s křížovým podpisem pro ověření ostatních
|
- 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ý.
|
<b>Soukromí a šifrované zprávy</b>
|
||||||
|
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:
|
<b>Element lze hostovat samostatně</b>
|
||||||
|
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
|
<b>Vlastněte svá data</b>
|
||||||
2. Hostujte svůj účet spuštěním serveru na svém vlastním hardwaru
|
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.
|
||||||
3. Zaregistrujte si účet na vlastním serveru jednoduchým přihlášením k hostitelské platformě Element Matrix Services
|
|
||||||
|
|
||||||
<b>Proč zvolit Element?</b>
|
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.
|
||||||
|
|
||||||
<b>VLASTNĚTE SVÁ DATA</b>: 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.
|
<b>Otevřené zasílání zpráv a spolupráce</b>
|
||||||
|
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.
|
||||||
|
|
||||||
<b>ZPRÁVY A SPOLUPRÁCE</b>: 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.
|
<b>Superbezpečné</b>
|
||||||
|
Skutečné end-to-end šifrování (zprávy mohou dešifrovat pouze účastníci konverzace) a křížové ověřování zařízení.
|
||||||
|
|
||||||
<b>MAXIMÁLNĚ BEZPEČNÉ</b>: 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.
|
<b>Kompletní komunikace a integrace</b>
|
||||||
|
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.
|
||||||
|
|
||||||
<b>KOMPLETNÍ KOMUNIKACE</b>: 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.
|
<b>Navažte tam, kde jste skončili</b>
|
||||||
|
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
|
||||||
<b>KDEKOLIV JSTE</b>: 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.
|
|
||||||
|
|
|
@ -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
|
|
@ -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.
|
||||||
|
|
||||||
<b>Element bietet folgende Funktionen:</b>
|
<b>Element bietet folgende Funktionen:</b>
|
||||||
- Fortschrittliche Werkzeuge für die Online-Kommunikation
|
- 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
|
- 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
|
- Sichere und kontrollierte Dateifreigabe durch verschlüsselte Daten beim Verwalten von Projekten
|
||||||
- Videochats mit VoIP und Bildschirmübertragung
|
- Videochats mit VoIP und Bildschirmübertragung
|
||||||
- Einfache Einbindung in Ihre bevorzugten Online-Kollaborations- und Projektverwaltungswerkzeuge, VoIP-Dienste und andere Kommunikationsapps für Ihr Team
|
- 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.
|
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.
|
||||||
|
|
||||||
<b>Privatsphäre/Datenschutz und verschlüsselte Kommunikation</b>
|
<b>Privatsphäre/Datenschutz und verschlüsselte Kommunikation</b>
|
||||||
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.
|
||||||
|
|
||||||
<b>Element kann man selber betreiben</b>
|
<b>Element kann man selber betreiben</b>
|
||||||
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.
|
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.
|
||||||
|
|
||||||
<b>Besitzen Sie Ihre Daten</b>
|
<b>Besitzen Sie Ihre Daten</b>
|
||||||
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:
|
Element gibt Ihnen auf verschiedene Arten 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
|
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. Ein Konto auf einem eigenen Server in der eigenen IT-Infrastruktur betreiben
|
2. Sie haben die Möglichkeit, 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)
|
3. Außerdem können Sie durch ein Abonnement der Element Matrix Services ein Konto auf einem für Sie maßgeschneiderten Server erstellen
|
||||||
|
|
||||||
<b>Offene Kommunikation und Zusammenarbeit</b>
|
<b>Offene Kommunikation und Zusammenarbeit</b>
|
||||||
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.
|
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.
|
||||||
|
|
||||||
<b>Super sicher</b>
|
<b>Super sicher</b>
|
||||||
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.
|
||||||
|
|
||||||
<b>Vollständige Kommunikation und Integration</b>
|
<b>Vollständige Kommunikation und Integration</b>
|
||||||
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.
|
||||||
|
|
||||||
<b>Da Weitermachen, wo Sie aufgehört haben</b>
|
<b>Da Weitermachen, wo Sie aufgehört haben</b>
|
||||||
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
|
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
|
||||||
|
|
|
@ -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
|
|
@ -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!
|
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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
<b>Element tulajdonságai:</b>
|
||||||
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
|
- Fejlett online kommunikációs eszköz
|
||||||
3. Megvédheted magad a hirdetésektől, adatbányászattól, és a nagy cégek megoldásaiba való bezártságtól
|
- Teljesen titkosított üzenetküldés biztonságos céges kommunikációt kínál még a távdolgozóknak is
|
||||||
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
|
- 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.
|
<b>Magánélet védelme és titkosított üzenetküldés</b>
|
||||||
|
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:
|
<b>Element futtatható saját szerveren</b>
|
||||||
|
|
||||||
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
|
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.
|
||||||
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
|
|
||||||
|
|
||||||
<b>Miért jó az Element-et választani?</b>
|
<b>A te adatod a tiéd</b>
|
||||||
|
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.
|
||||||
|
|
||||||
<b>ADATAID MEGVÉDÉSE</b>: 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
|
||||||
|
|
||||||
<b>NYÍLT BESZÉLGETÉS, ÉS CSAPATMUNKA</b>: 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.
|
<b>Nyílt üzenetküldés és kollaboráció</b>
|
||||||
|
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.
|
||||||
|
|
||||||
<b>SZUPER-BIZTONSÁGOS</b>: 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.
|
<b>Fantasztikusan biztonságos</b>
|
||||||
|
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.
|
||||||
|
|
||||||
<b>TELJES KOMMUNIKÁCIÓ</b>: Ü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.
|
<b>Teljes kommunikáció és integráció</b>
|
||||||
|
Ü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.
|
||||||
|
|
||||||
<b>AKÁRHOL, AHOL CSAK SZÜKSÉG VAN RÁ</b>: 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.
|
<b>Vedd fel a fonalat</b>
|
||||||
|
Maradj kapcsolatban bárhol minden eszközödön a szinkronizált üzenetekkel és a weben a https://app.element.io oldallal
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Biztonságos, decentralizált chat és VoIP. Tartsd az adataid biztonságban.
|
Csoportos üzenetküldő - titkosított üzenetek, videó hívások
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Element (régebben Riot.im)
|
Element - Biztonságos üzenetküldő
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
||||||
|
Основні зміни в цій версії: бета-підтримка Spaces. Стиснення відео перед надсиланням.
|
||||||
|
Повний журнал змін: https://github.com/vector-im/element-android/releases/tag/v1.1.7
|
|
@ -1,30 +1,39 @@
|
||||||
Element — це застосунок для спілкування та співпраці нового типу, який:
|
Element — це і безпечний месенджер, і застосунок для співпраці команди, який ідеально підходить для групових бесід під час віддаленої роботи. Цей застосунок для спілкування застосовує наскрізне шифрування для забезпечення відеоконференцій, обміну файлами та голосових викликів.
|
||||||
|
|
||||||
1. Надає вам повний контроль за своєю конфіденційністю
|
<b>Можливості Element включають:</b>
|
||||||
2. Дозволяє спілкування з будь-ким у мережі Matrix та поза нею, інтегруючись із такими застосунками, як Slack
|
- Розширені засоби спілкування в Інтернеті
|
||||||
3. Убезпечує вас від реклами, збору даних та штучних обмежень
|
- Повністю зашифровані повідомлення для надання можливості безпечнішого корпоративного спілкування, навіть для віддалених працівників
|
||||||
4. Захищає ваше спілкування наскрізним шифруванням із перехресним підписуванням для звірення інших осіб
|
- Децентралізований чат на основі відкритого коду Matrix
|
||||||
|
- Безпечний обмін файлами із зашифрованими даними для керування проєктами
|
||||||
|
- Відеочати з передачею голосу через IP та показом екрану іншим
|
||||||
|
- Проста інтеграція з вашими улюбленими інструментами для онлайн-співпраці, інструментами керування проєктами, послугами VoIP та іншими застосунками обміну повідомленнями для команд
|
||||||
|
|
||||||
Element ґрунтовно відрізняється від інших застосунків для спілкування та співпраці тому що він є децентралізованим та відкритоджерельним.
|
Element цілковито відрізняється від інших застосунків обміну повідомленнями та спільної роботи. Він працює на Matrix, відкритій мережі для безпечного обміну повідомленнями та децентралізованого зв'язку. Це дозволяє самостійне розгортання, щоб надати користувачам якнайбільше володіння та контролю над їх даними та повідомленнями.
|
||||||
|
|
||||||
Element дозволяє вам розміщувати сервер в себе або обирати будь-якого з надавачів послуг, таким чином забезпечуючи вам конфіденційність і можливість володіти власними даними й бесідами та контролювати їх. Він надає вам доступ до відкритої мережі, тож ви не є обмеженими спілкуванням виключно з користувачами Element. І він є дуже надійним та безпечним.
|
<b>Приватність та обмін зашифрованими повідомленнями</b>
|
||||||
|
Element захищає вас від небажаної реклами, збору даних та обмежень. Він також захищає всі ваші дані, відео та голосовий зв'язок віч-на-віч за допомогою наскрізного шифрування та взаємного підписування пристроїв.
|
||||||
|
|
||||||
Element здатен забезпечити усе це завдяки тому, що він заснований на протоколі Matrix — стандарті для відкритого та децентралізованого спілкування.
|
Element дає вам можливість контролювати вашу приватність, одночасно дозволяючи вам безпечно спілкуватися з будь-ким у мережі Matrix або через інші інструменти ділової співпраці, інтегрувавшись із такими програмами, як Slack.
|
||||||
|
|
||||||
Element надає вам повний контроль, дозволяючи обирати з-поміж надавачів послуг, що обслуговують сервери з вашими бесідами. Ви вільні обрати будь-який спосіб розміщення прямо з застосунку Element:
|
<b>Element можна розгортати самостійно</b>
|
||||||
|
Щоб забезпечити більше контролю над вашими приватними даними та розмовами, Element можна самостійно розміщувати або ви можете вибрати будь-який вузол на основі Matrix — стандарт для децентралізованого спілкування з відкритим кодом. Element надає вам приватність, відповідність безпеці та гнучкість інтеграції.
|
||||||
|
|
||||||
1. Отримати безкоштовний обліковий запис на загальнодоступному сервері matrix.org, який обслуговують розробники Matrix, чи на одному з тисяч публічних серверів, які обслуговують волонтери
|
<b>Ваші дані</b>
|
||||||
2. Розмістити свій обліковий запис на власному сервері
|
Ви вирішуєте, де зберігати свої дані та повідомлення. Без ризику видобутку даних або стороннього доступу.
|
||||||
3. Зареєструватись на індивідуальному сервері, просто підписавшись на послуги платформи Element Matrix Services
|
|
||||||
|
|
||||||
<b>Чому я маю обрати Element?</b>
|
Element надає такі можливості на вибір:
|
||||||
|
1. Отримайте безплатний обліковий запис на загальнодоступному сервері matrix.org, розміщеному розробниками Matrix, або виберіть серед тисяч загальнодоступних серверів, розміщених волонтерами
|
||||||
|
2. Самостійно розмістіть свій обліковий запис, запустивши сервер на власній ІТ-інфраструктурі
|
||||||
|
3. Зареєструйте обліковий запис на власному сервері, просто підписавшись на хостинг-платформу Element Matrix Services
|
||||||
|
|
||||||
<b>ВОЛОДІЙТЕ ВАШИМИ ДАНИМИ</b>: Ви вирішуєте де тримати ваші дані та повідомлення. Саме ви володієте ними та контролюєте їх, а не якась Мегакорпорація, що збирає ваші дані та надає стороннім особам доступ до них.
|
<b>Відкриті обмін повідомленнями та співпраця</b>
|
||||||
|
Ви можете спілкуватися з усіма у мережі Matrix, незалежно від того, чи користуються вони Element, іншим застосунком Matrix або навіть якщо іншим застосунком для обміну повідомленнями.
|
||||||
|
|
||||||
<b>ВІДКРИТІ ОБМІН ПОВІДОМЛЕННЯМИ ТА СПІВПРАЦЯ</b>: Ви можете балакати з будь-ким у мережі Matrix, хоч вони користуються Element, хоч іншим застосунком для Matrix, і навіть якщо вони користуються іншою системою обміну повідомленнями на кшталт Slack, IRC чи XMPP.
|
<b>Надбезпечний</b>
|
||||||
|
Справжнє наскрізне шифрування (лише учасники бесіди можуть розшифровувати повідомлення) та взаємне підписування пристроїв.
|
||||||
|
|
||||||
<b>НАДБЕЗПЕЧНІСТЬ</b>: Справжнє наскрізне шифрування (лише ваші співрозмовники здатні дешифровувати повідомлення) та перехресне підписування для звірення пристроїв інших учасників бесіди.
|
<b>Повноцінні спілкування та інтеграція</b>
|
||||||
|
Обмін повідомленнями, голосові та відеовиклики, обмін файлами, спільний доступ до екрана та ціла купа інтеграцій, ботів та віджетів. Створюйте кімнати, спільноти, залишайтеся на зв’язку та виконуйте завдання.
|
||||||
|
|
||||||
<b>ДОВЕРШЕНИЙ ЗВʼЯЗОК</b>: Повідомлення, голосові та відеодзвінки, обмін файлами, розподіл екрану та ціла купа інтеграцій, ботів та знадобів. Створюйте кімнати й спільноти, залишайтесь на зв'язку та завершуйте свої справи.
|
<b>Продовжуйте, де зупинилися</b>
|
||||||
|
Залишайтеся на зв'язку, де б ви не знаходились, з повністю синхронізованою історією повідомлень на всіх своїх пристроях та в Інтернеті за адресою https://app.element.io
|
||||||
<b>ДЕ Б ВИ НЕ БУЛИ</b>: Залишайтесь на зв'язку де б ви не були, разом з синхронізовною історією листувань на усіх ваших пристроях та в Інтернеті на https://app.element.io.
|
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
此版本中的主要更新:改进性能和错误修复!
|
||||||
|
完整的更新记录:https://github.com/vector-im/element-android/releases/tag/v1.1.2
|
|
@ -0,0 +1,2 @@
|
||||||
|
此版本中的主要更新:改进性能和修复错误!
|
||||||
|
完整的更新记录:https://github.com/vector-im/element-android/releases/tag/v1.1.3
|
|
@ -0,0 +1,2 @@
|
||||||
|
此版本中的主要更新:改进性能和修复错误!
|
||||||
|
完整的更新记录:https://github.com/vector-im/element-android/releases/tag/v1.1.4
|
|
@ -0,0 +1,2 @@
|
||||||
|
此版本中的主要更新:1.1.4 的热修复
|
||||||
|
完整的更新记录:https://github.com/vector-im/element-android/releases/tag/v1.1.5
|
|
@ -0,0 +1,2 @@
|
||||||
|
此版本中的主要更新:1.1.5 的热修复
|
||||||
|
完整的更新记录:https://github.com/vector-im/element-android/releases/tag/v1.1.6
|
|
@ -0,0 +1,2 @@
|
||||||
|
此版本中的主要更新:对「空间」的测试版支持。发送前压缩视频。
|
||||||
|
完整的更新记录:https://github.com/vector-im/element-android/releases/tag/v1.1.7
|
|
@ -1,30 +1,39 @@
|
||||||
Element 是一种新型的通讯与协作应用:
|
Element 不仅是安全的通讯软件,同时也是生产力团队协作应用,非常适合在远端工作时进行群组聊天。此聊天应用使用了端到端加密来提供强大的视频会议、文件分享与语音通话功能。
|
||||||
|
|
||||||
1. 使您可以掌控您的隐私
|
<b>Element 的功能包含了:</b>
|
||||||
2. 使您与 Matrix 网络中的任何人交流,甚至可以通过集成功能与如 Slack 之类的其他应用通讯
|
- 进阶的线上通讯工具
|
||||||
3. 保护您免受广告,大数据挖掘和封闭服务的侵害
|
- 完全加密的信息,即使对于远端工作者来说,也可以有更安全的公司通讯
|
||||||
4. 通过端到端加密保证安全,通过交叉签名验证其他人
|
- 以 Matrix 开放源码框架为基础的去中心化的聊天
|
||||||
|
- 在管理项目时通过加密资料安全地分享文件
|
||||||
|
- 包含了 VoIP 与画面分享的视频聊天
|
||||||
|
- 与你最喜欢的协作工具、项目管理工具、VoIP 服务与其他团队信息应用轻松整合
|
||||||
|
|
||||||
Element 与其他通讯与协作应用完全不同,因为它是去中心化且开源的。
|
Element 与其他信息传递与协作应用完全不同。它在 Matrix(一个用于安全传递讯息与去中心化通讯的开放网络)上运行。其可以自建,让使用者对他们的资料和信息拥有最大的所有权与控制权。
|
||||||
|
|
||||||
Element 允许您自托管——或者选择托管商——因此,您能拥有数据和会话的隐私权,所有权和控制权。它允许您访问开放网络;因此,您可以与 Element 用户以外的人交流。并且它非常安全。
|
<b>隐私与加密信息传递</b>
|
||||||
|
Element 保护你不受不想要的广告、信息泄露与围城侵扰。其也通过端到端加密与交叉签章装置验证保护了你所有的资料,并提供一对一视频以及语音通讯。
|
||||||
|
|
||||||
Element 之所以可以做到这些,是因为它在 Matrix 上运行——开放,去中心化通讯的标准。
|
Element 通过与其他商业协作工具,如 Slack 等应用整合,让你可以在控制你的隐私的同时,也可以与 Matrix 网络上的任何人安全地通讯。
|
||||||
|
|
||||||
通过让您选择由谁来托管您的会话,Element 让您掌控一切。在 Element 应用中,您可以选择不同的托管方式:
|
<b>Element 可以自建</b>
|
||||||
|
为了可以完整控制你的敏感资料与对话,Element 可以自建,你也可以选择任何以 Matrix 为基础的服务提供商,开放源码、去中心化的通讯标准。Element 为你提供隐私、安全合规与整合灵活性。
|
||||||
|
|
||||||
1. 在由 Matrix 开发者托管的 matrix.org 公共服务器上获取免费帐户,或从志愿者托管的上千个公共服务器中选择
|
<b>拥有你的资料</b>
|
||||||
2. 在您自己的硬件上运行服务器,自托管您的会话
|
你可以决定将你的资料与信息储存在何处。没有信息泄露或被第三方爬取的风险。
|
||||||
3. 通过订阅 Element Matrix Services 托管平台,简单地在自定义服务器上注册账户
|
|
||||||
|
|
||||||
<b>为什么选择 Element?</b>
|
Element 透过不同的方式让你掌控一切:
|
||||||
|
1. 在 Matrix 开发者架设的 matrix.org 公开服务器上取得免费帐号,或是从数千个由志愿者架设的公开服务器中选择
|
||||||
|
2. 在你自己的 IT 基础架构上的服务器自行托管你的帐号
|
||||||
|
3. 只要订阅 Element Matrix Services 托管平台就可以在自定义的服务器上注册帐号
|
||||||
|
|
||||||
<b>掌控您的数据</b>:您来决定存放您的数据和消息的位置。拥有并控制它的是您,而不是挖掘您的数据或与第三方分享的巨型企业。
|
<b>开放信息传递与协作</b>
|
||||||
|
你可以与 Matrix 网络上的任何人聊天,不论他们是使用 Element、其他 Matrix 应用或其他通讯应用。
|
||||||
|
|
||||||
<b>开放通讯与协作</b>:您可以与 Matrix 网络中的任何人聊天,不论他们使用 Element 还是其他 Matrix 应用,甚至/即使他们在使用不同的通讯系统,例如 Slack,IRC 或 XMPP。
|
<b>超级安全</b>
|
||||||
|
真正的端到端加密(仅有那些在对话中的可以解密讯息)以及交叉签章装置验证。
|
||||||
|
|
||||||
<b>超级安全</b>:支持真正的端到端加密(仅有会话中的人可以解密消息),还有能够验证会话参与方的设备的交叉签名。
|
<b>完整的通讯与整合</b>
|
||||||
|
信息传递、语音与视频通话、文件分享、画面分享与超多的整合、机器人与挂件。建构聊天室、社群、保持联络并完成工作。
|
||||||
|
|
||||||
<b>完善的通讯方式</b>:消息,语音和视频通话,文件共享,屏幕共享和大量集成功能,机器人和小挂件。建立房间与社区,保持联系并完成工作。
|
<b>从上次离开的地方开始</b>
|
||||||
|
无论你身在何处,都可以透过在你所有设备与网页 https://app.element.io 间完全同步的信息历史保持联络
|
||||||
<b>随时随地</b>:消息历史可在您的全部设备和 https://app.element.io 网页端之间完全同步,无论您在哪里,都可以保持联系。
|
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
此版本中的主要變動:對「空間」的測試版支援。傳送前壓縮影片。
|
||||||
|
完整的變更紀錄:https://github.com/vector-im/element-android/releases/tag/v1.1.7
|
|
@ -24,7 +24,7 @@ import kotlinx.coroutines.rx2.rxSingle
|
||||||
import org.matrix.android.sdk.api.extensions.orFalse
|
import org.matrix.android.sdk.api.extensions.orFalse
|
||||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||||
import org.matrix.android.sdk.api.session.Session
|
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.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.MASTER_KEY_SSSS_NAME
|
||||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo
|
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.identity.ThreePid
|
||||||
import org.matrix.android.sdk.api.session.pushers.Pusher
|
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.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.members.ChangeMembershipState
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||||
|
@ -177,10 +178,17 @@ class RxSession(private val session: Session) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun liveUserAccountData(types: Set<String>): Observable<List<AccountDataEvent>> {
|
fun liveUserAccountData(types: Set<String>): Observable<List<UserAccountDataEvent>> {
|
||||||
return session.userAccountDataService().getLiveAccountDataEvents(types).asObservable()
|
return session.accountDataService().getLiveUserAccountDataEvents(types).asObservable()
|
||||||
.startWithCallable {
|
.startWithCallable {
|
||||||
session.userAccountDataService().getAccountDataEvents(types)
|
session.accountDataService().getUserAccountDataEvents(types)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun liveRoomAccountData(types: Set<String>): Observable<List<RoomAccountDataEvent>> {
|
||||||
|
return session.accountDataService().getLiveRoomAccountDataEvents(types).asObservable()
|
||||||
|
.startWithCallable {
|
||||||
|
session.accountDataService().getRoomAccountDataEvents(types)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,7 +209,7 @@ class RxSession(private val session: Session) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun liveSecretSynchronisationInfo(): Observable<SecretsSynchronisationInfo> {
|
fun liveSecretSynchronisationInfo(): Observable<SecretsSynchronisationInfo> {
|
||||||
return Observable.combineLatest<List<AccountDataEvent>, Optional<MXCrossSigningInfo>, Optional<PrivateKeysInfo>, SecretsSynchronisationInfo>(
|
return Observable.combineLatest<List<UserAccountDataEvent>, Optional<MXCrossSigningInfo>, Optional<PrivateKeysInfo>, SecretsSynchronisationInfo>(
|
||||||
liveUserAccountData(setOf(MASTER_KEY_SSSS_NAME, USER_SIGNING_KEY_SSSS_NAME, SELF_SIGNING_KEY_SSSS_NAME, KEYBACKUP_SECRET_SSSS_NAME)),
|
liveUserAccountData(setOf(MASTER_KEY_SSSS_NAME, USER_SIGNING_KEY_SSSS_NAME, SELF_SIGNING_KEY_SSSS_NAME, KEYBACKUP_SECRET_SSSS_NAME)),
|
||||||
liveCrossSigningInfo(session.myUserId),
|
liveCrossSigningInfo(session.myUserId),
|
||||||
liveCrossSigningPrivateKeys(),
|
liveCrossSigningPrivateKeys(),
|
||||||
|
|
|
@ -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.SSSS_ALGORITHM_AES_HMAC_SHA2
|
||||||
import org.matrix.android.sdk.internal.crypto.crosssigning.toBase64NoPadding
|
import org.matrix.android.sdk.internal.crypto.crosssigning.toBase64NoPadding
|
||||||
import org.matrix.android.sdk.internal.crypto.secrets.DefaultSharedSecretStorageService
|
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.Dispatchers
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
@ -73,12 +73,12 @@ class QuadSTests : InstrumentedTest {
|
||||||
|
|
||||||
// Assert Account data is updated
|
// Assert Account data is updated
|
||||||
val accountDataLock = CountDownLatch(1)
|
val accountDataLock = CountDownLatch(1)
|
||||||
var accountData: AccountDataEvent? = null
|
var accountData: UserAccountDataEvent? = null
|
||||||
|
|
||||||
val liveAccountData = runBlocking(Dispatchers.Main) {
|
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<Optional<AccountDataEvent>?> { t ->
|
val accountDataObserver = Observer<Optional<UserAccountDataEvent>?> { t ->
|
||||||
if (t?.getOrNull()?.type == "${DefaultSharedSecretStorageService.KEY_ID_BASE}.$TEST_KEY_ID") {
|
if (t?.getOrNull()?.type == "${DefaultSharedSecretStorageService.KEY_ID_BASE}.$TEST_KEY_ID") {
|
||||||
accountData = t.getOrNull()
|
accountData = t.getOrNull()
|
||||||
accountDataLock.countDown()
|
accountDataLock.countDown()
|
||||||
|
@ -100,13 +100,13 @@ class QuadSTests : InstrumentedTest {
|
||||||
quadS.setDefaultKey(TEST_KEY_ID)
|
quadS.setDefaultKey(TEST_KEY_ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
var defaultKeyAccountData: AccountDataEvent? = null
|
var defaultKeyAccountData: UserAccountDataEvent? = null
|
||||||
val defaultDataLock = CountDownLatch(1)
|
val defaultDataLock = CountDownLatch(1)
|
||||||
|
|
||||||
val liveDefAccountData = runBlocking(Dispatchers.Main) {
|
val liveDefAccountData = runBlocking(Dispatchers.Main) {
|
||||||
aliceSession.userAccountDataService().getLiveAccountDataEvent(DefaultSharedSecretStorageService.DEFAULT_KEY_ID)
|
aliceSession.accountDataService().getLiveUserAccountDataEvent(DefaultSharedSecretStorageService.DEFAULT_KEY_ID)
|
||||||
}
|
}
|
||||||
val accountDefDataObserver = Observer<Optional<AccountDataEvent>?> { t ->
|
val accountDefDataObserver = Observer<Optional<UserAccountDataEvent>?> { t ->
|
||||||
if (t?.getOrNull()?.type == DefaultSharedSecretStorageService.DEFAULT_KEY_ID) {
|
if (t?.getOrNull()?.type == DefaultSharedSecretStorageService.DEFAULT_KEY_ID) {
|
||||||
defaultKeyAccountData = t.getOrNull()!!
|
defaultKeyAccountData = t.getOrNull()!!
|
||||||
defaultDataLock.countDown()
|
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<*, *>
|
val encryptedContent = accountDataEvent?.content?.get("encrypted") as? Map<*, *>
|
||||||
|
|
||||||
assertEquals("Content should contains two encryptions", 2, encryptedContent?.keys?.size ?: 0)
|
assertEquals("Content should contains two encryptions", 2, encryptedContent?.keys?.size ?: 0)
|
||||||
|
@ -275,14 +275,14 @@ class QuadSTests : InstrumentedTest {
|
||||||
mTestHelper.signOutAndClose(aliceSession)
|
mTestHelper.signOutAndClose(aliceSession)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun assertAccountData(session: Session, type: String): AccountDataEvent {
|
private fun assertAccountData(session: Session, type: String): UserAccountDataEvent {
|
||||||
val accountDataLock = CountDownLatch(1)
|
val accountDataLock = CountDownLatch(1)
|
||||||
var accountData: AccountDataEvent? = null
|
var accountData: UserAccountDataEvent? = null
|
||||||
|
|
||||||
val liveAccountData = runBlocking(Dispatchers.Main) {
|
val liveAccountData = runBlocking(Dispatchers.Main) {
|
||||||
session.userAccountDataService().getLiveAccountDataEvent(type)
|
session.accountDataService().getLiveUserAccountDataEvent(type)
|
||||||
}
|
}
|
||||||
val accountDataObserver = Observer<Optional<AccountDataEvent>?> { t ->
|
val accountDataObserver = Observer<Optional<UserAccountDataEvent>?> { t ->
|
||||||
if (t?.getOrNull()?.type == type) {
|
if (t?.getOrNull()?.type == type) {
|
||||||
accountData = t.getOrNull()
|
accountData = t.getOrNull()
|
||||||
accountDataLock.countDown()
|
accountDataLock.countDown()
|
||||||
|
|
|
@ -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.federation.FederationService
|
||||||
import org.matrix.android.sdk.api.pushrules.PushRuleService
|
import org.matrix.android.sdk.api.pushrules.PushRuleService
|
||||||
import org.matrix.android.sdk.api.session.account.AccountService
|
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.cache.CacheService
|
||||||
import org.matrix.android.sdk.api.session.call.CallSignalingService
|
import org.matrix.android.sdk.api.session.call.CallSignalingService
|
||||||
import org.matrix.android.sdk.api.session.content.ContentUploadStateTracker
|
import org.matrix.android.sdk.api.session.content.ContentUploadStateTracker
|
||||||
|
@ -239,9 +239,9 @@ interface Session :
|
||||||
fun openIdService(): OpenIdService
|
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.
|
* Add a listener to the session.
|
||||||
|
|
|
@ -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<Optional<UserAccountDataEvent>>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<String>): List<UserAccountDataEvent>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Observe the account data with the provided types. If an empty set is provided, all the AccountData are observed
|
||||||
|
*/
|
||||||
|
fun getLiveUserAccountDataEvents(types: Set<String>): LiveData<List<UserAccountDataEvent>>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<String>): List<RoomAccountDataEvent>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<String>): LiveData<List<RoomAccountDataEvent>>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the account data with the provided type and the provided account data content
|
||||||
|
*/
|
||||||
|
suspend fun updateUserAccountData(type: String, content: Content)
|
||||||
|
}
|
|
@ -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.
|
* 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)
|
@JsonClass(generateAdapter = true)
|
||||||
data class AccountDataEvent(
|
data class UserAccountDataEvent(
|
||||||
@Json(name = "type") val type: String,
|
@Json(name = "type") val type: String,
|
||||||
@Json(name = "content") val content: Content
|
@Json(name = "content") val content: Content
|
||||||
)
|
)
|
|
@ -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.DeviceInfo
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.DevicesListResponse
|
import org.matrix.android.sdk.internal.crypto.model.rest.DevicesListResponse
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyRequestBody
|
import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyRequestBody
|
||||||
import kotlin.jvm.Throws
|
|
||||||
|
|
||||||
interface CryptoService {
|
interface CryptoService {
|
||||||
|
|
||||||
|
@ -82,9 +81,11 @@ interface CryptoService {
|
||||||
|
|
||||||
fun getDeviceTrackingStatus(userId: String): Int
|
fun getDeviceTrackingStatus(userId: String): Int
|
||||||
|
|
||||||
fun importRoomKeys(roomKeysAsArray: ByteArray, password: String, progressListener: ProgressListener?, callback: MatrixCallback<ImportRoomKeysResult>)
|
suspend fun importRoomKeys(roomKeysAsArray: ByteArray,
|
||||||
|
password: String,
|
||||||
|
progressListener: ProgressListener?): ImportRoomKeysResult
|
||||||
|
|
||||||
fun exportRoomKeys(password: String, callback: MatrixCallback<ByteArray>)
|
suspend fun exportRoomKeys(password: String): ByteArray
|
||||||
|
|
||||||
fun setRoomBlacklistUnverifiedDevices(roomId: String)
|
fun setRoomBlacklistUnverifiedDevices(roomId: String)
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ interface IdentityService {
|
||||||
/**
|
/**
|
||||||
* Check if the identity server is valid
|
* Check if the identity server is valid
|
||||||
* See https://matrix.org/docs/spec/identity_service/latest#status-check
|
* 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)
|
suspend fun isValidIdentityServer(url: String)
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
package org.matrix.android.sdk.api.session.room
|
package org.matrix.android.sdk.api.session.room
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
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.alias.AliasService
|
||||||
import org.matrix.android.sdk.api.session.room.call.RoomCallService
|
import org.matrix.android.sdk.api.session.room.call.RoomCallService
|
||||||
import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService
|
import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService
|
||||||
|
@ -57,7 +57,7 @@ interface Room :
|
||||||
RelationService,
|
RelationService,
|
||||||
RoomCryptoService,
|
RoomCryptoService,
|
||||||
RoomPushRuleService,
|
RoomPushRuleService,
|
||||||
AccountDataService {
|
RoomAccountDataService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The roomId of this room
|
* The roomId of this room
|
||||||
|
|
|
@ -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
|
||||||
|
)
|
|
@ -14,37 +14,37 @@
|
||||||
* limitations under the License.
|
* 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 androidx.lifecycle.LiveData
|
||||||
import org.matrix.android.sdk.api.session.events.model.Content
|
import org.matrix.android.sdk.api.session.events.model.Content
|
||||||
import org.matrix.android.sdk.api.util.Optional
|
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
|
* 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
|
* Observe the account data with the provided type
|
||||||
*/
|
*/
|
||||||
fun getLiveAccountDataEvent(type: String): LiveData<Optional<AccountDataEvent>>
|
fun getLiveAccountDataEvent(type: String): LiveData<Optional<RoomAccountDataEvent>>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the account data with the provided types. The return list can have a different size that
|
* 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.
|
* the size of the types set, because some AccountData may not exist.
|
||||||
* If an empty set is provided, all the AccountData are retrieved
|
* If an empty set is provided, all the AccountData are retrieved
|
||||||
*/
|
*/
|
||||||
fun getAccountDataEvents(types: Set<String>): List<AccountDataEvent>
|
fun getAccountDataEvents(types: Set<String>): List<RoomAccountDataEvent>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Observe the account data with the provided types. If an empty set is provided, all the AccountData are observed
|
* Observe the account data with the provided types. If an empty set is provided, all the AccountData are observed
|
||||||
*/
|
*/
|
||||||
fun getLiveAccountDataEvents(types: Set<String>): LiveData<List<AccountDataEvent>>
|
fun getLiveAccountDataEvents(types: Set<String>): LiveData<List<RoomAccountDataEvent>>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the account data with the provided type and the provided account data content
|
* Update the account data with the provided type and the provided account data content
|
|
@ -388,7 +388,7 @@ internal class DefaultCryptoService @Inject constructor(
|
||||||
cryptoStore.close()
|
cryptoStore.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Aways enabled on RiotX
|
// Always enabled on Matrix Android SDK2
|
||||||
override fun isCryptoEnabled() = true
|
override fun isCryptoEnabled() = true
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -928,14 +928,10 @@ internal class DefaultCryptoService @Inject constructor(
|
||||||
* Export the crypto keys
|
* Export the crypto keys
|
||||||
*
|
*
|
||||||
* @param password the password
|
* @param password the password
|
||||||
* @param callback the exported keys
|
* @return the exported keys
|
||||||
*/
|
*/
|
||||||
override fun exportRoomKeys(password: String, callback: MatrixCallback<ByteArray>) {
|
override suspend fun exportRoomKeys(password: String): ByteArray {
|
||||||
cryptoCoroutineScope.launch(coroutineDispatchers.main) {
|
return exportRoomKeys(password, MXMegolmExportEncryption.DEFAULT_ITERATION_COUNT)
|
||||||
runCatching {
|
|
||||||
exportRoomKeys(password, MXMegolmExportEncryption.DEFAULT_ITERATION_COUNT)
|
|
||||||
}.foldToCallback(callback)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -963,15 +959,12 @@ internal class DefaultCryptoService @Inject constructor(
|
||||||
* @param roomKeysAsArray the room keys as array.
|
* @param roomKeysAsArray the room keys as array.
|
||||||
* @param password the password
|
* @param password the password
|
||||||
* @param progressListener the progress listener
|
* @param progressListener the progress listener
|
||||||
* @param callback the asynchronous callback.
|
* @return the result ImportRoomKeysResult
|
||||||
*/
|
*/
|
||||||
override fun importRoomKeys(roomKeysAsArray: ByteArray,
|
override suspend fun importRoomKeys(roomKeysAsArray: ByteArray,
|
||||||
password: String,
|
password: String,
|
||||||
progressListener: ProgressListener?,
|
progressListener: ProgressListener?): ImportRoomKeysResult {
|
||||||
callback: MatrixCallback<ImportRoomKeysResult>) {
|
return withContext(coroutineDispatchers.crypto) {
|
||||||
cryptoCoroutineScope.launch(coroutineDispatchers.main) {
|
|
||||||
runCatching {
|
|
||||||
withContext(coroutineDispatchers.crypto) {
|
|
||||||
Timber.v("## CRYPTO | importRoomKeys starts")
|
Timber.v("## CRYPTO | importRoomKeys starts")
|
||||||
|
|
||||||
val t0 = System.currentTimeMillis()
|
val t0 = System.currentTimeMillis()
|
||||||
|
@ -998,8 +991,6 @@ internal class DefaultCryptoService @Inject constructor(
|
||||||
progressListener = progressListener
|
progressListener = progressListener
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}.foldToCallback(callback)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -155,7 +155,7 @@ internal class MXMegolmDecryption(private val userId: String,
|
||||||
withHeldInfo.code?.value ?: "",
|
withHeldInfo.code?.value ?: "",
|
||||||
withHeldInfo.reason)
|
withHeldInfo.reason)
|
||||||
} else {
|
} 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)
|
// addEventToPendingList(event, timeline)
|
||||||
if (requestKeysOnFail) {
|
if (requestKeysOnFail) {
|
||||||
requestKeysForEvent(event, false)
|
requestKeysForEvent(event, false)
|
||||||
|
|
|
@ -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.extensions.orFalse
|
||||||
import org.matrix.android.sdk.api.listeners.ProgressListener
|
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.events.model.toContent
|
||||||
import org.matrix.android.sdk.api.session.securestorage.EncryptedSecretContent
|
import org.matrix.android.sdk.api.session.securestorage.EncryptedSecretContent
|
||||||
import org.matrix.android.sdk.api.session.securestorage.IntegrityResult
|
import org.matrix.android.sdk.api.session.securestorage.IntegrityResult
|
||||||
|
@ -56,7 +56,7 @@ import kotlin.experimental.and
|
||||||
|
|
||||||
internal class DefaultSharedSecretStorageService @Inject constructor(
|
internal class DefaultSharedSecretStorageService @Inject constructor(
|
||||||
@UserId private val userId: String,
|
@UserId private val userId: String,
|
||||||
private val accountDataService: AccountDataService,
|
private val accountDataService: SessionAccountDataService,
|
||||||
private val outgoingGossipingRequestManager: OutgoingGossipingRequestManager,
|
private val outgoingGossipingRequestManager: OutgoingGossipingRequestManager,
|
||||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||||
private val cryptoCoroutineScope: CoroutineScope
|
private val cryptoCoroutineScope: CoroutineScope
|
||||||
|
@ -84,7 +84,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
|
||||||
)
|
)
|
||||||
} ?: storageKeyContent
|
} ?: storageKeyContent
|
||||||
|
|
||||||
accountDataService.updateAccountData("$KEY_ID_BASE.$keyId", signedContent.toContent())
|
accountDataService.updateUserAccountData("$KEY_ID_BASE.$keyId", signedContent.toContent())
|
||||||
SsssKeyCreationInfo(
|
SsssKeyCreationInfo(
|
||||||
keyId = keyId,
|
keyId = keyId,
|
||||||
content = storageKeyContent,
|
content = storageKeyContent,
|
||||||
|
@ -113,7 +113,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
|
||||||
)
|
)
|
||||||
} ?: storageKeyContent
|
} ?: storageKeyContent
|
||||||
|
|
||||||
accountDataService.updateAccountData(
|
accountDataService.updateUserAccountData(
|
||||||
"$KEY_ID_BASE.$keyId",
|
"$KEY_ID_BASE.$keyId",
|
||||||
signedContent.toContent()
|
signedContent.toContent()
|
||||||
)
|
)
|
||||||
|
@ -127,11 +127,11 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hasKey(keyId: String): Boolean {
|
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 {
|
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 KeyInfoResult.Error(SharedSecretStorageError.UnknownKey(keyId))
|
||||||
return SecretStorageKeyContent.fromJson(accountData.content)?.let {
|
return SecretStorageKeyContent.fromJson(accountData.content)?.let {
|
||||||
KeyInfoResult.Success(
|
KeyInfoResult.Success(
|
||||||
|
@ -143,14 +143,14 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
|
||||||
override suspend fun setDefaultKey(keyId: String) {
|
override suspend fun setDefaultKey(keyId: String) {
|
||||||
val existingKey = getKey(keyId)
|
val existingKey = getKey(keyId)
|
||||||
if (existingKey is KeyInfoResult.Success) {
|
if (existingKey is KeyInfoResult.Success) {
|
||||||
accountDataService.updateAccountData(DEFAULT_KEY_ID, mapOf("key" to keyId))
|
accountDataService.updateUserAccountData(DEFAULT_KEY_ID, mapOf("key" to keyId))
|
||||||
} else {
|
} else {
|
||||||
throw SharedSecretStorageError.UnknownKey(keyId)
|
throw SharedSecretStorageError.UnknownKey(keyId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getDefaultKey(): KeyInfoResult {
|
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))
|
?: return KeyInfoResult.Error(SharedSecretStorageError.UnknownKey(DEFAULT_KEY_ID))
|
||||||
val keyId = accountData.content["key"] as? String
|
val keyId = accountData.content["key"] as? String
|
||||||
?: return KeyInfoResult.Error(SharedSecretStorageError.UnknownKey(DEFAULT_KEY_ID))
|
?: return KeyInfoResult.Error(SharedSecretStorageError.UnknownKey(DEFAULT_KEY_ID))
|
||||||
|
@ -178,7 +178,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
accountDataService.updateAccountData(
|
accountDataService.updateUserAccountData(
|
||||||
type = name,
|
type = name,
|
||||||
content = mapOf("encrypted" to encryptedContents)
|
content = mapOf("encrypted" to encryptedContents)
|
||||||
)
|
)
|
||||||
|
@ -288,7 +288,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getAlgorithmsForSecret(name: String): List<KeyInfoResult> {
|
override fun getAlgorithmsForSecret(name: String): List<KeyInfoResult> {
|
||||||
val accountData = accountDataService.getAccountDataEvent(name)
|
val accountData = accountDataService.getUserAccountDataEvent(name)
|
||||||
?: return listOf(KeyInfoResult.Error(SharedSecretStorageError.UnknownSecret(name)))
|
?: return listOf(KeyInfoResult.Error(SharedSecretStorageError.UnknownSecret(name)))
|
||||||
val encryptedContent = accountData.content[ENCRYPTED] as? Map<*, *>
|
val encryptedContent = accountData.content[ENCRYPTED] as? Map<*, *>
|
||||||
?: return listOf(KeyInfoResult.Error(SharedSecretStorageError.SecretNotEncrypted(name)))
|
?: 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 {
|
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 encryptedContent = accountData.content[ENCRYPTED] as? Map<*, *> ?: throw SharedSecretStorageError.SecretNotEncrypted(name)
|
||||||
val key = keyId?.let { getKey(it) } as? KeyInfoResult.Success ?: getDefaultKey() as? KeyInfoResult.Success
|
val key = keyId?.let { getKey(it) } as? KeyInfoResult.Success ?: getDefaultKey() as? KeyInfoResult.Success
|
||||||
?: throw SharedSecretStorageError.UnknownKey(name)
|
?: throw SharedSecretStorageError.UnknownKey(name)
|
||||||
|
@ -368,7 +368,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
secretNames.forEach { secretName ->
|
secretNames.forEach { secretName ->
|
||||||
val secretEvent = accountDataService.getAccountDataEvent(secretName)
|
val secretEvent = accountDataService.getUserAccountDataEvent(secretName)
|
||||||
?: return IntegrityResult.Error(SharedSecretStorageError.UnknownSecret(secretName))
|
?: return IntegrityResult.Error(SharedSecretStorageError.UnknownSecret(secretName))
|
||||||
if ((secretEvent.content["encrypted"] as? Map<*, *>)?.get(keyInfo.id) == null) {
|
if ((secretEvent.content["encrypted"] as? Map<*, *>)?.get(keyInfo.id) == null) {
|
||||||
return IntegrityResult.Error(SharedSecretStorageError.SecretNotEncryptedWithKey(secretName, keyInfo.id))
|
return IntegrityResult.Error(SharedSecretStorageError.SecretNotEncryptedWithKey(secretName, keyInfo.id))
|
||||||
|
|
|
@ -17,7 +17,8 @@
|
||||||
package org.matrix.android.sdk.internal.database.mapper
|
package org.matrix.android.sdk.internal.database.mapper
|
||||||
|
|
||||||
import com.squareup.moshi.Moshi
|
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.api.util.JSON_DICT_PARAMETERIZED_TYPE
|
||||||
import org.matrix.android.sdk.internal.database.model.RoomAccountDataEntity
|
import org.matrix.android.sdk.internal.database.model.RoomAccountDataEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.UserAccountDataEntity
|
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<Map<String, Any>>(JSON_DICT_PARAMETERIZED_TYPE)
|
private val adapter = moshi.adapter<Map<String, Any>>(JSON_DICT_PARAMETERIZED_TYPE)
|
||||||
|
|
||||||
fun map(entity: UserAccountDataEntity): AccountDataEvent {
|
fun map(entity: UserAccountDataEntity): UserAccountDataEvent {
|
||||||
return AccountDataEvent(
|
return UserAccountDataEvent(
|
||||||
type = entity.type ?: "",
|
type = entity.type ?: "",
|
||||||
content = entity.contentStr?.let { adapter.fromJson(it) }.orEmpty()
|
content = entity.contentStr?.let { adapter.fromJson(it) }.orEmpty()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun map(entity: RoomAccountDataEntity): AccountDataEvent {
|
fun map(roomId: String, entity: RoomAccountDataEntity): RoomAccountDataEvent {
|
||||||
return AccountDataEvent(
|
return RoomAccountDataEvent(
|
||||||
|
roomId = roomId,
|
||||||
type = entity.type ?: "",
|
type = entity.type ?: "",
|
||||||
content = entity.contentStr?.let { adapter.fromJson(it) }.orEmpty()
|
content = entity.contentStr?.let { adapter.fromJson(it) }.orEmpty()
|
||||||
)
|
)
|
||||||
|
|
|
@ -153,7 +153,7 @@ internal class DefaultLegacySessionImporter @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun importCryptoDb(legacyConfig: LegacyHomeServerConnectionConfig) {
|
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 userMd5 = legacyConfig.credentials.userId.md5()
|
||||||
|
|
||||||
val sessionId = legacyConfig.credentials.let { (if (it.deviceId.isNullOrBlank()) it.userId else "${it.userId}|${it.deviceId}").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")
|
Timber.d("Migration: copy DB to encrypted DB")
|
||||||
Realm.getInstance(realmConfiguration).use {
|
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))
|
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) {
|
private fun clearFileSystem(legacyConfig: LegacyHomeServerConnectionConfig) {
|
||||||
val cryptoFolder = legacyConfig.credentials.userId.md5()
|
val cryptoFolder = legacyConfig.credentials.userId.md5()
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ internal class UserAgentHolder @Inject constructor(private val context: Context,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an user agent with the application version.
|
* 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
|
* @param flavorDescription the flavor description
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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.Session
|
||||||
import org.matrix.android.sdk.api.session.SessionLifecycleObserver
|
import org.matrix.android.sdk.api.session.SessionLifecycleObserver
|
||||||
import org.matrix.android.sdk.api.session.account.AccountService
|
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.cache.CacheService
|
||||||
import org.matrix.android.sdk.api.session.call.CallSignalingService
|
import org.matrix.android.sdk.api.session.call.CallSignalingService
|
||||||
import org.matrix.android.sdk.api.session.content.ContentUploadStateTracker
|
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.SyncTokenStore
|
||||||
import org.matrix.android.sdk.internal.session.sync.job.SyncThread
|
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.sync.job.SyncWorker
|
||||||
import org.matrix.android.sdk.internal.session.user.accountdata.UserAccountDataService
|
|
||||||
import org.matrix.android.sdk.internal.util.createUIHandler
|
import org.matrix.android.sdk.internal.util.createUIHandler
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -118,7 +117,7 @@ internal class DefaultSession @Inject constructor(
|
||||||
private val contentDownloadStateTracker: ContentDownloadStateTracker,
|
private val contentDownloadStateTracker: ContentDownloadStateTracker,
|
||||||
private val initialSyncProgressService: Lazy<InitialSyncProgressService>,
|
private val initialSyncProgressService: Lazy<InitialSyncProgressService>,
|
||||||
private val homeServerCapabilitiesService: Lazy<HomeServerCapabilitiesService>,
|
private val homeServerCapabilitiesService: Lazy<HomeServerCapabilitiesService>,
|
||||||
private val accountDataService: Lazy<UserAccountDataService>,
|
private val accountDataService: Lazy<SessionAccountDataService>,
|
||||||
private val _sharedSecretStorageService: Lazy<SharedSecretStorageService>,
|
private val _sharedSecretStorageService: Lazy<SharedSecretStorageService>,
|
||||||
private val accountService: Lazy<AccountService>,
|
private val accountService: Lazy<AccountService>,
|
||||||
private val eventService: Lazy<EventService>,
|
private val eventService: Lazy<EventService>,
|
||||||
|
@ -293,7 +292,7 @@ internal class DefaultSession @Inject constructor(
|
||||||
|
|
||||||
override fun openIdService(): OpenIdService = openIdService.get()
|
override fun openIdService(): OpenIdService = openIdService.get()
|
||||||
|
|
||||||
override fun userAccountDataService(): AccountDataService = accountDataService.get()
|
override fun accountDataService(): SessionAccountDataService = accountDataService.get()
|
||||||
|
|
||||||
override fun getOkHttpClient(): OkHttpClient {
|
override fun getOkHttpClient(): OkHttpClient {
|
||||||
return unauthenticatedWithCertificateOkHttpClient.get()
|
return unauthenticatedWithCertificateOkHttpClient.get()
|
||||||
|
|
|
@ -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.crypto.MXCryptoConfig
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.api.session.SessionLifecycleObserver
|
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.events.EventService
|
||||||
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilitiesService
|
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilitiesService
|
||||||
import org.matrix.android.sdk.api.session.initsync.InitialSyncProgressService
|
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.room.tombstone.RoomTombstoneEventProcessor
|
||||||
import org.matrix.android.sdk.internal.session.securestorage.DefaultSecureStorageService
|
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.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.session.widgets.DefaultWidgetURLFormatter
|
||||||
import org.matrix.android.sdk.internal.util.md5
|
import org.matrix.android.sdk.internal.util.md5
|
||||||
import retrofit2.Retrofit
|
import retrofit2.Retrofit
|
||||||
|
@ -364,7 +364,7 @@ internal abstract class SessionModule {
|
||||||
abstract fun bindHomeServerCapabilitiesService(service: DefaultHomeServerCapabilitiesService): HomeServerCapabilitiesService
|
abstract fun bindHomeServerCapabilitiesService(service: DefaultHomeServerCapabilitiesService): HomeServerCapabilitiesService
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun bindAccountDataService(service: UserAccountDataService): AccountDataService
|
abstract fun bindSessionAccountDataService(service: DefaultSessionAccountDataService): SessionAccountDataService
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun bindEventService(service: DefaultEventService): EventService
|
abstract fun bindEventService(service: DefaultEventService): EventService
|
||||||
|
|
|
@ -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.api.session.SessionLifecycleObserver
|
||||||
import org.matrix.android.sdk.internal.session.SessionScope
|
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.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.UserAccountDataDataSource
|
||||||
import org.matrix.android.sdk.internal.session.user.accountdata.UpdateUserAccountDataTask
|
import org.matrix.android.sdk.internal.session.user.accountdata.UpdateUserAccountDataTask
|
||||||
import org.matrix.android.sdk.internal.session.widgets.helper.WidgetFactory
|
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)
|
return extractWidgetSequence(widgetFactory)
|
||||||
.filter {
|
.filter {
|
||||||
WidgetType.IntegrationManager == it.type
|
WidgetType.IntegrationManager == it.type
|
||||||
|
|
|
@ -17,10 +17,10 @@
|
||||||
package org.matrix.android.sdk.internal.session.room
|
package org.matrix.android.sdk.internal.session.room
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
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.crypto.CryptoService
|
||||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
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.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.alias.AliasService
|
||||||
import org.matrix.android.sdk.api.session.room.call.RoomCallService
|
import org.matrix.android.sdk.api.session.room.call.RoomCallService
|
||||||
import org.matrix.android.sdk.api.session.room.members.MembershipService
|
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.api.util.Optional
|
||||||
import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
|
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.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.state.SendStateTask
|
||||||
import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource
|
import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource
|
||||||
import org.matrix.android.sdk.internal.session.search.SearchTask
|
import org.matrix.android.sdk.internal.session.search.SearchTask
|
||||||
|
@ -86,7 +85,7 @@ internal class DefaultRoom(override val roomId: String,
|
||||||
RelationService by relationService,
|
RelationService by relationService,
|
||||||
MembershipService by roomMembersService,
|
MembershipService by roomMembersService,
|
||||||
RoomPushRuleService by roomPushRuleService,
|
RoomPushRuleService by roomPushRuleService,
|
||||||
AccountDataService by roomAccountDataService {
|
RoomAccountDataService by roomAccountDataService {
|
||||||
|
|
||||||
override fun getRoomSummaryLive(): LiveData<Optional<RoomSummary>> {
|
override fun getRoomSummaryLive(): LiveData<Optional<RoomSummary>> {
|
||||||
return roomSummaryDataSource.getRoomSummaryLive(roomId)
|
return roomSummaryDataSource.getRoomSummaryLive(roomId)
|
||||||
|
|
|
@ -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.crypto.CryptoService
|
||||||
import org.matrix.android.sdk.api.session.room.Room
|
import org.matrix.android.sdk.api.session.room.Room
|
||||||
import org.matrix.android.sdk.internal.session.SessionScope
|
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.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.alias.DefaultAliasService
|
||||||
import org.matrix.android.sdk.internal.session.room.call.DefaultRoomCallService
|
import org.matrix.android.sdk.internal.session.room.call.DefaultRoomCallService
|
||||||
import org.matrix.android.sdk.internal.session.room.draft.DefaultDraftService
|
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 relationServiceFactory: DefaultRelationService.Factory,
|
||||||
private val membershipServiceFactory: DefaultMembershipService.Factory,
|
private val membershipServiceFactory: DefaultMembershipService.Factory,
|
||||||
private val roomPushRuleServiceFactory: DefaultRoomPushRuleService.Factory,
|
private val roomPushRuleServiceFactory: DefaultRoomPushRuleService.Factory,
|
||||||
private val roomAccountDataServiceFactory: RoomAccountDataService.Factory,
|
private val roomAccountDataServiceFactory: DefaultRoomAccountDataService.Factory,
|
||||||
private val sendStateTask: SendStateTask,
|
private val sendStateTask: SendStateTask,
|
||||||
private val viaParameterFinder: ViaParameterFinder,
|
private val viaParameterFinder: ViaParameterFinder,
|
||||||
private val searchTask: SearchTask) :
|
private val searchTask: SearchTask) :
|
||||||
|
|
|
@ -20,34 +20,34 @@ import androidx.lifecycle.LiveData
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
import dagger.assisted.AssistedInject
|
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.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
|
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 dataSource: RoomAccountDataDataSource,
|
||||||
private val updateRoomAccountDataTask: UpdateRoomAccountDataTask
|
private val updateRoomAccountDataTask: UpdateRoomAccountDataTask
|
||||||
) : AccountDataService {
|
) : RoomAccountDataService {
|
||||||
|
|
||||||
@AssistedFactory
|
@AssistedFactory
|
||||||
interface Factory {
|
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)
|
return dataSource.getAccountDataEvent(roomId, type)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getLiveAccountDataEvent(type: String): LiveData<Optional<AccountDataEvent>> {
|
override fun getLiveAccountDataEvent(type: String): LiveData<Optional<RoomAccountDataEvent>> {
|
||||||
return dataSource.getLiveAccountDataEvent(roomId, type)
|
return dataSource.getLiveAccountDataEvent(roomId, type)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getAccountDataEvents(types: Set<String>): List<AccountDataEvent> {
|
override fun getAccountDataEvents(types: Set<String>): List<RoomAccountDataEvent> {
|
||||||
return dataSource.getAccountDataEvents(roomId, types)
|
return dataSource.getAccountDataEvents(roomId, types)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getLiveAccountDataEvents(types: Set<String>): LiveData<List<AccountDataEvent>> {
|
override fun getLiveAccountDataEvents(types: Set<String>): LiveData<List<RoomAccountDataEvent>> {
|
||||||
return dataSource.getLiveAccountDataEvents(roomId, types)
|
return dataSource.getLiveAccountDataEvents(roomId, types)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,14 +20,16 @@ import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MediatorLiveData
|
import androidx.lifecycle.MediatorLiveData
|
||||||
import androidx.lifecycle.Transformations
|
import androidx.lifecycle.Transformations
|
||||||
import com.zhuinden.monarchy.Monarchy
|
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.Optional
|
||||||
import org.matrix.android.sdk.api.util.toOptional
|
import org.matrix.android.sdk.api.util.toOptional
|
||||||
import org.matrix.android.sdk.internal.database.RealmSessionProvider
|
import org.matrix.android.sdk.internal.database.RealmSessionProvider
|
||||||
import org.matrix.android.sdk.internal.database.mapper.AccountDataMapper
|
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.RoomAccountDataEntityFields
|
||||||
import org.matrix.android.sdk.internal.database.model.RoomEntity
|
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 org.matrix.android.sdk.internal.di.SessionDatabase
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -35,43 +37,62 @@ internal class RoomAccountDataDataSource @Inject constructor(@SessionDatabase pr
|
||||||
private val realmSessionProvider: RealmSessionProvider,
|
private val realmSessionProvider: RealmSessionProvider,
|
||||||
private val accountDataMapper: AccountDataMapper) {
|
private val accountDataMapper: AccountDataMapper) {
|
||||||
|
|
||||||
fun getAccountDataEvent(roomId: String, type: String): AccountDataEvent? {
|
fun getAccountDataEvent(roomId: String, type: String): RoomAccountDataEvent? {
|
||||||
return getAccountDataEvents(roomId, setOf(type)).firstOrNull()
|
return getAccountDataEvents(roomId, setOf(type)).firstOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getLiveAccountDataEvent(roomId: String, type: String): LiveData<Optional<AccountDataEvent>> {
|
fun getLiveAccountDataEvent(roomId: String, type: String): LiveData<Optional<RoomAccountDataEvent>> {
|
||||||
return Transformations.map(getLiveAccountDataEvents(roomId, setOf(type))) {
|
return Transformations.map(getLiveAccountDataEvents(roomId, setOf(type))) {
|
||||||
it.firstOrNull()?.toOptional()
|
it.firstOrNull()?.toOptional()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAccountDataEvents(roomId: String, types: Set<String>): List<AccountDataEvent> {
|
/**
|
||||||
|
* @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<String>): List<RoomAccountDataEvent> {
|
||||||
return realmSessionProvider.withRealm { realm ->
|
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)
|
roomEntity.accountDataEvents(types)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getLiveAccountDataEvents(roomId: String, types: Set<String>): LiveData<List<AccountDataEvent>> {
|
/**
|
||||||
val liveRoomEntity = monarchy.findAllManagedWithChanges { RoomEntity.where(it, roomId) }
|
* @param roomId the roomId to search for account data event. If null will check in every room.
|
||||||
val resultLiveData = MediatorLiveData<List<AccountDataEvent>>()
|
* @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).
|
||||||
resultLiveData.addSource(liveRoomEntity) {
|
*
|
||||||
val roomEntity = it.realmResults.firstOrNull()
|
*/
|
||||||
if (roomEntity == null) {
|
fun getLiveAccountDataEvents(roomId: String?, types: Set<String>): LiveData<List<RoomAccountDataEvent>> {
|
||||||
resultLiveData.postValue(emptyList())
|
val liveRoomEntity = monarchy.findAllManagedWithChanges {
|
||||||
} else {
|
buildRoomQuery(it, roomId, types)
|
||||||
val mappedResult = roomEntity.accountDataEvents(types)
|
|
||||||
resultLiveData.postValue(mappedResult)
|
|
||||||
}
|
}
|
||||||
|
val resultLiveData = MediatorLiveData<List<RoomAccountDataEvent>>()
|
||||||
|
resultLiveData.addSource(liveRoomEntity) { changeSet ->
|
||||||
|
val mappedResult = changeSet.realmResults.flatMap { it.accountDataEvents(types) }
|
||||||
|
resultLiveData.postValue(mappedResult)
|
||||||
}
|
}
|
||||||
return resultLiveData
|
return resultLiveData
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun RoomEntity.accountDataEvents(types: Set<String>): List<AccountDataEvent> {
|
private fun buildRoomQuery(realm: Realm, roomId: String?, types: Set<String>): RealmQuery<RoomEntity> {
|
||||||
|
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<String>): List<RoomAccountDataEvent> {
|
||||||
val query = accountData.where()
|
val query = accountData.where()
|
||||||
if (types.isNotEmpty()) {
|
if (types.isNotEmpty()) {
|
||||||
query.`in`(RoomAccountDataEntityFields.TYPE, types.toTypedArray())
|
query.`in`(RoomAccountDataEntityFields.TYPE, types.toTypedArray())
|
||||||
}
|
}
|
||||||
return query.findAll().map { accountDataMapper.map(it) }
|
return query.findAll().map { accountDataMapper.map(roomId, it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ import io.realm.RealmQuery
|
||||||
import io.realm.RealmResults
|
import io.realm.RealmResults
|
||||||
import io.realm.Sort
|
import io.realm.Sort
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
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.orFalse
|
||||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||||
|
@ -168,9 +167,7 @@ internal class DefaultTimeline(
|
||||||
timelineEvents.addChangeListener(eventsChangeListener)
|
timelineEvents.addChangeListener(eventsChangeListener)
|
||||||
handleInitialLoad()
|
handleInitialLoad()
|
||||||
loadRoomMembersTask
|
loadRoomMembersTask
|
||||||
.configureWith(LoadRoomMembersTask.Params(roomId)) {
|
.configureWith(LoadRoomMembersTask.Params(roomId))
|
||||||
this.callback = NoOpMatrixCallback()
|
|
||||||
}
|
|
||||||
.executeBy(taskExecutor)
|
.executeBy(taskExecutor)
|
||||||
|
|
||||||
// Ensure ReadReceipt from init sync are loaded
|
// Ensure ReadReceipt from init sync are loaded
|
||||||
|
|
|
@ -18,13 +18,13 @@ package org.matrix.android.sdk.internal.session.room.typing
|
||||||
|
|
||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedInject
|
|
||||||
import dagger.assisted.AssistedFactory
|
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.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
|
import timber.log.Timber
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,7 +35,6 @@ import timber.log.Timber
|
||||||
*/
|
*/
|
||||||
internal class DefaultTypingService @AssistedInject constructor(
|
internal class DefaultTypingService @AssistedInject constructor(
|
||||||
@Assisted private val roomId: String,
|
@Assisted private val roomId: String,
|
||||||
private val taskExecutor: TaskExecutor,
|
|
||||||
private val sendTypingTask: SendTypingTask
|
private val sendTypingTask: SendTypingTask
|
||||||
) : TypingService {
|
) : TypingService {
|
||||||
|
|
||||||
|
@ -44,8 +43,8 @@ internal class DefaultTypingService @AssistedInject constructor(
|
||||||
fun create(roomId: String): DefaultTypingService
|
fun create(roomId: String): DefaultTypingService
|
||||||
}
|
}
|
||||||
|
|
||||||
private var currentTask: Cancelable? = null
|
private val coroutineScope = CoroutineScope(Job())
|
||||||
private var currentAutoStopTask: Cancelable? = null
|
private var currentTask: Job? = null
|
||||||
|
|
||||||
// What the homeserver knows
|
// What the homeserver knows
|
||||||
private var userIsTyping = false
|
private var userIsTyping = false
|
||||||
|
@ -53,26 +52,24 @@ internal class DefaultTypingService @AssistedInject constructor(
|
||||||
// Last time the user is typing event has been sent
|
// Last time the user is typing event has been sent
|
||||||
private var lastRequestTimestamp: Long = 0
|
private var lastRequestTimestamp: Long = 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify to the server that the user is typing and schedule the auto typing off
|
||||||
|
*/
|
||||||
override fun userIsTyping() {
|
override fun userIsTyping() {
|
||||||
scheduleAutoStop()
|
|
||||||
|
|
||||||
val now = SystemClock.elapsedRealtime()
|
val now = SystemClock.elapsedRealtime()
|
||||||
|
currentTask?.cancel()
|
||||||
|
currentTask = coroutineScope.launch {
|
||||||
if (userIsTyping && now < lastRequestTimestamp + MIN_DELAY_BETWEEN_TWO_USER_IS_TYPING_REQUESTS_MILLIS) {
|
if (userIsTyping && now < lastRequestTimestamp + MIN_DELAY_BETWEEN_TWO_USER_IS_TYPING_REQUESTS_MILLIS) {
|
||||||
Timber.d("Typing: Skip start request")
|
Timber.d("Typing: Skip start request")
|
||||||
return
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
Timber.d("Typing: Send start request")
|
Timber.d("Typing: Send start request")
|
||||||
userIsTyping = true
|
|
||||||
lastRequestTimestamp = now
|
lastRequestTimestamp = now
|
||||||
|
sendRequest(true)
|
||||||
currentTask?.cancel()
|
}
|
||||||
|
delay(MIN_DELAY_TO_SEND_STOP_TYPING_REQUEST_WHEN_NO_USER_ACTIVITY_MILLIS)
|
||||||
val params = SendTypingTask.Params(roomId, true)
|
Timber.d("Typing: auto stop")
|
||||||
currentTask = sendTypingTask
|
sendRequest(false)
|
||||||
.configureWith(params)
|
}
|
||||||
.executeBy(taskExecutor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun userStopsTyping() {
|
override fun userStopsTyping() {
|
||||||
|
@ -82,36 +79,23 @@ internal class DefaultTypingService @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
Timber.d("Typing: Send stop request")
|
Timber.d("Typing: Send stop request")
|
||||||
userIsTyping = false
|
|
||||||
lastRequestTimestamp = 0
|
lastRequestTimestamp = 0
|
||||||
|
|
||||||
currentAutoStopTask?.cancel()
|
|
||||||
currentTask?.cancel()
|
currentTask?.cancel()
|
||||||
|
currentTask = coroutineScope.launch {
|
||||||
val params = SendTypingTask.Params(roomId, false)
|
sendRequest(false)
|
||||||
currentTask = sendTypingTask
|
}
|
||||||
.configureWith(params)
|
|
||||||
.executeBy(taskExecutor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun scheduleAutoStop() {
|
private suspend fun sendRequest(isTyping: Boolean) {
|
||||||
Timber.d("Typing: Schedule auto stop")
|
try {
|
||||||
currentAutoStopTask?.cancel()
|
sendTypingTask.execute(SendTypingTask.Params(roomId, isTyping))
|
||||||
|
userIsTyping = isTyping
|
||||||
val params = SendTypingTask.Params(
|
} catch (failure: Throwable) {
|
||||||
roomId,
|
// Ignore network error, etc...
|
||||||
false,
|
Timber.w(failure, "Unable to send typing request")
|
||||||
delay = MIN_DELAY_TO_SEND_STOP_TYPING_REQUEST_WHEN_NO_USER_ACTIVITY_MILLIS)
|
|
||||||
currentAutoStopTask = sendTypingTask
|
|
||||||
.configureWith(params) {
|
|
||||||
callback = object : MatrixCallback<Unit> {
|
|
||||||
override fun onSuccess(data: Unit) {
|
|
||||||
userIsTyping = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
.executeBy(taskExecutor)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val MIN_DELAY_BETWEEN_TWO_USER_IS_TYPING_REQUESTS_MILLIS = 10_000L
|
private const val MIN_DELAY_BETWEEN_TWO_USER_IS_TYPING_REQUESTS_MILLIS = 10_000L
|
||||||
|
|
|
@ -17,11 +17,10 @@
|
||||||
package org.matrix.android.sdk.internal.session.room.typing
|
package org.matrix.android.sdk.internal.session.room.typing
|
||||||
|
|
||||||
import org.matrix.android.sdk.internal.di.UserId
|
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.network.executeRequest
|
||||||
import org.matrix.android.sdk.internal.session.room.RoomAPI
|
import org.matrix.android.sdk.internal.session.room.RoomAPI
|
||||||
import org.matrix.android.sdk.internal.task.Task
|
import org.matrix.android.sdk.internal.task.Task
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal interface SendTypingTask : Task<SendTypingTask.Params, Unit> {
|
internal interface SendTypingTask : Task<SendTypingTask.Params, Unit> {
|
||||||
|
@ -29,9 +28,7 @@ internal interface SendTypingTask : Task<SendTypingTask.Params, Unit> {
|
||||||
data class Params(
|
data class Params(
|
||||||
val roomId: String,
|
val roomId: String,
|
||||||
val isTyping: Boolean,
|
val isTyping: Boolean,
|
||||||
val typingTimeoutMillis: Int? = 30_000,
|
val typingTimeoutMillis: Int? = 30_000
|
||||||
// Optional delay before sending the request to the homeserver
|
|
||||||
val delay: Long? = null
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,8 +39,6 @@ internal class DefaultSendTypingTask @Inject constructor(
|
||||||
) : SendTypingTask {
|
) : SendTypingTask {
|
||||||
|
|
||||||
override suspend fun execute(params: SendTypingTask.Params) {
|
override suspend fun execute(params: SendTypingTask.Params) {
|
||||||
delay(params.delay ?: -1)
|
|
||||||
|
|
||||||
executeRequest(globalErrorReceiver) {
|
executeRequest(globalErrorReceiver) {
|
||||||
roomAPI.sendTypingState(
|
roomAPI.sendTypingState(
|
||||||
params.roomId,
|
params.roomId,
|
||||||
|
|
|
@ -23,7 +23,7 @@ import io.realm.kotlin.where
|
||||||
import org.matrix.android.sdk.api.pushrules.RuleScope
|
import org.matrix.android.sdk.api.pushrules.RuleScope
|
||||||
import org.matrix.android.sdk.api.pushrules.RuleSetKey
|
import org.matrix.android.sdk.api.pushrules.RuleSetKey
|
||||||
import org.matrix.android.sdk.api.pushrules.rest.GetPushRulesResponse
|
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.accountdata.UserAccountDataTypes
|
||||||
import org.matrix.android.sdk.api.session.events.model.Content
|
import org.matrix.android.sdk.api.session.events.model.Content
|
||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
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<GetPushRulesResponse>() ?: return
|
val pushRules = event.content.toModel<GetPushRulesResponse>() ?: return
|
||||||
realm.where(PushRulesEntity::class.java)
|
realm.where(PushRulesEntity::class.java)
|
||||||
.findAll()
|
.findAll()
|
||||||
|
@ -155,7 +155,7 @@ internal class UserAccountDataSyncHandler @Inject constructor(
|
||||||
realm.insertOrUpdate(underrides)
|
realm.insertOrUpdate(underrides)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleDirectChatRooms(realm: Realm, event: AccountDataEvent) {
|
private fun handleDirectChatRooms(realm: Realm, event: UserAccountDataEvent) {
|
||||||
val content = event.content.toModel<DirectMessagesContent>() ?: return
|
val content = event.content.toModel<DirectMessagesContent>() ?: return
|
||||||
content.forEach { (userId, roomIds) ->
|
content.forEach { (userId, roomIds) ->
|
||||||
roomIds.forEach { roomId ->
|
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<IgnoredUsersContent>()?.ignoredUsers?.keys ?: return
|
val userIds = event.content.toModel<IgnoredUsersContent>()?.ignoredUsers?.keys ?: return
|
||||||
realm.where(IgnoredUserEntity::class.java)
|
realm.where(IgnoredUserEntity::class.java)
|
||||||
.findAll()
|
.findAll()
|
||||||
|
@ -191,7 +191,7 @@ internal class UserAccountDataSyncHandler @Inject constructor(
|
||||||
// TODO If not initial sync, we should execute a init sync
|
// 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<BreadcrumbsContent>()?.recentRoomIds ?: return
|
val recentRoomIds = event.content.toModel<BreadcrumbsContent>()?.recentRoomIds ?: return
|
||||||
val entity = BreadcrumbsEntity.getOrCreate(realm)
|
val entity = BreadcrumbsEntity.getOrCreate(realm)
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,9 @@ package org.matrix.android.sdk.internal.session.sync.model.accountdata
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
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)
|
@JsonClass(generateAdapter = true)
|
||||||
internal data class UserAccountDataSync(
|
internal data class UserAccountDataSync(
|
||||||
@Json(name = "events") val list: List<AccountDataEvent> = emptyList()
|
@Json(name = "events") val list: List<UserAccountDataEvent> = emptyList()
|
||||||
)
|
)
|
||||||
|
|
|
@ -56,7 +56,6 @@ internal class RoomSyncAccountDataHandler @Inject constructor(private val roomTa
|
||||||
private fun handleGeneric(roomEntity: RoomEntity, content: JsonDict?, eventType: String) {
|
private fun handleGeneric(roomEntity: RoomEntity, content: JsonDict?, eventType: String) {
|
||||||
val existing = roomEntity.accountData.where().equalTo(RoomAccountDataEntityFields.TYPE, eventType).findFirst()
|
val existing = roomEntity.accountData.where().equalTo(RoomAccountDataEntityFields.TYPE, eventType).findFirst()
|
||||||
if (existing != null) {
|
if (existing != null) {
|
||||||
// Update current value
|
|
||||||
existing.contentStr = ContentMapper.map(content)
|
existing.contentStr = ContentMapper.map(content)
|
||||||
} else {
|
} else {
|
||||||
val roomAccountData = RoomAccountDataEntity(
|
val roomAccountData = RoomAccountDataEntity(
|
||||||
|
|
|
@ -18,42 +18,53 @@ package org.matrix.android.sdk.internal.session.user.accountdata
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import com.zhuinden.monarchy.Monarchy
|
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.session.events.model.Content
|
||||||
import org.matrix.android.sdk.api.util.Optional
|
import org.matrix.android.sdk.api.util.Optional
|
||||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||||
import org.matrix.android.sdk.internal.session.sync.UserAccountDataSyncHandler
|
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.TaskExecutor
|
||||||
import org.matrix.android.sdk.internal.task.configureWith
|
import org.matrix.android.sdk.internal.task.configureWith
|
||||||
import org.matrix.android.sdk.internal.util.awaitCallback
|
import org.matrix.android.sdk.internal.util.awaitCallback
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class UserAccountDataService @Inject constructor(
|
internal class DefaultSessionAccountDataService @Inject constructor(
|
||||||
@SessionDatabase private val monarchy: Monarchy,
|
@SessionDatabase private val monarchy: Monarchy,
|
||||||
private val updateUserAccountDataTask: UpdateUserAccountDataTask,
|
private val updateUserAccountDataTask: UpdateUserAccountDataTask,
|
||||||
private val userAccountDataSyncHandler: UserAccountDataSyncHandler,
|
private val userAccountDataSyncHandler: UserAccountDataSyncHandler,
|
||||||
private val accountDataDataSource: UserAccountDataDataSource,
|
private val userAccountDataDataSource: UserAccountDataDataSource,
|
||||||
|
private val roomAccountDataDataSource: RoomAccountDataDataSource,
|
||||||
private val taskExecutor: TaskExecutor
|
private val taskExecutor: TaskExecutor
|
||||||
) : AccountDataService {
|
) : SessionAccountDataService {
|
||||||
|
|
||||||
override fun getAccountDataEvent(type: String): AccountDataEvent? {
|
override fun getUserAccountDataEvent(type: String): UserAccountDataEvent? {
|
||||||
return accountDataDataSource.getAccountDataEvent(type)
|
return userAccountDataDataSource.getAccountDataEvent(type)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getLiveAccountDataEvent(type: String): LiveData<Optional<AccountDataEvent>> {
|
override fun getLiveUserAccountDataEvent(type: String): LiveData<Optional<UserAccountDataEvent>> {
|
||||||
return accountDataDataSource.getLiveAccountDataEvent(type)
|
return userAccountDataDataSource.getLiveAccountDataEvent(type)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getAccountDataEvents(types: Set<String>): List<AccountDataEvent> {
|
override fun getUserAccountDataEvents(types: Set<String>): List<UserAccountDataEvent> {
|
||||||
return accountDataDataSource.getAccountDataEvents(types)
|
return userAccountDataDataSource.getAccountDataEvents(types)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getLiveAccountDataEvents(types: Set<String>): LiveData<List<AccountDataEvent>> {
|
override fun getLiveUserAccountDataEvents(types: Set<String>): LiveData<List<UserAccountDataEvent>> {
|
||||||
return accountDataDataSource.getLiveAccountDataEvents(types)
|
return userAccountDataDataSource.getLiveAccountDataEvents(types)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun updateAccountData(type: String, content: Content) {
|
override fun getRoomAccountDataEvents(types: Set<String>): List<RoomAccountDataEvent> {
|
||||||
|
return roomAccountDataDataSource.getAccountDataEvents(null, types)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getLiveRoomAccountDataEvents(types: Set<String>): LiveData<List<RoomAccountDataEvent>> {
|
||||||
|
return roomAccountDataDataSource.getLiveAccountDataEvents(null, types)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun updateUserAccountData(type: String, content: Content) {
|
||||||
val params = UpdateUserAccountDataTask.AnyParams(type = type, any = content)
|
val params = UpdateUserAccountDataTask.AnyParams(type = type, any = content)
|
||||||
awaitCallback<Unit> { callback ->
|
awaitCallback<Unit> { callback ->
|
||||||
updateUserAccountDataTask.configureWith(params) {
|
updateUserAccountDataTask.configureWith(params) {
|
|
@ -21,7 +21,7 @@ import androidx.lifecycle.Transformations
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
import io.realm.RealmQuery
|
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.Optional
|
||||||
import org.matrix.android.sdk.api.util.toOptional
|
import org.matrix.android.sdk.api.util.toOptional
|
||||||
import org.matrix.android.sdk.internal.database.RealmSessionProvider
|
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 realmSessionProvider: RealmSessionProvider,
|
||||||
private val accountDataMapper: AccountDataMapper) {
|
private val accountDataMapper: AccountDataMapper) {
|
||||||
|
|
||||||
fun getAccountDataEvent(type: String): AccountDataEvent? {
|
fun getAccountDataEvent(type: String): UserAccountDataEvent? {
|
||||||
return getAccountDataEvents(setOf(type)).firstOrNull()
|
return getAccountDataEvents(setOf(type)).firstOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getLiveAccountDataEvent(type: String): LiveData<Optional<AccountDataEvent>> {
|
fun getLiveAccountDataEvent(type: String): LiveData<Optional<UserAccountDataEvent>> {
|
||||||
return Transformations.map(getLiveAccountDataEvents(setOf(type))) {
|
return Transformations.map(getLiveAccountDataEvents(setOf(type))) {
|
||||||
it.firstOrNull()?.toOptional()
|
it.firstOrNull()?.toOptional()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAccountDataEvents(types: Set<String>): List<AccountDataEvent> {
|
fun getAccountDataEvents(types: Set<String>): List<UserAccountDataEvent> {
|
||||||
return realmSessionProvider.withRealm {
|
return realmSessionProvider.withRealm {
|
||||||
accountDataEventsQuery(it, types).findAll().map(accountDataMapper::map)
|
accountDataEventsQuery(it, types).findAll().map(accountDataMapper::map)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getLiveAccountDataEvents(types: Set<String>): LiveData<List<AccountDataEvent>> {
|
fun getLiveAccountDataEvents(types: Set<String>): LiveData<List<UserAccountDataEvent>> {
|
||||||
return monarchy.findAllMappedWithChanges(
|
return monarchy.findAllMappedWithChanges(
|
||||||
{ accountDataEventsQuery(it, types) },
|
{ accountDataEventsQuery(it, types) },
|
||||||
accountDataMapper::map
|
accountDataMapper::map
|
||||||
|
|
|
@ -23,7 +23,7 @@ import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.Transformations
|
import androidx.lifecycle.Transformations
|
||||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||||
import org.matrix.android.sdk.api.session.Session
|
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.accountdata.UserAccountDataTypes
|
||||||
import org.matrix.android.sdk.api.session.events.model.Content
|
import org.matrix.android.sdk.api.session.events.model.Content
|
||||||
import org.matrix.android.sdk.api.session.events.model.Event
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
|
@ -47,7 +47,7 @@ import javax.inject.Inject
|
||||||
|
|
||||||
@SessionScope
|
@SessionScope
|
||||||
internal class WidgetManager @Inject constructor(private val integrationManager: IntegrationManager,
|
internal class WidgetManager @Inject constructor(private val integrationManager: IntegrationManager,
|
||||||
private val accountDataDataSource: UserAccountDataDataSource,
|
private val userAccountDataDataSource: UserAccountDataDataSource,
|
||||||
private val stateEventDataSource: StateEventDataSource,
|
private val stateEventDataSource: StateEventDataSource,
|
||||||
private val createWidgetTask: CreateWidgetTask,
|
private val createWidgetTask: CreateWidgetTask,
|
||||||
private val widgetFactory: WidgetFactory,
|
private val widgetFactory: WidgetFactory,
|
||||||
|
@ -136,7 +136,7 @@ internal class WidgetManager @Inject constructor(private val integrationManager:
|
||||||
widgetTypes: Set<String>? = null,
|
widgetTypes: Set<String>? = null,
|
||||||
excludedTypes: Set<String>? = null
|
excludedTypes: Set<String>? = null
|
||||||
): LiveData<List<Widget>> {
|
): LiveData<List<Widget>> {
|
||||||
val widgetsAccountData = accountDataDataSource.getLiveAccountDataEvent(UserAccountDataTypes.TYPE_WIDGETS)
|
val widgetsAccountData = userAccountDataDataSource.getLiveAccountDataEvent(UserAccountDataTypes.TYPE_WIDGETS)
|
||||||
return Transformations.map(widgetsAccountData) {
|
return Transformations.map(widgetsAccountData) {
|
||||||
it.getOrNull()?.mapToWidgets(widgetTypes, excludedTypes).orEmpty()
|
it.getOrNull()?.mapToWidgets(widgetTypes, excludedTypes).orEmpty()
|
||||||
}
|
}
|
||||||
|
@ -146,11 +146,11 @@ internal class WidgetManager @Inject constructor(private val integrationManager:
|
||||||
widgetTypes: Set<String>? = null,
|
widgetTypes: Set<String>? = null,
|
||||||
excludedTypes: Set<String>? = null
|
excludedTypes: Set<String>? = null
|
||||||
): List<Widget> {
|
): List<Widget> {
|
||||||
val widgetsAccountData = accountDataDataSource.getAccountDataEvent(UserAccountDataTypes.TYPE_WIDGETS) ?: return emptyList()
|
val widgetsAccountData = userAccountDataDataSource.getAccountDataEvent(UserAccountDataTypes.TYPE_WIDGETS) ?: return emptyList()
|
||||||
return widgetsAccountData.mapToWidgets(widgetTypes, excludedTypes)
|
return widgetsAccountData.mapToWidgets(widgetTypes, excludedTypes)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun AccountDataEvent.mapToWidgets(widgetTypes: Set<String>? = null,
|
private fun UserAccountDataEvent.mapToWidgets(widgetTypes: Set<String>? = null,
|
||||||
excludedTypes: Set<String>? = null): List<Widget> {
|
excludedTypes: Set<String>? = null): List<Widget> {
|
||||||
return extractWidgetSequence(widgetFactory)
|
return extractWidgetSequence(widgetFactory)
|
||||||
.filter {
|
.filter {
|
||||||
|
|
|
@ -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.Event
|
||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
import org.matrix.android.sdk.api.util.JsonDict
|
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
|
import org.matrix.android.sdk.api.session.widgets.model.Widget
|
||||||
|
|
||||||
internal fun AccountDataEvent.extractWidgetSequence(widgetFactory: WidgetFactory): Sequence<Widget> {
|
internal fun UserAccountDataEvent.extractWidgetSequence(widgetFactory: WidgetFactory): Sequence<Widget> {
|
||||||
return content.asSequence()
|
return content.asSequence()
|
||||||
.mapNotNull {
|
.mapNotNull {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Migrate DefaultTypingService, KeysImporter and KeysExporter to coroutines
|
|
@ -0,0 +1 @@
|
||||||
|
Update Message Composer design
|
|
@ -0,0 +1 @@
|
||||||
|
Cleanup Epoxy items, and debounce all the clicks
|
|
@ -0,0 +1,2 @@
|
||||||
|
Migrate to new colors and cleanup the style and theme
|
||||||
|
Ref: https://material.io/blog/migrate-android-material-components
|
|
@ -0,0 +1 @@
|
||||||
|
VoIP: Change hold direction to send-only.
|
|
@ -0,0 +1 @@
|
||||||
|
Splits SessionAccountDataService and RoomAccountDataService and offers to query RoomAccountDataEvent at the session level.
|
|
@ -136,8 +136,9 @@ android\.R\.id\.home===2
|
||||||
### Kotlin conversion tools introduce this, but is can be replace by trim()
|
### Kotlin conversion tools introduce this, but is can be replace by trim()
|
||||||
trim \{ it \<\= \' \' \}
|
trim \{ it \<\= \' \' \}
|
||||||
|
|
||||||
### Use AlertDialog form v7 compat lib
|
### Use MaterialAlertDialogBuilder
|
||||||
android\.app\.AlertDialog
|
android\.app\.AlertDialog
|
||||||
|
androidx\.appcompat\.app\.AlertDialog===4
|
||||||
|
|
||||||
### Put the operator at the beginning of next line
|
### Put the operator at the beginning of next line
|
||||||
&&$
|
&&$
|
||||||
|
|
|
@ -84,3 +84,22 @@ layout_constraintLeft_
|
||||||
|
|
||||||
### Use androidx.recyclerview.widget.RecyclerView because EpoxyRecyclerViews add behavior we do not want to
|
### Use androidx.recyclerview.widget.RecyclerView because EpoxyRecyclerViews add behavior we do not want to
|
||||||
<com\.airbnb\.epoxy\.EpoxyRecyclerView
|
<com\.airbnb\.epoxy\.EpoxyRecyclerView
|
||||||
|
|
||||||
|
### Use Button instead of MaterialButton, the inflater will automatically inflate MaterialButton.
|
||||||
|
<com\.google\.android\.material\.button\.MaterialButton
|
||||||
|
<androidx\.appcompat\.widget\.AppCompatButton
|
||||||
|
|
||||||
|
### Use CheckBox instead of MaterialCheckBox, the inflater will automatically inflate MaterialCheckBox.
|
||||||
|
<com\.google\.android\.material\.checkbox\.MaterialCheckBox
|
||||||
|
|
||||||
|
### Use RadioButton instead of MaterialRadioButton, the inflater will automatically inflate Material Views.
|
||||||
|
<com\.google\.android\.material\.radiobutton\.MaterialRadioButton
|
||||||
|
|
||||||
|
### Use com.google.android.material.switchmaterial.SwitchMaterial instead of Switch, the inflater will not automatically inflate Material Views for Switch.
|
||||||
|
<Switch
|
||||||
|
|
||||||
|
### Use colorSecondary
|
||||||
|
colorAccent
|
||||||
|
|
||||||
|
### Use MaterialCardView
|
||||||
|
<androidx\.cardview\.widget\.CardView
|
|
@ -320,13 +320,13 @@ dependencies {
|
||||||
implementation project(":diff-match-patch")
|
implementation project(":diff-match-patch")
|
||||||
implementation project(":multipicker")
|
implementation project(":multipicker")
|
||||||
implementation project(":attachment-viewer")
|
implementation project(":attachment-viewer")
|
||||||
implementation 'com.android.support:multidex:1.0.3'
|
implementation 'androidx.multidex:multidex:2.0.1'
|
||||||
|
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
|
||||||
|
|
||||||
implementation "androidx.recyclerview:recyclerview:1.2.0"
|
implementation "androidx.recyclerview:recyclerview:1.2.1"
|
||||||
implementation 'androidx.appcompat:appcompat:1.3.0'
|
implementation 'androidx.appcompat:appcompat:1.3.0'
|
||||||
implementation "androidx.fragment:fragment-ktx:$fragment_version"
|
implementation "androidx.fragment:fragment-ktx:$fragment_version"
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
||||||
|
@ -396,7 +396,7 @@ dependencies {
|
||||||
implementation 'androidx.browser:browser:1.3.0'
|
implementation 'androidx.browser:browser:1.3.0'
|
||||||
|
|
||||||
// Passphrase strength helper
|
// Passphrase strength helper
|
||||||
implementation 'com.nulab-inc:zxcvbn:1.5.0'
|
implementation 'com.nulab-inc:zxcvbn:1.5.2'
|
||||||
|
|
||||||
//Alerter
|
//Alerter
|
||||||
implementation 'com.tapadoo.android:alerter:7.0.1'
|
implementation 'com.tapadoo.android:alerter:7.0.1'
|
||||||
|
|
|
@ -6,11 +6,26 @@
|
||||||
<activity android:name=".features.debug.TestLinkifyActivity" />
|
<activity android:name=".features.debug.TestLinkifyActivity" />
|
||||||
<activity android:name=".features.debug.sas.DebugSasEmojiActivity" />
|
<activity android:name=".features.debug.sas.DebugSasEmojiActivity" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".features.debug.DebugMaterialThemeLightActivity"
|
android:name=".features.debug.DebugMaterialThemeLightDefaultActivity"
|
||||||
android:theme="@style/VectorMaterialThemeDebugLight" />
|
android:theme="@style/VectorMaterialThemeDebugLight" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".features.debug.DebugMaterialThemeDarkActivity"
|
android:name=".features.debug.DebugMaterialThemeLightTestActivity"
|
||||||
|
android:theme="@style/VectorMaterialThemeDebugLight.Test" />
|
||||||
|
<activity
|
||||||
|
android:name=".features.debug.DebugMaterialThemeLightVectorActivity"
|
||||||
|
android:theme="@style/AppTheme.Light" />
|
||||||
|
<activity
|
||||||
|
android:name=".features.debug.DebugMaterialThemeDarkDefaultActivity"
|
||||||
android:theme="@style/VectorMaterialThemeDebugDark" />
|
android:theme="@style/VectorMaterialThemeDebugDark" />
|
||||||
|
<activity
|
||||||
|
android:name=".features.debug.DebugMaterialThemeDarkTestActivity"
|
||||||
|
android:theme="@style/VectorMaterialThemeDebugDark.Test" />
|
||||||
|
<activity
|
||||||
|
android:name=".features.debug.DebugMaterialThemeDarkVectorActivity"
|
||||||
|
android:theme="@style/AppTheme.Dark" />
|
||||||
|
<activity
|
||||||
|
android:name=".features.debug.DebugVectorButtonStylesActivity"
|
||||||
|
android:theme="@style/AppTheme.Light" />
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,9 +18,8 @@ package im.vector.app.features.debug
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import androidx.appcompat.app.AlertDialog
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
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 com.google.android.material.snackbar.Snackbar
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.utils.toast
|
import im.vector.app.core.utils.toast
|
||||||
|
@ -45,7 +44,8 @@ abstract class DebugMaterialThemeActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
views.debugShowDialog.setOnClickListener {
|
views.debugShowDialog.setOnClickListener {
|
||||||
AlertDialog.Builder(this)
|
MaterialAlertDialogBuilder(this)
|
||||||
|
.setTitle("Dialog title")
|
||||||
.setMessage("Dialog content")
|
.setMessage("Dialog content")
|
||||||
.setIcon(R.drawable.ic_settings_x)
|
.setIcon(R.drawable.ic_settings_x)
|
||||||
.setPositiveButton("Positive", null)
|
.setPositiveButton("Positive", null)
|
||||||
|
@ -55,7 +55,7 @@ abstract class DebugMaterialThemeActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
views.debugShowBottomSheet.setOnClickListener {
|
views.debugShowBottomSheet.setOnClickListener {
|
||||||
BottomSheetDialogFragment().show(supportFragmentManager, "TAG")
|
DebugBottomSheet().show(supportFragmentManager, "TAG")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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()
|
|
@ -16,4 +16,4 @@
|
||||||
|
|
||||||
package im.vector.app.features.debug
|
package im.vector.app.features.debug
|
||||||
|
|
||||||
class DebugMaterialThemeDarkActivity : DebugMaterialThemeActivity()
|
class DebugMaterialThemeDarkTestActivity : DebugMaterialThemeActivity()
|
|
@ -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()
|
|
@ -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()
|
|
@ -16,4 +16,4 @@
|
||||||
|
|
||||||
package im.vector.app.features.debug
|
package im.vector.app.features.debug
|
||||||
|
|
||||||
class DebugMaterialThemeLightActivity : DebugMaterialThemeActivity()
|
class DebugMaterialThemeLightTestActivity : DebugMaterialThemeActivity()
|
|
@ -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()
|
|
@ -71,10 +71,29 @@ class DebugMenuActivity : VectorBaseActivity<ActivityDebugMenuBinding>() {
|
||||||
|
|
||||||
private fun setupViews() {
|
private fun setupViews() {
|
||||||
views.debugTestTextViewLink.setOnClickListener { testTextViewLink() }
|
views.debugTestTextViewLink.setOnClickListener { testTextViewLink() }
|
||||||
|
views.debugOpenButtonStyles.setOnClickListener {
|
||||||
|
startActivity(Intent(this, DebugVectorButtonStylesActivity::class.java))
|
||||||
|
}
|
||||||
views.debugShowSasEmoji.setOnClickListener { showSasEmoji() }
|
views.debugShowSasEmoji.setOnClickListener { showSasEmoji() }
|
||||||
views.debugTestNotification.setOnClickListener { testNotification() }
|
views.debugTestNotification.setOnClickListener { testNotification() }
|
||||||
views.debugTestMaterialThemeLight.setOnClickListener { testMaterialThemeLight() }
|
views.debugTestMaterialThemeLightDefault.setOnClickListener {
|
||||||
views.debugTestMaterialThemeDark.setOnClickListener { testMaterialThemeDark() }
|
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.debugTestCrash.setOnClickListener { testCrash() }
|
||||||
views.debugScanQrCode.setOnClickListener { scanQRCode() }
|
views.debugScanQrCode.setOnClickListener { scanQRCode() }
|
||||||
}
|
}
|
||||||
|
@ -174,14 +193,6 @@ class DebugMenuActivity : VectorBaseActivity<ActivityDebugMenuBinding>() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun testMaterialThemeLight() {
|
|
||||||
startActivity(Intent(this, DebugMaterialThemeLightActivity::class.java))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun testMaterialThemeDark() {
|
|
||||||
startActivity(Intent(this, DebugMaterialThemeDarkActivity::class.java))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun testCrash() {
|
private fun testCrash() {
|
||||||
throw RuntimeException("Application crashed from user demand")
|
throw RuntimeException("Application crashed from user demand")
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<ActivityDebugButtonStylesBinding>() {
|
||||||
|
override fun getBinding() = ActivityDebugButtonStylesBinding.inflate(layoutInflater)
|
||||||
|
}
|
|
@ -0,0 +1,131 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".features.debug.DebugVectorButtonStylesActivity"
|
||||||
|
tools:ignore="HardcodedText">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/VectorButtonStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Default" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/VectorButtonStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:enabled="false"
|
||||||
|
android:text="Default disabled" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/VectorButtonStyleText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Text" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/VectorButtonStyleText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:enabled="false"
|
||||||
|
android:text="Text disabled" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/VectorButtonStyle.Positive"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Positive" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/VectorButtonStyle.Positive"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:enabled="false"
|
||||||
|
android:text="Positive disabled" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/VectorButtonStyle.Destructive"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Destructive" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/VectorButtonStyle.Destructive"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:enabled="false"
|
||||||
|
android:text="Destructive disabled" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/VectorButtonStyleUnelevated.Bot"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Bot" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/VectorButtonStyleUnelevated.Bot"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:enabled="false"
|
||||||
|
android:text="Bot disabled" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/VectorButtonStyleOutlined"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:checked="true"
|
||||||
|
android:text="Outline" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/VectorButtonStyleOutlined"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:enabled="false"
|
||||||
|
android:text="Outline disabled" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/VectorButtonStyleOutlined.Poll"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Poll " />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/VectorButtonStyleOutlined.Poll"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:enabled="false"
|
||||||
|
android:text="Poll disabled" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/palette_azure"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="8dp">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/AlerterButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:checked="true"
|
||||||
|
android:text="Alerter" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/AlerterButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:enabled="false"
|
||||||
|
android:text="Alerter disabled" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
|
@ -20,51 +20,106 @@
|
||||||
android:padding="@dimen/layout_horizontal_margin"
|
android:padding="@dimen/layout_horizontal_margin"
|
||||||
android:showDividers="middle">
|
android:showDividers="middle">
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<Button
|
||||||
android:id="@+id/debug_test_text_view_link"
|
android:id="@+id/debug_test_text_view_link"
|
||||||
style="@style/VectorButtonStyle"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Test linkification" />
|
android:text="Test linkification" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<Button
|
||||||
android:id="@+id/debug_test_notification"
|
android:id="@+id/debug_test_notification"
|
||||||
style="@style/VectorButtonStyle"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Test Notification" />
|
android:text="Test Notification" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<TextView
|
||||||
android:id="@+id/debug_test_material_theme_light"
|
|
||||||
style="@style/VectorButtonStyle"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Test Material theme Light" />
|
android:text="Light theme" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<LinearLayout
|
||||||
android:id="@+id/debug_test_material_theme_dark"
|
android:layout_width="match_parent"
|
||||||
style="@style/VectorButtonStyle"
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/debug_test_material_theme_light_default"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Test Material theme Dark" />
|
android:layout_margin="8dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="Default" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<Button
|
||||||
|
android:id="@+id/debug_test_material_theme_light_test"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="Test" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/debug_test_material_theme_light_vector"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="Vector" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Dark theme" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/debug_test_material_theme_dark_default"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="Default" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/debug_test_material_theme_dark_test"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="Test" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/debug_test_material_theme_dark_vector"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="Vector" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/debug_open_button_styles"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="See button styles" />
|
||||||
|
|
||||||
|
<Button
|
||||||
android:id="@+id/debug_show_sas_emoji"
|
android:id="@+id/debug_show_sas_emoji"
|
||||||
style="@style/VectorButtonStyle"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Display all SAS emoji" />
|
android:text="Display all SAS emoji" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<Button
|
||||||
android:id="@+id/debug_test_crash"
|
android:id="@+id/debug_test_crash"
|
||||||
style="@style/VectorButtonStyle"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Crash the app" />
|
android:text="Crash the app" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<Button
|
||||||
android:id="@+id/debug_scan_qr_code"
|
android:id="@+id/debug_scan_qr_code"
|
||||||
style="@style/VectorButtonStyle"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Scan QR-code" />
|
android:text="Scan QR-code" />
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
android:id="@+id/coordinatorLayout"
|
android:id="@+id/coordinatorLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
|
||||||
tools:context=".features.debug.DebugMaterialThemeActivity"
|
tools:context=".features.debug.DebugMaterialThemeActivity"
|
||||||
tools:ignore="HardcodedText">
|
tools:ignore="HardcodedText">
|
||||||
|
|
||||||
|
@ -28,6 +27,229 @@
|
||||||
app:subtitle="Toolbar Subtitle"
|
app:subtitle="Toolbar Subtitle"
|
||||||
app:title="Toolbar Title" />
|
app:title="Toolbar Title" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:baselineAligned="false"
|
||||||
|
android:divider="@drawable/linear_divider"
|
||||||
|
android:showDividers="middle">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="#FFFFFF"
|
||||||
|
android:divider="@drawable/linear_divider"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:showDividers="middle">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.White"
|
||||||
|
android:background="?colorPrimary"
|
||||||
|
android:text="colorPrimary" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.White"
|
||||||
|
android:background="?colorPrimaryVariant"
|
||||||
|
android:text="colorPrimaryVariant" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.White"
|
||||||
|
android:background="?colorOnPrimary"
|
||||||
|
android:text="colorOnPrimary" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.White"
|
||||||
|
android:background="?colorSecondary"
|
||||||
|
android:text="colorSecondary" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.White"
|
||||||
|
android:background="?colorSecondaryVariant"
|
||||||
|
android:text="colorSecondaryVariant" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.White"
|
||||||
|
android:background="?colorOnSecondary"
|
||||||
|
android:text="colorOnSecondary" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.White"
|
||||||
|
android:background="?colorError"
|
||||||
|
android:text="colorError" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.White"
|
||||||
|
android:background="?colorOnError"
|
||||||
|
android:text="colorOnError" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.White"
|
||||||
|
android:background="?colorSurface"
|
||||||
|
android:text="colorSurface" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.White"
|
||||||
|
android:background="?colorOnSurface"
|
||||||
|
android:text="colorOnSurface" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.White"
|
||||||
|
android:background="?android:colorBackground"
|
||||||
|
android:text="android:colorBackground" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.White"
|
||||||
|
android:background="?colorOnBackground"
|
||||||
|
android:text="colorOnBackground" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.White"
|
||||||
|
android:background="?colorAccent"
|
||||||
|
android:text="colorAccent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.White"
|
||||||
|
android:background="?android:statusBarColor"
|
||||||
|
android:text="android:statusBarColor" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.White"
|
||||||
|
android:background="?android:navigationBarColor"
|
||||||
|
android:text="android:navigationBarColor" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.White"
|
||||||
|
android:background="?android:textColorPrimary"
|
||||||
|
android:text="android:textColorPrimary" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.White"
|
||||||
|
android:background="?android:textColorSecondary"
|
||||||
|
android:text="android:textColorSecondary" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.White"
|
||||||
|
android:background="?android:textColorTertiary"
|
||||||
|
android:text="android:textColorTertiary" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.White"
|
||||||
|
android:background="?android:textColorLink"
|
||||||
|
android:text="android:textColorLink" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="#000000"
|
||||||
|
android:divider="@drawable/linear_divider"
|
||||||
|
android:dividerPadding="8dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:showDividers="middle">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.Black"
|
||||||
|
android:background="?colorPrimary"
|
||||||
|
android:text="colorPrimary" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.Black"
|
||||||
|
android:background="?colorPrimaryVariant"
|
||||||
|
android:text="colorPrimaryVariant" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.Black"
|
||||||
|
android:background="?colorOnPrimary"
|
||||||
|
android:text="colorOnPrimary" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.Black"
|
||||||
|
android:background="?colorSecondary"
|
||||||
|
android:text="colorSecondary" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.Black"
|
||||||
|
android:background="?colorSecondaryVariant"
|
||||||
|
android:text="colorSecondaryVariant" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.Black"
|
||||||
|
android:background="?colorOnSecondary"
|
||||||
|
android:text="colorOnSecondary" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.Black"
|
||||||
|
android:background="?colorError"
|
||||||
|
android:text="colorError" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.Black"
|
||||||
|
android:background="?colorOnError"
|
||||||
|
android:text="colorOnError" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.Black"
|
||||||
|
android:background="?colorSurface"
|
||||||
|
android:text="colorSurface" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.Black"
|
||||||
|
android:background="?colorOnSurface"
|
||||||
|
android:text="colorOnSurface" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.Black"
|
||||||
|
android:background="?android:colorBackground"
|
||||||
|
android:text="android:colorBackground" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.Black"
|
||||||
|
android:background="?colorOnBackground"
|
||||||
|
android:text="colorOnBackground" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.Black"
|
||||||
|
android:background="?colorAccent"
|
||||||
|
android:text="colorAccent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.Black"
|
||||||
|
android:background="?android:statusBarColor"
|
||||||
|
android:text="android:statusBarColor" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.Black"
|
||||||
|
android:background="?android:navigationBarColor"
|
||||||
|
android:text="android:navigationBarColor" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.Black"
|
||||||
|
android:background="?android:textColorPrimary"
|
||||||
|
android:text="android:textColorPrimary" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.Black"
|
||||||
|
android:background="?android:textColorSecondary"
|
||||||
|
android:text="android:textColorSecondary" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.Black"
|
||||||
|
android:background="?android:textColorTertiary"
|
||||||
|
android:text="android:textColorTertiary" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/DebugTextColorDemo.Black"
|
||||||
|
android:background="?android:textColorLink"
|
||||||
|
android:text="android:textColorLink" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -81,60 +303,105 @@
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Buttons" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<Button
|
||||||
style="@style/Widget.MaterialComponents.Button"
|
style="@style/Widget.MaterialComponents.Button"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Material Button Classic"
|
android:text="Classic"
|
||||||
app:icon="@drawable/ic_settings_x" />
|
app:icon="@drawable/ic_settings_x" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<Button
|
||||||
|
style="@style/Widget.MaterialComponents.Button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:enabled="false"
|
||||||
|
android:text="Classic Disabled"
|
||||||
|
app:icon="@drawable/ic_settings_x" />
|
||||||
|
|
||||||
|
<Button
|
||||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Material Button OutlinedButton"
|
android:text="OutlinedButton"
|
||||||
app:icon="@drawable/ic_settings_x" />
|
app:icon="@drawable/ic_settings_x" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<Button
|
||||||
|
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:enabled="false"
|
||||||
|
android:text="OutlinedButton Disabled"
|
||||||
|
app:icon="@drawable/ic_settings_x" />
|
||||||
|
|
||||||
|
<Button
|
||||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Material Button TextButton"
|
android:text="TextButton"
|
||||||
app:icon="@drawable/ic_settings_x" />
|
app:icon="@drawable/ic_settings_x" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<Button
|
||||||
|
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:enabled="false"
|
||||||
|
android:text="TextButton Disabled"
|
||||||
|
app:icon="@drawable/ic_settings_x" />
|
||||||
|
|
||||||
|
<Button
|
||||||
style="@style/Widget.MaterialComponents.Button.UnelevatedButton"
|
style="@style/Widget.MaterialComponents.Button.UnelevatedButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Material Button UnelevatedButton"
|
android:text="UnelevatedButton"
|
||||||
app:icon="@drawable/ic_settings_x" />
|
app:icon="@drawable/ic_settings_x" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<Button
|
||||||
|
style="@style/Widget.MaterialComponents.Button.UnelevatedButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:enabled="false"
|
||||||
|
android:text="UnelevatedButton Disabled"
|
||||||
|
app:icon="@drawable/ic_settings_x" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Actions" />
|
||||||
|
|
||||||
|
<Button
|
||||||
android:id="@+id/debugShowSnackbar"
|
android:id="@+id/debugShowSnackbar"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
android:text="Show Snackbar" />
|
android:text="Show Snackbar" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<Button
|
||||||
android:id="@+id/debugShowToast"
|
android:id="@+id/debugShowToast"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
android:text="Show Toast" />
|
android:text="Show Toast" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<Button
|
||||||
android:id="@+id/debugShowDialog"
|
android:id="@+id/debugShowDialog"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
android:text="Show Dialog" />
|
android:text="Show Dialog" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<Button
|
||||||
android:id="@+id/debugShowBottomSheet"
|
android:id="@+id/debugShowBottomSheet"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
android:text="Show Bottom Sheet" />
|
android:text="Show Bottom Sheet" />
|
||||||
|
|
||||||
<com.google.android.material.checkbox.MaterialCheckBox
|
<CheckBox
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Material CheckBox" />
|
android:text="Material CheckBox" />
|
||||||
|
@ -146,7 +413,8 @@
|
||||||
|
|
||||||
<com.google.android.material.card.MaterialCardView
|
<com.google.android.material.card.MaterialCardView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -159,9 +427,16 @@
|
||||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="end"
|
||||||
|
android:layout_margin="16dp"
|
||||||
android:importantForAccessibility="no"
|
android:importantForAccessibility="no"
|
||||||
android:src="@drawable/ic_settings_x" />
|
android:src="@drawable/ic_settings_x" />
|
||||||
|
|
||||||
|
<com.google.android.material.bottomnavigation.BottomNavigationView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:menu="@menu/home_bottom_navigation" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|
|
@ -8,8 +8,7 @@
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical">
|
||||||
android:theme="@style/Theme.AppCompat.Light.DarkActionBar">
|
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:textColor="@color/black"
|
android:textColor="@color/emoji_color"
|
||||||
android:textSize="22sp"
|
android:textSize="22sp"
|
||||||
tools:text="🔧" />
|
tools:text="🔧" />
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -38,4 +38,4 @@
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</androidx.cardview.widget.CardView>
|
</com.google.android.material.card.MaterialCardView>
|
|
@ -7,6 +7,10 @@
|
||||||
|
|
||||||
|
|
||||||
<style name="VectorMaterialThemeDebugLight" parent="Theme.MaterialComponents.Light.NoActionBar">
|
<style name="VectorMaterialThemeDebugLight" parent="Theme.MaterialComponents.Light.NoActionBar">
|
||||||
|
<!-- Keep all default value -->
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="VectorMaterialThemeDebugLight.Test">
|
||||||
<item name="colorPrimary">#7F7F00</item>
|
<item name="colorPrimary">#7F7F00</item>
|
||||||
<item name="colorPrimaryVariant">#00FF00</item>
|
<item name="colorPrimaryVariant">#00FF00</item>
|
||||||
<item name="colorOnPrimary">#0000FF</item>
|
<item name="colorOnPrimary">#0000FF</item>
|
||||||
|
@ -24,14 +28,17 @@
|
||||||
<item name="android:colorBackground">#FF7777</item>
|
<item name="android:colorBackground">#FF7777</item>
|
||||||
<item name="colorOnBackground">#077700</item>
|
<item name="colorOnBackground">#077700</item>
|
||||||
|
|
||||||
<!-- TODO is it still required? -->
|
|
||||||
<item name="colorAccent">#03b381</item>
|
|
||||||
|
|
||||||
<item name="android:statusBarColor">#1188FF</item>
|
<item name="android:statusBarColor">#1188FF</item>
|
||||||
<item name="android:navigationBarColor">#FF8811</item>
|
<item name="android:navigationBarColor">#FF8811</item>
|
||||||
|
|
||||||
|
<item name="android:textColorLink">#000FFF</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="VectorMaterialThemeDebugDark" parent="Theme.MaterialComponents.NoActionBar">
|
<style name="VectorMaterialThemeDebugDark" parent="Theme.MaterialComponents.NoActionBar">
|
||||||
|
<!-- Keep all default value -->
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="VectorMaterialThemeDebugDark.Test">
|
||||||
<item name="colorPrimary">#7F7F00</item>
|
<item name="colorPrimary">#7F7F00</item>
|
||||||
<item name="colorPrimaryVariant">#00FF00</item>
|
<item name="colorPrimaryVariant">#00FF00</item>
|
||||||
<item name="colorOnPrimary">#0000FF</item>
|
<item name="colorOnPrimary">#0000FF</item>
|
||||||
|
@ -49,11 +56,26 @@
|
||||||
<item name="android:colorBackground">#FF7777</item>
|
<item name="android:colorBackground">#FF7777</item>
|
||||||
<item name="colorOnBackground">#077700</item>
|
<item name="colorOnBackground">#077700</item>
|
||||||
|
|
||||||
<!-- TODO is it still required? -->
|
|
||||||
<item name="colorAccent">#03b381</item>
|
|
||||||
|
|
||||||
<item name="android:statusBarColor">#1188FF</item>
|
<item name="android:statusBarColor">#1188FF</item>
|
||||||
<item name="android:navigationBarColor">#FF8811</item>
|
<item name="android:navigationBarColor">#FF8811</item>
|
||||||
|
|
||||||
|
<item name="android:textColorLink">#000FFF</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="DebugTextColorDemo">
|
||||||
|
<item name="android:layout_height">wrap_content</item>
|
||||||
|
<item name="android:layout_width">match_parent</item>
|
||||||
|
<item name="android:padding">4dp</item>
|
||||||
|
<item name="android:gravity">center</item>
|
||||||
|
<item name="android:textSize">16sp</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="DebugTextColorDemo.White">
|
||||||
|
<item name="android:textColor">#FFFFFF</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="DebugTextColorDemo.Black">
|
||||||
|
<item name="android:textColor">#000000</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
|
@ -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<V : View>(context: Context, attrs: AttributeSet) : CoordinatorLayout.Behavior<V>(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()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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.call.transfer.CallTransferActivity
|
||||||
import im.vector.app.features.createdirect.CreateDirectRoomActivity
|
import im.vector.app.features.createdirect.CreateDirectRoomActivity
|
||||||
import im.vector.app.features.crypto.keysbackup.settings.KeysBackupManageActivity
|
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.quads.SharedSecureStorageActivity
|
||||||
import im.vector.app.features.crypto.recover.BootstrapBottomSheet
|
import im.vector.app.features.crypto.recover.BootstrapBottomSheet
|
||||||
import im.vector.app.features.crypto.verification.VerificationBottomSheet
|
import im.vector.app.features.crypto.verification.VerificationBottomSheet
|
||||||
|
@ -138,6 +139,7 @@ interface ScreenComponent {
|
||||||
fun inject(activity: LinkHandlerActivity)
|
fun inject(activity: LinkHandlerActivity)
|
||||||
fun inject(activity: MainActivity)
|
fun inject(activity: MainActivity)
|
||||||
fun inject(activity: RoomDirectoryActivity)
|
fun inject(activity: RoomDirectoryActivity)
|
||||||
|
fun inject(activity: KeysBackupSetupActivity)
|
||||||
fun inject(activity: BugReportActivity)
|
fun inject(activity: BugReportActivity)
|
||||||
fun inject(activity: FilteredRoomsActivity)
|
fun inject(activity: FilteredRoomsActivity)
|
||||||
fun inject(activity: CreateRoomActivity)
|
fun inject(activity: CreateRoomActivity)
|
||||||
|
|
|
@ -18,8 +18,8 @@ package im.vector.app.core.dialogs
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.appcompat.app.AlertDialog
|
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.databinding.DialogConfirmationWithReasonBinding
|
import im.vector.app.databinding.DialogConfirmationWithReasonBinding
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ object ConfirmationDialogBuilder {
|
||||||
views.dialogReasonInput.setHint(reasonHintRes)
|
views.dialogReasonInput.setHint(reasonHintRes)
|
||||||
}
|
}
|
||||||
|
|
||||||
AlertDialog.Builder(activity)
|
MaterialAlertDialogBuilder(activity)
|
||||||
.setTitle(titleRes)
|
.setTitle(titleRes)
|
||||||
.setView(layout)
|
.setView(layout)
|
||||||
.setPositiveButton(positiveRes) { _, _ ->
|
.setPositiveButton(positiveRes) { _, _ ->
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue