Compare commits

...

185 Commits

Author SHA1 Message Date
B. Petersen b8da4bc9c7 bump version 2018-11-20 18:56:38 +01:00
B. Petersen b83b2e9e29 Update messenger-backend submodule. 2018-11-20 18:50:28 +01:00
Angelo Fuchs 7f97bd0ea9 closes #114 when a user taps a picture or document (or the non-player segment of an audio message) he is asked if he wants to engage in a chat, just like he would if tapping a text. 2018-11-20 14:46:48 +01:00
Angelo Fuchs f0abb05e0a removed double filtering of messages. closes #128 - If there are new messages that only belong to one group the senders are now shown properly if the messages should be hidden. 2018-11-20 12:22:24 +01:00
Angelo Fuchs 7db7c5beeb proper handling of events in the background threads #128 2018-11-20 11:51:24 +01:00
Angelo Fuchs 50e22ddcc9 changing the display for multi-sender notifications for groups #128 2018-11-19 15:23:14 +01:00
Angelo Fuchs 85e2203244 notifications are now recreated once on startup of the app (e.G. after a restart of the phone). 2018-11-19 12:22:06 +01:00
Angelo Fuchs 7b2ef54922 notifications are now updated when a chat is seen #128 2018-11-19 11:22:27 +01:00
Angelo Fuchs 4043338f90 selecting chat background #50 for lower SDK versions. 2018-11-19 11:21:55 +01:00
Angelo Fuchs 269cb006c4 Update messenger-backend submodule. 2018-11-19 09:53:03 +01:00
B. Petersen 3daaa51d13 update issue-template 2018-11-17 23:51:52 +01:00
B. Petersen 099f3ad109 Update messenger-backend submodule. 2018-11-16 12:18:28 +01:00
B. Petersen 91ec15330b no interrupt-idle an activity starting, seems too much 2018-11-16 12:18:09 +01:00
Florian Haar 7a5f382315 Allow for customized Background image #50 2018-11-16 08:41:39 +01:00
B. Petersen 0cfc61fde9 handle DC_EVENT_ERROR_NETWORK, closes #129 2018-11-16 00:08:49 +01:00
B. Petersen 0a060fbb74 Update messenger-backend submodule. 2018-11-15 23:23:26 +01:00
B. Petersen 8a8034c33e tweak imap-thread 2018-11-15 16:38:33 +01:00
Angelo Fuchs 313e67fa57 multiple different senders in a chat are now distinguished #128 2018-11-15 12:13:41 +01:00
B. Petersen 0613b879fe remove dead code: BackoffReceiver, MmsBodyProvider 2018-11-15 02:26:36 +01:00
B. Petersen 155e748bd1 remove some verbose logging 2018-11-15 02:25:15 +01:00
B. Petersen 40e57b3286 remove header boilerplate 2018-11-15 02:11:44 +01:00
B. Petersen 90bf08845b remove dead code 2018-11-15 02:03:48 +01:00
B. Petersen 328132e041 adapt permissions 2018-11-15 01:55:53 +01:00
B. Petersen baec8d229d remove dead close: telephony 2018-11-15 01:32:57 +01:00
B. Petersen 740c7bd210 format 2018-11-15 01:17:40 +01:00
B. Petersen 032c38b3d7 remove dead code: sms 2018-11-15 01:15:15 +01:00
B. Petersen 2fbcf3f7f9 ignore warning that the apk is not searchable; this is a feature :) 2018-11-15 01:13:45 +01:00
B. Petersen 4a811d4f37 remove dead code: sms 2018-11-15 00:59:32 +01:00
B. Petersen 1f9ae91488 remove dead code: AccountAuthenticator 2018-11-15 00:49:51 +01:00
B. Petersen 3e76970257 remove dead code: verify identity 2018-11-15 00:00:46 +01:00
B. Petersen f022088ed9 remove dead code 2018-11-14 23:56:42 +01:00
B. Petersen e60c143a42 remove dead code: signal registration service 2018-11-14 23:44:01 +01:00
B. Petersen 5861ca14d6 remove no unused injections 2018-11-14 22:58:05 +01:00
B. Petersen 99f5948fc7 use DcContext.sendMsg() instead of MessageSender 2018-11-14 18:19:34 +01:00
B. Petersen c2e9ba3763 implement reply-from-notification, closes #126 2018-11-14 18:06:13 +01:00
B. Petersen 9743011f25 remove now unused greenrobot.eventbus 2018-11-14 17:56:07 +01:00
B. Petersen 7fb244b0be remove dead code 2018-11-14 17:36:47 +01:00
B. Petersen a79a33751b remove dead code 2018-11-14 17:28:27 +01:00
B. Petersen 1f4ccc2944 rework MessageRetrievalService into KeepAliveService 2018-11-14 17:12:59 +01:00
B. Petersen 7776939716 remove dead code: gcm receiver 2018-11-14 15:10:55 +01:00
B. Petersen d9810443fc remove dead code: SignalCommunicationModule and releated jobs and classes 2018-11-14 14:57:32 +01:00
B. Petersen 17d01b27f2 webrtc: remove dead code 2018-11-14 14:01:15 +01:00
B. Petersen fd2e034f13 webrtc: remove dependency from MessageNotifier 2018-11-14 14:01:01 +01:00
björn petersen 361e153605 Merge pull request #125 from deltachat/connect
connect permanently
2018-11-14 03:39:48 +01:00
B. Petersen 564915ab9f add out boot receiver 2018-11-14 03:37:55 +01:00
B. Petersen 69a887fe61 Update messenger-backend submodule. 2018-11-14 03:28:50 +01:00
B. Petersen e6020f9707 use permanent notification to keep threads alive 2018-11-14 03:28:25 +01:00
B. Petersen b2ee6320f4 remove header boilerplate 2018-11-14 00:12:51 +01:00
B. Petersen 98af653204 add network state receiver and call dc_maybe_network() on re-connect 2018-11-14 00:09:44 +01:00
B. Petersen 56527d3f3f remove signal's network state receiver 2018-11-13 23:55:03 +01:00
B. Petersen 1355f59a94 add a timer to restart smtp- and imap-threads if needed 2018-11-13 23:32:08 +01:00
B. Petersen c02df7a370 remove signals exponential backoff 2018-11-13 23:07:06 +01:00
B. Petersen 89e8e80665 adapt to new API, use lambda for threads 2018-11-13 21:40:03 +01:00
Angelo Fuchs 3ef1650b51 only produce a notification if something new happens, not if something gets noticed. #117 2018-11-13 14:39:27 +01:00
Angelo Fuchs 4739b8c165 in case ndk-build is done from gradle, this folder needs to be ignored. 2018-11-13 14:38:28 +01:00
B. Petersen ebdb5f382d Update messenger-backend submodule. 2018-11-13 00:20:09 +01:00
daniel.boehrs fa8e9cefd3 verified-icon not always visible in chat-titlebar #120 2018-11-09 15:23:32 +01:00
daniel.boehrs b459e9bd0e avatars from system contacts #55 2018-11-09 12:49:25 +01:00
Florian Haar a336ce3e2c Allow for customized Background image #50 2018-11-09 10:16:32 +01:00
Lars-Magnus Skog 986d86f82e Merge pull request #121 from JellyRollJunior/master
Fix error in README.md
2018-11-09 04:15:44 +01:00
Brandon Lin f202ca1eb2 Fix error in README.md
-removed double usage of "can"
2018-11-08 18:32:13 -08:00
Angelo Fuchs f1b2dd581a addendum #113. the notification event is running on the background thread now, the default for event handlers is the main thread, though. 2018-11-04 23:35:59 +02:00
Angelo Fuchs 5ed18c106c close #113. the notification event is running on the background thread now, the default for event handlers is the main thread, though. 2018-11-04 22:58:05 +02:00
Angelo Fuchs e051eecf48 closes #111 media gallery image selection now goes to the right image. 2018-11-04 21:42:40 +02:00
Angelo Fuchs 5fcf183215 don't display notifications for the currently active thread. closes #32 notifications are now completle 2018-11-04 16:58:18 +02:00
Angelo Fuchs df494a49a8 some cleanup, no functional change. 2018-11-04 14:16:53 +02:00
Angelo Fuchs 564b837d93 activating signalling (sound and vibration) for #32 2018-11-04 13:57:44 +02:00
Angelo Fuchs 8c9cd3dd3d having the proper icon for #32 notifications. 2018-11-02 17:10:35 +02:00
Florian Haar c290194c9a Allow for customized Background image #50 2018-11-02 13:39:03 +01:00
Florian Haar cf2bdefcee forward selected messages #74 2018-11-02 11:02:51 +01:00
Florian Haar 4f9c692dbd forward selected messages #74 2018-11-02 10:04:17 +01:00
daniel.boehrs dd67248066 avatars for contact / new chat view #55 2018-11-02 09:01:43 +01:00
Angelo Fuchs d4f1af7521 for #32 (notifications) the type of thread id in ConversationActivity is now int (not long). Where its too hard, I added a cast and a todo. 2018-11-01 21:22:13 +02:00
Angelo Fuchs df62bfe8de #32 grouping together the actions of marking messages as notified. 2018-11-01 21:22:13 +02:00
Angelo Fuchs b8929c181a added todos for future work. 2018-11-01 21:22:13 +02:00
Angelo Fuchs 9fa44b3e68 #32 notification stuff running in background thread so glide is satisfied. 2018-11-01 21:22:13 +02:00
daniel.boehrs 755d081c64 Adjust avatar fallback colors #55 2018-11-01 10:42:26 +01:00
daniel.boehrs b635384dd5 Make GroupCreateActivity aware of verified joins #92 2018-11-01 10:04:51 +01:00
daniel.boehrs 1fb07c9f80 unlocking does not work #112 2018-11-01 08:54:14 +01:00
Angelo Fuchs 5a9220356c notifications for new messages are displayed and hidden appropriately #32 2018-10-31 14:01:40 +02:00
Angelo Fuchs c8accec761 added convenience function when you already have a dc context 2018-10-31 14:01:40 +02:00
Angelo Fuchs cad5c5c185 generating slides from messages 2018-10-31 14:01:39 +02:00
Angelo Fuchs acaf836af9 DcMsg no longer requires the Recipient. 2018-10-31 14:01:39 +02:00
daniel.boehrs 5221b4c8fd Show qr and self reference on group edit #92 2018-10-30 16:19:18 +01:00
daniel.boehrs 5ee4320a6c Prepare ContactAccessor to load photos for #55 2018-10-30 14:02:26 +01:00
daniel.boehrs 92a0a83187 Rewrite profile image handling for #55 2018-10-30 12:16:02 +01:00
daniel.boehrs 76a8a724ff Adjust UI #55 2018-10-30 12:16:02 +01:00
B. Petersen d8ccf5ed6d add a function to get profile image of a contact 2018-10-30 11:21:55 +01:00
B. Petersen a2d6a00cd1 Update messenger-backend submodule. 2018-10-29 23:40:38 +01:00
Angelo Fuchs ffe69f7f4b Using DcEventDelegate instead of Object. 2018-10-29 23:01:57 +02:00
björn petersen 887cc3a1bb [WIP] Media gallery (#109) closes #78
* Update messenger-backend submodule.
* display a swipe able media gallery when one taps an image
* display a tiled gallery from chat-menu and from preview gallery
* changed some utility classes to handle the new situations
2018-10-29 20:55:49 +01:00
daniel.boehrs c192b719f5 show avatars for groups #55 2018-10-29 15:44:55 +01:00
daniel.boehrs ed0de74406 Adjust keyboard show / hide #92 2018-10-29 10:29:43 +01:00
B. Petersen ff1878511d show contact-avatar in deaddrop, tackles #95 2018-10-23 23:16:03 +02:00
B. Petersen a77cbee5f2 remove unused semi-transparency 2018-10-23 23:07:01 +02:00
B. Petersen e92fda0ca3 use plus-icon instead of pencil in chatlist, closes #107 2018-10-23 22:53:31 +02:00
B. Petersen a4c9e1699b improve 'no messages' hint on empty chats. 2018-10-23 21:51:14 +02:00
B. Petersen df87b64f66 upper-right align date in chatlist 2018-10-23 16:36:44 +02:00
B. Petersen b79e8e812d make status icons mutual exclusive 2018-10-23 16:24:19 +02:00
B. Petersen ec2deebda4 add space between columns in chatlist, closes #106 2018-10-23 16:09:09 +02:00
B. Petersen befbf84c59 remove unused thumbnail from chatlist 2018-10-23 14:30:08 +02:00
B. Petersen 7b205db200 do not show the date in bold on unread, too noisy. only show subject in bold and green unread counter. 2018-10-23 13:57:58 +02:00
B. Petersen e43c85b12b unify ripple color 2018-10-23 13:52:29 +02:00
B. Petersen 758c175b3d add horizontal border between chats in chatlist, tackles #106 2018-10-23 13:11:21 +02:00
B. Petersen fdceb0e080 draw verified-icon directly right of chat-title, closes #105 2018-10-23 12:00:56 +02:00
B. Petersen 3863ef91e1 comment 2018-10-23 09:51:35 +02:00
B. Petersen 6e07258fc7 make deaddrop-background compatible to selection-background 2018-10-23 07:04:15 +02:00
B. Petersen c07a0dedd6 bump version 2018-10-22 23:52:25 +02:00
B. Petersen e5b906184d do not draw buggy deaddrop background for now 2018-10-22 23:50:09 +02:00
B. Petersen 2dbd12403f implement archive/unarchive/delete/leave from chat-activity 2018-10-22 23:14:15 +02:00
daniel.boehrs 9906608956 fix group create crash #103 2018-10-22 19:08:35 +02:00
B. Petersen 5870f0cd02 implement group leaving 2018-10-22 18:09:58 +02:00
B. Petersen 3dc6ea1c85 cleanup chat-menu 2018-10-22 17:47:18 +02:00
B. Petersen e66ae137fe make 'Edit group' a first-class action, tackles #92 2018-10-22 17:06:00 +02:00
B. Petersen 4d32f5746c no special click-handler for ConversationUpdateItem 2018-10-22 16:32:26 +02:00
daniel.boehrs 6e5c6e3d4d Merge branch 'master' of https://github.com/deltachat/deltachat-android-ii 2018-10-22 16:23:54 +02:00
daniel.boehrs c459aa4476 set group image #92 2018-10-22 16:23:42 +02:00
B. Petersen bf4bcba78c remove RecipientModifiedListener from ConversationActivity and ConversationListActivity 2018-10-22 16:21:59 +02:00
B. Petersen ccb5e3285f Update messenger-backend submodule. 2018-10-22 16:12:34 +02:00
daniel.boehrs 5424d56801 edit groups #92 2018-10-22 15:20:24 +02:00
B. Petersen 5c15784f66 hide unused controls in contact-requests, tackles #95 2018-10-22 01:21:15 +02:00
B. Petersen 0abecd74c9 remove unused code 2018-10-22 00:56:42 +02:00
B. Petersen aa3df42f71 ask 'Chat with NAME?' on clicks on a contact request and offer several options, tackles #95. 2018-10-22 00:29:45 +02:00
B. Petersen cfe6e023cb handle msg_id and contact_id in chatlist-items 2018-10-21 23:57:00 +02:00
B. Petersen 6140b2aab4 add a function to get the msg_id from a chatlist-index 2018-10-21 23:55:09 +02:00
B. Petersen cc95e1fa1f show contact request in chatlist with different background 2018-10-21 23:04:58 +02:00
B. Petersen 643e8d80f7 typo 2018-10-21 15:02:12 +02:00
B. Petersen 84cc1c124a show correct title for contact requests 2018-10-21 15:01:33 +02:00
B. Petersen 22d8f3177f remove unused parameters on opening/creating chats 2018-10-21 14:43:44 +02:00
B. Petersen 471f4480ac remove now unused ConversationActivity.DISTRIBUTION_TYPE_EXTRA 2018-10-21 14:36:29 +02:00
B. Petersen bc387096f5 remove dependency from this.distributionType on draft saving 2018-10-21 14:30:41 +02:00
B. Petersen 93b5a345ea remove unused group-options 2018-10-21 14:22:59 +02:00
B. Petersen 50b18b7d65 remove now redundant ConversationActivity.ADDRESS_EXTRA 2018-10-21 14:15:55 +02:00
B. Petersen 004319db64 remove dependency to ConversationActivity.ADDRESS_EXTRA from ConversationFragment 2018-10-21 14:09:33 +02:00
B. Petersen 90b52cebf1 remove TIMING_EXTRA 2018-10-21 13:58:58 +02:00
B. Petersen f4a01a2bae re-add accidentially removed advanced-preference click-handler 2018-10-21 01:28:56 +02:00
B. Petersen 77ed15125d move invite/help to settings 2018-10-21 00:59:11 +02:00
B. Petersen 15ef0271fc add contact-request (aka deaddrop) menu entry, tackles #95 2018-10-21 00:02:19 +02:00
B. Petersen 1dd2ad04ba a click on a deaddrop-message opens a new chat, tackles #95 2018-10-20 23:52:54 +02:00
B. Petersen 0a259d2277 bump version 2018-10-19 23:06:47 +02:00
B. Petersen 9f6a7cbf00 make create groups work again, tackles #92 2018-10-19 23:03:06 +02:00
B. Petersen 5c6e84b21b bump version 2018-10-19 15:30:59 +02:00
B. Petersen 00f0f143af send voice messages as such 2018-10-19 15:29:40 +02:00
B. Petersen 7bcfec2367 send images, audio, documents 2018-10-19 15:07:15 +02:00
daniel.boehrs 17e5fe5a89 Verify icon layout broken #93 2018-10-19 10:11:26 +02:00
Florian Haar 4b8fef6918 Merge branch 'master' of https://github.com/deltachat/deltachat-android-ii 2018-10-19 09:03:08 +02:00
Florian Haar 44afb50c81 Allow for customized Background image #50 2018-10-19 09:01:47 +02:00
B. Petersen 39f14a4a9a basically send media with URIs 2018-10-19 01:40:27 +02:00
B. Petersen d015f567da bump version 2018-10-18 18:55:15 +02:00
B. Petersen d98174b45b remove unused directory from update script 2018-10-18 16:35:23 +02:00
daniel.boehrs db92bb274b prefill groups form with exstiting data #92 2018-10-18 16:13:27 +02:00
B. Petersen c8d889da04 Update messenger-backend submodule. 2018-10-18 16:11:29 +02:00
B. Petersen 6da2a9fc87 remove ndk-buid call from update, if needed it should be called explicitly 2018-10-18 16:07:26 +02:00
Florian Haar 39b64bd9aa Merge branch 'master' of https://github.com/deltachat/deltachat-android-ii 2018-10-18 10:56:46 +02:00
Florian Haar ca55e21eb2 show "first message may take a while" in new chats #62 2018-10-18 10:55:59 +02:00
daniel.boehrs bf85918ed2 add qr show+scan activities #79 and adjust UI 2018-10-18 10:53:21 +02:00
björn petersen b0adddebfa Merge pull request #91 from deltachat/qr-verify-79
add verify-contact activities
2018-10-17 23:36:39 +02:00
B. Petersen f27f0b4305 show secure-join-events on joiner side 2018-10-17 23:26:58 +02:00
B. Petersen c441c11601 start activity after QR scanning from ui thread 2018-10-17 19:10:23 +02:00
daniel.boehrs 77d7f545d4 add qr show+scan activities #79 2018-10-17 16:57:10 +02:00
Angelo Fuchs 7d4add1b5e introduced DcAttachment and introduced its use where applicable. 2018-10-17 15:20:39 +02:00
Angelo Fuchs e72f2b4cb6 for #78 setting the attachment state to done when its displayed. 2018-10-17 15:18:20 +02:00
B. Petersen 264765917f adapt to new api 2018-10-17 14:08:55 +02:00
B. Petersen 9b6dcf955f adapt name and return value of dc_msg_get_filebytes() wrapper function 2018-10-17 14:06:36 +02:00
B. Petersen 6027072d78 remove download button from AudioView 2018-10-17 02:15:38 +02:00
B. Petersen af5fb87c06 Update messenger-backend submodule. 2018-10-17 01:14:11 +02:00
B. Petersen 96c4fd6835 adapt to new api 2018-10-17 01:13:56 +02:00
B. Petersen a0b7d41a7a Update messenger-backend submodule. 2018-10-17 00:02:41 +02:00
B. Petersen 3cd732f089 adapt to new api 2018-10-17 00:02:26 +02:00
B. Petersen e299eb26c2 Update messenger-backend submodule. 2018-10-16 16:50:46 +02:00
B. Petersen 1038de2cc5 cleanup 2018-10-16 16:50:30 +02:00
Florian Haar f02380fd52 Adjust the CreateProfileActivity UI #87 2018-10-16 14:25:55 +02:00
daniel.boehrs a02574dbbb Allow for customized Background image #50 2018-10-16 13:58:24 +02:00
B. Petersen 35521f5dfe force software layer to allow larger items in ConversationList, closes #88 2018-10-16 10:39:30 +02:00
B. Petersen a1e6c14443 use different app name for X-Mailer header 2018-10-15 15:31:39 +02:00
Florian Haar 58ada319bb Merge branch 'master' of https://github.com/deltachat/deltachat-android-ii 2018-10-15 11:38:05 +02:00
Florian Haar 45bfab9fbd Adjust the CreateProfileActivity UI #87 2018-10-15 11:36:09 +02:00
B. Petersen e5d8a2bc28 update error indicator 2018-10-14 23:25:32 +02:00
B. Petersen 99b1e2ba43 harden getConfigInt() 2018-10-14 12:11:07 +02:00
B. Petersen 27d632f17c show sender names in groups, closes #85 2018-10-13 22:34:24 +02:00
B. Petersen fbd53b3767 make opened chat as being noticed, closes #66 2018-10-13 16:56:29 +02:00
B. Petersen 8f56d5872a adding SELF to the list of contacts so that one can easily create a self-chat 2018-10-13 15:33:34 +02:00
daniel.boehrs 0e75880c24 show "verified" icon in contact list and in chat title #80 2018-10-12 15:54:58 +02:00
B. Petersen 0e55a4ad5e Merge branch 'master' of https://github.com/deltachat/deltachat-android-ii 2018-10-12 13:56:11 +02:00
B. Petersen 6eed72a4d2 bump version 2018-10-12 13:56:08 +02:00
317 changed files with 3721 additions and 21756 deletions
+14 -38
View File
@@ -1,48 +1,24 @@
<!--
Please read the guidelines linked above, especially when you are a first time contributor. Remove this text and provide some basic informations below, if applicable. Remove template content which is not applicable.
This is a bug report forum, if you like to discuss a new feature or submit suggestions, please use the community forum at https://support.delta.chat
Please fill in as much as you can below (leaving out if not applicable is ok). This is a bug report and feature-tracking forum, if you like to discuss a new feature, please use the community forum at https://support.delta.chat.
-->
**Delta Chat version**
<!-- See settings dialog … -->
**Expected behavior**
<!-- What is the expected output? -->
**Actual behavior**
<!-- What do you see instead? -->
**Steps to reproduce the problem**
1.
2.
**Screen snapshots**
<!-- If applicable … -->
**Debug logs**
<details>
<summary>Logs</summary>
```
- Platform (android/blackberry/anbox):
- Device:
- Delta Chat Version:
- Expected behavior:
- Actual behavior:
- Steps to reproduce the problem:
- Screenshots:
- Logs:
<!--
If applicable, debug logs can be copied from within the Delta Chat app:
Open the _Settings_ menu -> _About_ -> _version number|Info_.
Debug logs can be copied from within the Delta Chat app with
Settings menu -> Advanced -> Debug log
Alternatively from the Android system log:
`adb logcat -v time -s DeltaChat`
` adb logcat -v time -s DeltaChat `
This log contains private data (e.g. mail address, provider information) which shall be removed or anonymised prior to posting.
Logs may contain private data
which shall be removed or anonymised prior to posting.
-->
```
</details>
+3
View File
@@ -27,3 +27,6 @@ jni/libspeex/.deps/
# ignore private scripts and directories, eg. local2github.prv.sh
*.prv*
# contains files for ndk-build when done from gradle.
.externalNativeBuild
+16 -103
View File
@@ -15,67 +15,22 @@
<uses-feature android:name="android.hardware.portrait" android:required="false"/>
<uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
<uses-permission android:name="android.permission.USE_FINGERPRINT"/>
<uses-permission android:name="org.thoughtcrime.securesms.ACCESS_SECRETS"/>
<uses-permission android:name="android.permission.READ_PROFILE"/>
<uses-permission android:name="android.permission.WRITE_PROFILE"/>
<uses-permission android:name="android.permission.BROADCAST_WAP_PUSH"
tools:ignore="ProtectedPermissions"/>
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.READ_CALL_STATE"/>
<!-- For sending/receiving events -->
<uses-permission android:name="android.permission.WRITE_CALENDAR"/>
<uses-permission android:name="android.permission.READ_CALENDAR"/>
<!-- Normal -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<!-- So we can add a TextSecure 'Account' -->
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS"/>
<!-- For conversation 'shortcuts' on the desktop -->
<uses-permission android:name="android.permission.INSTALL_SHORTCUT"/>
<!-- For fixing MMS -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<!-- Set image as wallpaper -->
<uses-permission android:name="android.permission.SET_WALLPAPER"/>
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.RAISED_THREAD_PRIORITY" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<application android:name=".ApplicationContext"
android:icon="@mipmap/ic_launcher_dev"
@@ -84,7 +39,8 @@
tools:replace="android:allowBackup"
android:allowBackup="false"
android:theme="@style/TextSecure.LightTheme"
android:largeHeap="true">
android:largeHeap="true"
tools:ignore="GoogleAppIndexingWarning">
<meta-data
android:name="com.google.android.geo.API_KEY"
@@ -96,12 +52,6 @@
<meta-data android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc" />
<activity android:name="org.thoughtcrime.securesms.WebRtcCallActivity"
android:excludeFromRecents="true"
android:screenOrientation="portrait"
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|screenSize|fontScale"
android:launchMode="singleTask"/>
<activity android:name=".InviteActivity"
android:theme="@style/TextSecure.HighlightTheme"
android:windowSoftInputMode="stateHidden"
@@ -192,7 +142,6 @@
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" />
<activity android:name=".GroupCreateActivity"
android:windowSoftInputMode="stateVisible"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".DatabaseUpgradeActivity"
@@ -231,9 +180,6 @@
android:label="@string/AndroidManifest__change_passphrase"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".VerifyIdentityActivity"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".ApplicationPreferencesActivity"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
@@ -300,6 +246,14 @@
android:windowSoftInputMode="stateVisible"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".QrScanActivity"
android:theme="@style/TextSecure.LightTheme"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".QrShowActivity"
android:theme="@style/TextSecure.LightTheme"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".ClearProfileAvatarActivity"
android:theme="@style/Theme.AppCompat.Dialog.Alert"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
@@ -324,24 +278,13 @@
android:theme="@style/TextSecure.LightNoActionBar"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<service android:enabled="true" android:name="org.thoughtcrime.securesms.service.WebRtcCallService"/>
<activity android:name=".preferences.ChatBackgroundActivity"
android:theme="@style/TextSecure.LightTheme"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<service android:enabled="true" android:exported="false" android:name=".service.KeyCachingService"/>
<service android:enabled="true" android:name=".service.MessageRetrievalService"/>
<service android:name=".service.AccountAuthenticatorService" android:exported="true">
<intent-filter>
<action android:name="android.accounts.AccountAuthenticator" />
</intent-filter>
<meta-data android:name="android.accounts.AccountAuthenticator" android:resource="@xml/authenticator" />
</service>
<service android:name=".service.ContactsSyncAdapterService" android:exported="true">
<intent-filter>
<action android:name="android.content.SyncAdapter"/>
</intent-filter>
<meta-data android:name="android.content.SyncAdapter" android:resource="@xml/syncadapter" />
<meta-data android:name="android.provider.CONTACTS_STRUCTURE" android:resource="@xml/contactsformat" />
</service>
<service android:name=".connect.KeepAliveService" android:enabled="true"/>
<service android:name=".service.DirectShareService"
android:permission="android.permission.BIND_CHOOSER_TARGET_SERVICE">
@@ -352,12 +295,7 @@
<service android:name=".service.GenericForegroundService"/>
<receiver android:name=".gcm.GcmBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="org.thoughtcrime.securesms" />
</intent-filter>
</receiver>
<receiver android:name=".connect.TimerReceiver" android:enabled="true"/>
<receiver android:name=".notifications.MarkReadReceiver"
android:enabled="true"
@@ -391,18 +329,11 @@
<receiver android:name=".service.ExpirationListener" />
<receiver android:name=".jobmanager.requirements.BackoffReceiver" />
<provider android:name=".providers.PartProvider"
android:grantUriPermissions="true"
android:exported="false"
android:authorities="${applicationId}.provider.securesms" />
<provider android:name=".providers.MmsBodyProvider"
android:grantUriPermissions="true"
android:exported="false"
android:authorities="${applicationId}.provider.securesms.mms" />
<provider android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
@@ -426,24 +357,6 @@
</intent-filter>
</receiver>
<receiver android:name=".service.DirectoryRefreshListener">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver android:name=".service.RotateSignedPreKeyListener">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver android:name=".service.PersistentConnectionBootListener">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<receiver android:name=".notifications.MessageNotifier$ReminderReceiver">
<intent-filter>
<action android:name="org.thoughtcrime.securesms.MessageNotifier.REMINDER_ACTION"/>
-34
View File
@@ -1,34 +0,0 @@
TextSecure provides encrypted text messages for Android.
Copyright 2011 Whisper Systems
This software has the follow third party dependencies:
Bouncy Castle 1.42
http://www.bouncycastle.org/
MIT License
Copyright (c) 2000 - 2011 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
ZXing
http://code.google.com/p/zxing/
Apache License 2.0
Copyright 2009 ZXing authors
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.
+1 -1
View File
@@ -14,7 +14,7 @@ For ready-to-use binaries, please go to https://delta.chat .
When checking out _deltachat-android-ii_, make sure also to check out the
subproject _deltachat-core_:
- When using Git, you can can do this initially by
- When using Git, you can do this initially by
`$ git clone --recursive https://github.com/deltachat/deltachat-android-ii`
or later by `git submodule update --init --recursive`. If you do this in your
home directory, this results in the folder `~/deltachat-android-ii` which is just fine.
+4 -6
View File
@@ -83,6 +83,8 @@ dependencies {
compile 'org.whispersystems:signal-service-android:2.7.6'
compile 'org.whispersystems:webrtc-android:M68'
compile 'com.journeyapps:zxing-android-embedded:3.4.0'
compile "me.leolin:ShortcutBadger:1.1.16"
compile 'se.emilsjolander:stickylistheaders:2.7.0'
compile 'com.jpardogo.materialtabstrip:library:1.0.9'
@@ -92,11 +94,9 @@ dependencies {
annotationProcessor 'com.github.bumptech.glide:compiler:4.5.0'
compile 'com.makeramen:roundedimageview:2.1.0'
compile 'com.pnikosis:materialish-progress:1.5'
compile 'org.greenrobot:eventbus:3.0.0'
compile 'pl.tajchert:waitingdots:0.1.0'
compile 'com.soundcloud.android:android-crop:0.9.10@aar'
compile 'com.melnykov:floatingactionbutton:1.3.0'
compile 'com.google.zxing:android-integration:3.1.0'
compile 'com.squareup.dagger:dagger:1.2.2'
annotationProcessor 'com.squareup.dagger:dagger-compiler:1.2.2'
compile 'mobi.upod:time-duration-picker:1.1.3'
@@ -183,9 +183,7 @@ dependencyVerification {
'com.github.chrisbanes:PhotoView:ed06775308da260e1fd86d1d3288988fcd3d80db24ce0d7c9fcfedc39e622292',
'com.github.bumptech.glide:glide:997de7ac95be6c944d3b8cbe13de11307736ea45451c1b09a6cec7c328ead59f',
'com.makeramen:roundedimageview:1f5a1865796b308c6cdd114acc6e78408b110f0a62fc63553278fbeacd489cd1',
'org.greenrobot:eventbus:180d4212467df06f2fbc9c8d8a2984533ac79c87769ad883bc421612f0b4e17c',
'com.soundcloud.android:android-crop:ffd4b973cf6e97f7d64118a0dc088df50e9066fd5634fe6911dd0c0c5d346177',
'com.google.zxing:android-integration:89e56aadf1164bd71e57949163c53abf90af368b51669c0d4a47a163335f95c4',
'com.squareup.dagger:dagger:789aca24537022e49f91fc6444078d9de8f1dd99e1bfb090f18491b186967883',
'com.amulyakhare:com.amulyakhare.textdrawable:54c92b5fba38cfd316a07e5a30528068f45ce8515a6890f1297df4c401af5dcb',
'com.google.zxing:core:b4d82452e7a6bf6ec2698904b332431717ed8f9a850224f295aec89de80f2259',
@@ -255,8 +253,8 @@ android {
}
defaultConfig {
versionCode 392
versionName "0.0.1"
versionCode 399
versionName "0.0.9"
applicationId "chat.delta.androidii"
minSdkVersion 14
-1
View File
@@ -927,7 +927,6 @@ messenger-backend/src/dc_strbuilder.c \
messenger-backend/src/dc_strencode.c \
messenger-backend/src/dc_token.c \
messenger-backend/src/dc_tools.c \
messenger-backend/src/dc_uudecode.c \
dc_wrapper.c
include $(BUILD_SHARED_LIBRARY)
+22 -54
View File
@@ -238,27 +238,27 @@ JNIEXPORT jint Java_com_b44t_messenger_DcContext_isConfigured(JNIEnv *env, jobje
}
JNIEXPORT void Java_com_b44t_messenger_DcContext_performJobs(JNIEnv *env, jobject obj)
JNIEXPORT void Java_com_b44t_messenger_DcContext_performImapJobs(JNIEnv *env, jobject obj)
{
dc_perform_imap_jobs(get_dc_context(env, obj));
}
JNIEXPORT void Java_com_b44t_messenger_DcContext_idle(JNIEnv *env, jobject obj)
JNIEXPORT void Java_com_b44t_messenger_DcContext_performImapIdle(JNIEnv *env, jobject obj)
{
dc_perform_imap_idle(get_dc_context(env, obj));
}
JNIEXPORT void Java_com_b44t_messenger_DcContext_interruptIdle(JNIEnv *env, jobject obj)
JNIEXPORT void Java_com_b44t_messenger_DcContext_performImapFetch(JNIEnv *env, jobject obj)
{
dc_interrupt_imap_idle(get_dc_context(env, obj));
dc_perform_imap_fetch(get_dc_context(env, obj));
}
JNIEXPORT void Java_com_b44t_messenger_DcContext_fetch(JNIEnv *env, jobject obj)
JNIEXPORT void Java_com_b44t_messenger_DcContext_interruptImapIdle(JNIEnv *env, jobject obj)
{
dc_perform_imap_fetch(get_dc_context(env, obj));
dc_interrupt_imap_idle(get_dc_context(env, obj));
}
@@ -274,9 +274,9 @@ JNIEXPORT void Java_com_b44t_messenger_DcContext_performSmtpIdle(JNIEnv *env, jo
}
JNIEXPORT void Java_com_b44t_messenger_DcContext_interruptSmtpIdle(JNIEnv *env, jobject obj)
JNIEXPORT void Java_com_b44t_messenger_DcContext_maybeNetwork(JNIEnv *env, jobject obj)
{
dc_interrupt_smtp_idle(get_dc_context(env, obj));
dc_maybe_network(get_dc_context(env, obj));
}
@@ -547,34 +547,6 @@ JNIEXPORT jint Java_com_b44t_messenger_DcContext_sendTextMsg(JNIEnv *env, jobjec
}
JNIEXPORT jint Java_com_b44t_messenger_DcContext_sendVcardMsg(JNIEnv *env, jobject obj, jint chat_id, jint contact_id)
{
return dc_send_vcard_msg(get_dc_context(env, obj), chat_id, contact_id);
}
JNIEXPORT jint Java_com_b44t_messenger_DcContext_sendMediaMsg(JNIEnv *env, jobject obj, jint chat_id, jint type, jstring file, jstring mime, jint w, jint h, jint ms, jstring author, jstring trackname)
{
jint msg_id = 0;
CHAR_REF(file);
CHAR_REF(mime);
CHAR_REF(author);
CHAR_REF(trackname);
switch (type) {
case DC_MSG_IMAGE: msg_id = (jint)dc_send_image_msg(get_dc_context(env, obj), chat_id, filePtr, mimePtr, w, h); break;
case DC_MSG_VIDEO: msg_id = (jint)dc_send_video_msg(get_dc_context(env, obj), chat_id, filePtr, mimePtr, w, h, ms); break;
case DC_MSG_VOICE: msg_id = (jint)dc_send_voice_msg(get_dc_context(env, obj), chat_id, filePtr, mimePtr, ms); break;
case DC_MSG_AUDIO: msg_id = (jint)dc_send_audio_msg(get_dc_context(env, obj), chat_id, filePtr, mimePtr, ms, authorPtr, tracknamePtr); break;
default: msg_id = (jint)dc_send_file_msg (get_dc_context(env, obj), chat_id, filePtr, mimePtr); break;
}
CHAR_UNREF(trackname);
CHAR_UNREF(author);
CHAR_UNREF(mime);
CHAR_UNREF(file);
return msg_id;
}
/* DcContext - handle config */
JNIEXPORT void Java_com_b44t_messenger_DcContext_setConfig(JNIEnv *env, jobject obj, jstring key, jstring value /*may be NULL*/)
@@ -754,6 +726,12 @@ JNIEXPORT jlong Java_com_b44t_messenger_DcChatlist_getChatCPtr(JNIEnv *env, jobj
}
JNIEXPORT jint Java_com_b44t_messenger_DcChatlist_getMsgId(JNIEnv *env, jobject obj, jint index)
{
return dc_chatlist_get_msg_id(get_dc_chatlist(env, obj), index);
}
JNIEXPORT jlong Java_com_b44t_messenger_DcChatlist_getMsgCPtr(JNIEnv *env, jobject obj, jint index)
{
dc_chatlist_t* chatlist = get_dc_chatlist(env, obj);
@@ -1010,9 +988,9 @@ JNIEXPORT void Java_com_b44t_messenger_DcMsg_lateFilingMediaSize(JNIEnv *env, jo
}
JNIEXPORT jint Java_com_b44t_messenger_DcMsg_getBytes(JNIEnv *env, jobject obj)
JNIEXPORT jlong Java_com_b44t_messenger_DcMsg_getFilebytes(JNIEnv *env, jobject obj)
{
return (jint)dc_msg_get_filebytes(get_dc_msg(env, obj));
return (jlong)dc_msg_get_filebytes(get_dc_msg(env, obj));
}
@@ -1064,12 +1042,6 @@ JNIEXPORT jstring Java_com_b44t_messenger_DcMsg_getFilename(JNIEnv *env, jobject
}
JNIEXPORT jlong Java_com_b44t_messenger_DcMsg_getMediainfoCPtr(JNIEnv *env, jobject obj)
{
return (jlong)dc_msg_get_mediainfo(get_dc_msg(env, obj));
}
JNIEXPORT jboolean Java_com_b44t_messenger_DcMsg_isForwarded(JNIEnv *env, jobject obj)
{
return dc_msg_is_forwarded(get_dc_msg(env, obj))!=0;
@@ -1133,16 +1105,6 @@ JNIEXPORT void Java_com_b44t_messenger_DcMsg_setDuration(JNIEnv *env, jobject ob
}
JNIEXPORT void Java_com_b44t_messenger_DcMsg_setMediainfo(JNIEnv *env, jobject obj, jstring author, jstring trackname)
{
CHAR_REF(author);
CHAR_REF(trackname);
dc_msg_set_mediainfo(get_dc_msg(env, obj), authorPtr, tracknamePtr);
CHAR_UNREF(trackname);
CHAR_UNREF(author);
}
/*******************************************************************************
* DcContact
******************************************************************************/
@@ -1219,6 +1181,12 @@ JNIEXPORT jstring Java_com_b44t_messenger_DcContact_getNameNAddr(JNIEnv *env, jo
}
JNIEXPORT jstring Java_com_b44t_messenger_DcContact_getProfileImage(JNIEnv *env, jobject obj)
{
return JSTRING_NEW("");
}
JNIEXPORT jboolean Java_com_b44t_messenger_DcContact_isBlocked(JNIEnv *env, jobject obj)
{
return (jboolean)(dc_contact_is_blocked(get_dc_contact(env, obj))!=0);
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 B

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 727 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 750 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 532 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 B

After

Width:  |  Height:  |  Size: 351 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 B

After

Width:  |  Height:  |  Size: 368 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 822 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 B

After

Width:  |  Height:  |  Size: 387 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/ic_help_white_24dp"
android:tint="?attr/pref_icon_tint"/>
+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/ic_mood_white_24dp"
android:tint="?attr/pref_icon_tint"/>
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#8000" />
<padding
android:left="1dp"
android:right="1dp"
android:bottom="1dp"
android:top="1dp" />
<corners android:radius="8dp" />
</shape>
+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.journeyapps.barcodescanner.CompoundBarcodeView
android:id="@+id/zxing_barcode_scanner"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true" />
</RelativeLayout>
+26
View File
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="@+id/qrImage"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:contentDescription="@string/qr_scan_activity__title" />
<TextView
android:id="@+id/qrShowHint"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:text=""
android:textAlignment="center"
android:textAppearance="@style/TextAppearance.AppCompat"
android:textSize="16sp" />
</LinearLayout>
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/preview"
android:scaleType="centerCrop"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="bottom">
<Button
android:id="@+id/set_default_button"
android:theme="@style/Button.Primary"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:text="Set default" />
<Button
android:id="@+id/from_gallery_button"
android:theme="@style/Button.Primary"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:text="From gallery" />
</LinearLayout>
</FrameLayout>
-26
View File
@@ -1,26 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<ImageView
android:id="@+id/sms_failed_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_error"
android:visibility="gone"
android:tint="@color/core_red"
tools:visibility="visible"
android:contentDescription="@string/conversation_item_sent__send_failed_indicator_description" />
<ImageView
android:id="@+id/pending_approval_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_error"
android:tint="@color/core_light_60"
android:visibility="gone"
tools:visibility="visible"
android:layout_gravity="center_vertical"
android:contentDescription="@string/conversation_item_sent__pending_approval_description" />
</merge>
-10
View File
@@ -45,16 +45,6 @@
android:scaleType="centerInside"
android:contentDescription="@string/audio_view__pause_accessibility_description"/>
<ImageView android:id="@+id/download"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:clickable="true"
android:visibility="gone"
android:background="@drawable/circle_touch_highlight_background"
android:src="@drawable/ic_download_circle_fill_white_48dp"
android:contentDescription="@string/audio_view__download_accessibility_description"/>
</org.thoughtcrime.securesms.components.AnimatingToggle>
<SeekBar android:id="@+id/seek"
+10 -9
View File
@@ -32,15 +32,16 @@
android:orientation="vertical">
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
android:singleLine="true"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="16sp"
tools:text="Frieeeeeeedrich Nieeeeeeeeeetzsche" />
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
android:drawablePadding="5dp"
android:ellipsize="marquee"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="16sp"
tools:text="Frieeeeeeedrich Nieeeeeeeeeetzsche" />
<LinearLayout android:id="@+id/number_container"
android:orientation="horizontal"
+78 -83
View File
@@ -1,98 +1,93 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent" android:layout_width="match_parent">
<org.thoughtcrime.securesms.components.InputAwareLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<org.thoughtcrime.securesms.components.InputAwareLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<org.thoughtcrime.securesms.components.camera.QuickAttachmentDrawer
android:id="@+id/quick_attachment_drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<org.thoughtcrime.securesms.components.camera.QuickAttachmentDrawer
android:id="@+id/quick_attachment_drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout android:id="@+id/conversation_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="?attr/actionBarSize"
android:gravity="bottom"
android:clipToPadding="false"
android:clipChildren="false">
<LinearLayout android:id="@+id/conversation_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="?attr/actionBarSize"
android:gravity="bottom"
android:clipToPadding="false"
android:clipChildren="false">
<ViewStub android:id="@+id/group_share_profile_view_stub"
android:layout="@layout/conversation_activity_group_share_profile_stub"
android:inflatedId="@+id/group_share_profile_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<ViewStub android:id="@+id/group_share_profile_view_stub"
android:layout="@layout/conversation_activity_group_share_profile_stub"
android:inflatedId="@+id/group_share_profile_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<ViewStub android:id="@+id/unverified_banner_stub"
android:layout="@layout/conversation_activity_unverified_banner_stub"
android:inflatedId="@+id/unverified_banner"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<ViewStub android:id="@+id/unverified_banner_stub"
android:layout="@layout/conversation_activity_unverified_banner_stub"
android:inflatedId="@+id/unverified_banner"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<ViewStub
android:id="@+id/reminder_stub"
android:layout="@layout/conversation_activity_reminderview_stub"
android:inflatedId="@+id/reminder"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<ViewStub
android:id="@+id/reminder_stub"
android:layout="@layout/conversation_activity_reminderview_stub"
android:inflatedId="@+id/reminder"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<FrameLayout android:id="@+id/fragment_content"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<FrameLayout android:id="@+id/fragment_content"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<ViewStub
android:id="@+id/attachment_editor_stub"
android:inflatedId="@+id/attachment_editor"
android:layout="@layout/conversation_activity_attachment_editor_stub"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<ViewStub
android:id="@+id/attachment_editor_stub"
android:inflatedId="@+id/attachment_editor"
android:layout="@layout/conversation_activity_attachment_editor_stub"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<include layout="@layout/conversation_input_panel"/>
<include layout="@layout/conversation_input_panel"/>
<Button android:id="@+id/register_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="20dp"
android:text="@string/conversation_activity__enable_signal_messages"
android:visibility="gone"/>
<Button android:id="@+id/register_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="20dp"
android:text="@string/conversation_activity__enable_signal_messages"
android:visibility="gone"/>
<Button android:id="@+id/make_default_sms_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="20dp"
android:text="@string/conversation_activity__enable_signal_for_sms"
android:visibility="gone"/>
<Button android:id="@+id/unblock_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="20dp"
android:text="@string/ConversationActivity_unblock"
android:visibility="gone"/>
<Button android:id="@+id/make_default_sms_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="20dp"
android:text="@string/conversation_activity__enable_signal_for_sms"
android:visibility="gone"/>
<TextView android:id="@+id/space_left"
android:paddingLeft="5dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:background="?android:windowBackground"
android:text="160/160 (1)" />
<TextView android:id="@+id/space_left"
android:paddingLeft="5dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:background="?android:windowBackground"
android:text="160/160 (1)" />
<ViewStub
android:id="@+id/emoji_drawer_stub"
android:layout="@layout/conversation_activity_emojidrawer_stub"
android:inflatedId="@+id/emoji_drawer"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<ViewStub
android:id="@+id/emoji_drawer_stub"
android:layout="@layout/conversation_activity_emojidrawer_stub"
android:inflatedId="@+id/emoji_drawer"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</org.thoughtcrime.securesms.components.camera.QuickAttachmentDrawer>
</org.thoughtcrime.securesms.components.InputAwareLayout>
</LinearLayout>
</org.thoughtcrime.securesms.components.camera.QuickAttachmentDrawer>
</org.thoughtcrime.securesms.components.InputAwareLayout>
</RelativeLayout>
+11 -1
View File
@@ -2,7 +2,7 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/conversation_container"
android:id="@+id/conversation_container"
android:layout_width="fill_parent"
android:layout_height="match_parent">
@@ -34,6 +34,16 @@
android:visibility="gone"
tools:text="March 1, 2015" />
<TextView
android:id="@+id/no_messages_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="visible"
style="@style/NoMessagesTextView"
tools:text="@string/ConversationActivity_NoMessagesHint"
/>
<View android:id="@+id/compose_divider"
android:layout_width="match_parent"
android:layout_height="2dp"
+2 -1
View File
@@ -14,7 +14,8 @@
android:paddingTop="6dp"
android:paddingBottom="6dp"
android:clipChildren="false"
android:clipToPadding="false">
android:clipToPadding="false"
android:background="?attr/colorBackgroundFloating">
<FrameLayout
android:layout_width="0dp"
-22
View File
@@ -86,20 +86,6 @@
tools:visibility="visible"
tools:text="+14152222222"/>
<TextView
android:id="@+id/group_message_sender_profile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="4sp"
android:paddingLeft="4sp"
style="@style/Signal.Text.Preview"
android:fontFamily="sans-serif-regular"
android:textColor="?conversation_item_received_text_primary_color"
android:textStyle="italic"
android:maxLines="1"
android:ellipsize="end"
tools:text="~Clement Duval"/>
</LinearLayout>
<org.thoughtcrime.securesms.components.QuoteView
@@ -180,13 +166,5 @@
</LinearLayout>
<org.thoughtcrime.securesms.components.AlertView
android:id="@+id/indicators_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:orientation="vertical"
android:gravity="center_vertical"/>
</RelativeLayout>
</org.thoughtcrime.securesms.ConversationItem>
+4 -1
View File
@@ -133,7 +133,10 @@
</LinearLayout>
<org.thoughtcrime.securesms.components.AlertView
<!-- the following view is only left because it is used as a reference for positioning above.
removing would require some re-layouting, it's just not done yet.-->
<View
android:visibility="gone"
android:id="@+id/indicators_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+1 -1
View File
@@ -73,7 +73,7 @@
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
app:backgroundTint="@color/signal_primary"
android:src="@drawable/ic_create_white_24dp"
android:src="@drawable/ic_add_white_24dp"
android:focusable="true"
android:contentDescription="@string/conversation_list_fragment__fab_content_description"/>
+99 -117
View File
@@ -8,9 +8,7 @@
android:focusable="true"
android:nextFocusRight="@+id/fab"
android:nextFocusLeft="@+id/container"
android:layout_height="72dp"
android:paddingLeft="16dp"
android:paddingRight="16dp">
android:layout_height="72dp">
<org.thoughtcrime.securesms.components.AvatarImageView
android:id="@+id/contact_photo_image"
@@ -23,140 +21,124 @@
android:cropToPadding="true"
tools:src="@drawable/ic_contact_picture"
android:contentDescription="@string/conversation_list_item_view__contact_photo_image"
android:layout_marginRight="12dp"
android:layout_marginEnd="12dp" />
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp" />
<RelativeLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:layout_marginStart="4dp"
android:layout_centerVertical="true"
android:layout_toRightOf="@id/contact_photo_image"
android:layout_toEndOf="@id/contact_photo_image"
android:weightSum="1"
android:orientation="horizontal">
<LinearLayout
android:orientation="horizontal"
android:gravity="center_vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toRightOf="@id/contact_photo_image"
android:layout_toEndOf="@id/contact_photo_image">
<org.thoughtcrime.securesms.components.FromTextView
android:id="@+id/from"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_toLeftOf="@+id/thumbnail"
android:layout_toStartOf="@+id/thumbnail"
style="@style/Signal.Text.Body"
android:fontFamily="sans-serif-medium"
android:textColor="?attr/conversation_list_item_contact_color"
android:maxLines="1"
tools:text="Jules Bonnot"
android:ellipsize="end"
android:layout_marginBottom="2dp"
android:drawablePadding="5dp"/>
<LinearLayout
android:orientation="vertical"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="wrap_content">
<org.thoughtcrime.securesms.components.AlertView
android:id="@+id/indicators_parent"
android:layout_width="18dp"
android:layout_height="18dp"
android:paddingTop="2dp"
android:layout_marginRight="2dp"
android:layout_marginEnd="2dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@id/from"
app:useSmallIcon="true"
android:visibility="gone"
tools:visibility="visible"/>
<LinearLayout
android:id="@+id/from"
android:orientation="horizontal"
android:layout_marginBottom="2dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
<ImageView
android:id="@+id/group_indicator"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_gravity="center_vertical"
android:src="@drawable/ic_group_white_24dp"
android:visibility="gone"
android:layout_marginTop="1dp"
android:layout_marginRight="5dp"
android:layout_marginEnd="5dp" />
<org.thoughtcrime.securesms.components.FromTextView
android:id="@+id/from_text"
style="@style/Signal.Text.Body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawablePadding="5dp"
android:ellipsize="end"
android:fontFamily="sans-serif-medium"
android:maxLines="1"
android:textColor="?attr/conversation_list_item_contact_color"
tools:text="Jules Bonnot" />
</LinearLayout>
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
android:id="@+id/subject"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/from"
android:layout_toRightOf="@id/indicators_parent"
android:layout_toEndOf="@id/indicators_parent"
android:layout_toLeftOf="@+id/status"
android:layout_toStartOf="@+id/status"
android:paddingRight="1dp"
style="@style/Signal.Text.Preview"
android:textColor="?attr/conversation_list_item_subject_color"
android:maxLines="1"
tools:text="Wheels arrive at 3pm flat. This is a somewhat longer message."
android:ellipsize="end" />
<org.thoughtcrime.securesms.components.ThumbnailView
android:id="@+id/thumbnail"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center_horizontal"
android:layout_marginRight="5dp"
android:layout_marginLeft="5dp"
android:layout_toLeftOf="@+id/date"
android:layout_toStartOf="@+id/date"
android:layout_alignParentTop="true"
android:layout_marginTop="5dp"
android:contentDescription="@string/conversation_activity__attachment_thumbnail"
android:visibility="gone"
tools:src="@drawable/ic_video_light"
tools:visibility="visible" />
</LinearLayout>
<TextView android:id="@id/date"
android:layout_marginLeft="3dp"
android:layout_marginStart="3dp"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_alignBaseline="@+id/from"
android:layout_above="@id/subject"
style="@style/Signal.Text.Caption"
android:textColor="?attr/conversation_list_item_date_color"
android:textAllCaps="true"
tools:text="30 mins"
android:singleLine="true"/>
<LinearLayout
android:orientation="vertical"
android:gravity="end"
android:layout_marginLeft="24dp"
android:layout_marginStart="24dp"
android:layout_marginRight="12dp"
android:layout_marginEnd="12dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView android:id="@+id/archived"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/date"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_alignBaseline="@id/subject"
android:layout_marginLeft="5dp"
android:layout_marginStart="5dp"
android:paddingLeft="6dp"
android:paddingRight="6dp"
android:paddingTop="2dp"
android:paddingBottom="2dp"
style="@style/Signal.Text.Caption"
android:text="@string/conversation_list_item_view__archived"
android:textColor="@color/core_white"
android:textAllCaps="true"
android:background="@drawable/archived_indicator_background" />
<TextView android:id="@id/date"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
style="@style/Signal.Text.Caption"
android:textColor="?attr/conversation_list_item_date_color"
android:textAllCaps="true"
tools:text="30 mins"
android:singleLine="true"/>
<LinearLayout
android:orientation="horizontal"
android:minHeight="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<FrameLayout android:id="@+id/status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_below="@id/date"
android:layout_toLeftOf="@id/archived"
android:layout_toStartOf="@id/archived"
android:layout_alignWithParentIfMissing="true">
<TextView android:id="@+id/archived"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="6dp"
android:paddingRight="6dp"
android:paddingTop="2dp"
android:paddingBottom="2dp"
style="@style/Signal.Text.Caption"
android:text="@string/conversation_list_item_view__archived"
android:textColor="@color/core_white"
android:textAllCaps="true"
android:background="@drawable/archived_indicator_background" />
<org.thoughtcrime.securesms.components.DeliveryStatusView
android:id="@+id/delivery_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
app:iconColor="?attr/conversation_list_item_delivery_icon_color"/>
<org.thoughtcrime.securesms.components.DeliveryStatusView
android:id="@+id/delivery_status"
android:layout_marginTop="6dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:iconColor="?attr/conversation_list_item_delivery_icon_color"/>
<ImageView android:id="@+id/unread_indicator"
android:layout_width="24dp"
android:layout_height="24dp"/>
<ImageView android:id="@+id/unread_indicator"
android:layout_width="24dp"
android:layout_height="24dp"/>
</LinearLayout>
</FrameLayout>
</LinearLayout>
</RelativeLayout>
</LinearLayout>
<View android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_alignParentBottom="true"
android:background="@drawable/attachment_selector_shadow"/>
</org.thoughtcrime.securesms.ConversationListItem>
+28 -49
View File
@@ -39,59 +39,38 @@
tools:src="@drawable/ic_contact_picture"
android:contentDescription="@string/conversation_list_item_view__contact_photo_image"/>
<RelativeLayout android:id="@+id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/contact_photo_image"
android:layout_toEndOf="@id/contact_photo_image"
android:layout_centerVertical="true">
<LinearLayout
android:orientation="vertical"
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toEndOf="@id/contact_photo_image"
android:layout_toRightOf="@id/contact_photo_image">
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:ellipsize="end"
android:textSize="18dp"
android:transitionName="recipient_name"
android:drawablePadding="5dp"
android:gravity="center_vertical"
android:layout_gravity="center_vertical"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
style="@style/TextSecure.TitleTextStyle"
tools:ignore="UnusedAttribute"/>
<ImageView android:id="@+id/verified_indicator"
android:src="@drawable/ic_check_circle_white_18dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="3dp"
android:layout_marginEnd="3dp"
android:layout_gravity="bottom"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@id/title"
android:alpha="0.7"
android:visibility="gone"/>
android:id="@+id/title"
style="@style/TextSecure.TitleTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawablePadding="5dp"
android:ellipsize="end"
android:maxLines="1"
android:textSize="18dp"
android:transitionName="recipient_name"
tools:text="Jules Bonnot" />
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
android:id="@+id/subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:ellipsize="end"
android:layout_gravity="center_vertical|start"
android:gravity="center_vertical"
android:layout_toRightOf="@id/verified_indicator"
android:layout_toEndOf="@id/verified_indicator"
android:layout_below="@id/title"
android:textDirection="ltr"
android:textSize="13dp"
tools:text="(123) 123-1234"
style="@style/TextSecure.SubtitleTextStyle"/>
android:id="@+id/subtitle"
style="@style/TextSecure.SubtitleTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:textDirection="ltr"
android:textSize="13dp"
tools:text="(123) 123-1234" />
</RelativeLayout>
</LinearLayout>
</org.thoughtcrime.securesms.ConversationTitleView>
+2 -1
View File
@@ -13,6 +13,7 @@
android:horizontalSpacing="0dp"
android:verticalSpacing="0dp"
android:numColumns="auto_fit"
android:gravity="center"/>
android:gravity="center"
android:background="?emoji_tab_strip_background"/>
</FrameLayout>
+41 -19
View File
@@ -68,25 +68,47 @@
</RelativeLayout>
<com.dd.CircularProgressButton
android:id="@+id/add_member_button"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:background="@color/signal_primary"
android:layout_marginStart="15dp"
android:layout_marginLeft="15dp"
android:layout_marginBottom="15dp"
android:paddingEnd="12dp"
android:paddingStart="12dp"
android:textColor="@color/white"
app:cpb_colorIndicator="@color/white"
app:cpb_colorProgress="@color/textsecure_primary"
app:cpb_cornerRadius="20dp"
app:cpb_selectorIdle="@drawable/progress_button_state"
app:cpb_textIdle="@string/recipients_panel__add_members"
app:layout_constraintBottom_toTopOf="@id/skip_button_bottom_spacer"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.dd.CircularProgressButton
android:id="@+id/add_member_button"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:background="@color/signal_primary"
android:layout_marginStart="15dp"
android:layout_marginLeft="15dp"
android:layout_marginBottom="15dp"
android:paddingEnd="12dp"
android:paddingStart="12dp"
android:textColor="@color/white"
app:cpb_colorIndicator="@color/white"
app:cpb_colorProgress="@color/textsecure_primary"
app:cpb_cornerRadius="20dp"
app:cpb_selectorIdle="@drawable/progress_button_state"
app:cpb_textIdle="@string/recipients_panel__add_members"/>
<com.dd.CircularProgressButton
android:id="@+id/verify_button"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:background="@color/signal_primary"
android:layout_marginStart="15dp"
android:layout_marginLeft="15dp"
android:layout_marginBottom="15dp"
android:paddingEnd="12dp"
android:paddingStart="12dp"
android:textColor="@color/white"
app:cpb_colorIndicator="@color/white"
app:cpb_colorProgress="@color/textsecure_primary"
app:cpb_cornerRadius="20dp"
app:cpb_selectorIdle="@drawable/progress_button_state"
android:visibility="gone"
app:cpb_textIdle="@string/qr_show_activity__title"/>
</LinearLayout>
<ListView android:id="@+id/selected_contacts_list"
android:layout_width="match_parent"
+59 -72
View File
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout android:layout_width="match_parent"
<FrameLayout xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
@@ -23,42 +24,39 @@
android:layout_height="64dp"
android:transitionName="avatar"/>
<org.thoughtcrime.securesms.components.emoji.EmojiEditText
android:id="@+id/name"
android:hint="@string/profile_create_activity__your_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:layout_marginLeft="10dp"
android:inputType="textCapWords"/>
<android.support.design.widget.TextInputLayout
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp">
<org.thoughtcrime.securesms.components.emoji.EmojiToggle
android:id="@+id/emoji_toggle"
android:layout_width="37dp"
android:layout_height="37dp"
android:layout_gravity="center_vertical"
android:background="@drawable/touch_highlight_background"
android:contentDescription="@string/conversation_activity__emoji_toggle_description" />
<android.support.design.widget.TextInputEditText
android:id="@+id/name_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/profile_create_activity__your_name"
android:inputType="textCapWords" />
</android.support.design.widget.TextInputLayout>
</LinearLayout>
<android.support.design.widget.TextInputLayout
android:id="@+id/status"
android:layout_marginTop="4dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
<android.support.design.widget.TextInputLayout
android:id="@+id/status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="16dp">
<android.support.design.widget.TextInputEditText
android:id="@+id/status_text"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.TextInputEditText
android:id="@+id/status_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/default_status_hint"
android:inputType="text" />
</android.support.design.widget.TextInputLayout>
android:layout_height="wrap_content"
android:gravity="top|left"
android:hint="@string/default_status_hint"
android:inputType="textMultiLine"
android:maxLines="3" />
</android.support.design.widget.TextInputLayout>
<LinearLayout android:id="@+id/information_link_container"
android:clickable="true"
@@ -78,16 +76,17 @@
android:src="@drawable/ic_info_white_18dp"
android:tint="#73B7F0"/>
<TextView style="@style/Registration.Description"
android:id="@+id/information_label"
android:clickable="true"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="3dp"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:textColor="#73B7F0"
android:text="@string/profile_create_activity__who_can_see_this_information"/>
<TextView
android:id="@+id/information_label"
style="@style/Registration.Description"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_marginLeft="3dp"
android:clickable="true"
android:gravity="center_vertical"
android:text="@string/profile_create_activity__who_can_see_this_information"
android:textColor="#73B7F0" />
</LinearLayout>
@@ -98,31 +97,18 @@
android:clipChildren="false"
android:clipToPadding="false">
<com.dd.CircularProgressButton
android:id="@+id/finish_button"
app:cpb_textIdle="@string/profile_create_activity__finish"
app:cpb_selectorIdle="@drawable/progress_button_state"
app:cpb_colorIndicator="@color/white"
app:cpb_colorProgress="@color/textsecure_primary"
app:cpb_cornerRadius="50dp"
android:textAllCaps="true"
android:background="@color/signal_primary"
android:textColor="@color/white"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginBottom="20dp"
android:layout_gravity="center_horizontal"/>
<TextView android:id="@+id/password_account_settings_button"
android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:layout_marginBottom="20dp"
android:textColor="@color/gray50"
android:text="@string/profile_create_activity__password_account"/>
<TextView
android:id="@+id/password_account_settings_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="20dp"
android:layout_marginTop="0dp"
android:text="@string/profile_create_activity__password_account"
android:textColor="#73B7F0"
android:textSize="16sp"
android:textStyle="normal"
android:typeface="sans" />
<org.thoughtcrime.securesms.components.emoji.EmojiDrawer
xmlns:android="http://schemas.android.com/apk/res/android"
@@ -135,10 +121,11 @@
</org.thoughtcrime.securesms.components.InputAwareLayout>
<View android:id="@+id/reveal"
android:background="@color/textsecure_primary"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible"/>
<View
android:id="@+id/reveal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/textsecure_primary"
android:visibility="invisible" />
</FrameLayout>
+3 -3
View File
@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="@string/conversation__menu_view_profile"
android:id="@+id/menu_conversation_settings"/>
<item android:title="@string/conversation__menu_add_attachment"
android:id="@+id/menu_add_attachment" />
<item android:title="@string/conversation__menu_view_all_media"
android:id="@+id/menu_view_media" />
<item android:title="@string/conversation__menu_conversation_settings"
android:id="@+id/menu_conversation_settings"/>
</menu>
-10
View File
@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/menu_add_to_contacts"
android:title="@string/conversation_add_to_contacts__menu_add_to_contacts"
app:showAsAction="never" />
</menu>
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="@string/conversation__menu_archive_chat"
android:id="@+id/menu_archive_chat"/>
</menu>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="@string/conversation_insecure__invite"
android:id="@+id/menu_invite"/>
<item android:title="@string/conversation__menu_delete_chat"
android:id="@+id/menu_delete_chat"/>
</menu>
-9
View File
@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:title="@string/conversation_expiring_off__disappearing_messages"
android:id="@+id/menu_expiring_messages_off"
android:icon="@drawable/ic_timer_off_white_24dp"/>
</menu>
-10
View File
@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/menu_expiring_messages"
app:actionLayout="@layout/expiration_timer_menu"
app:showAsAction="always"
android:title="@string/menu_conversation_expiring_on__messages_expiring"/>
</menu>
-9
View File
@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:title="@string/convesation_group_options__recipients_list"
android:id="@+id/menu_group_recipients"
android:icon="?menu_group_icon"
app:showAsAction="ifRoom" />
</menu>
@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:title="@string/conversation_group_options__delivery"
android:id="@+id/menu_group_delivery"
android:icon="?menu_split_icon"
app:showAsAction="ifRoom" >
<menu>
<group android:id="@+id/distribution_group"
android:checkableBehavior="single">
<item android:id="@+id/menu_distribution_conversation" android:title="@string/conversation_group_options__conversation" android:checked="true" />
<item android:id="@+id/menu_distribution_broadcast" android:title="@string/conversation_group_options__broadcast" />
</group>
</menu>
</item>
</menu>
+2 -1
View File
@@ -3,7 +3,8 @@
<item android:id="@+id/menu_edit_group"
android:title="@string/conversation__menu_edit_group"
app:showAsAction="collapseActionView" />
android:icon="?menu_group_icon"
app:showAsAction="ifRoom" />
<item android:id="@+id/menu_leave"
android:title="@string/conversation__menu_leave_group"
-5
View File
@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="@string/conversation_secure_verified__menu_reset_secure_session"
android:id="@+id/menu_reset_secure_session"/>
</menu>
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="@string/conversation__menu_unarchive_chat"
android:id="@+id/menu_archive_chat"/>
</menu>
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_create_profile"
android:title="@string/profile_create_activity__finish"
app:showAsAction="always"
android:icon="?menu_accept_icon"/>
</menu>
+13 -7
View File
@@ -1,19 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:title="@string/qr_scan_activity__title"
android:id="@+id/menu_qr_scan"
android:icon="@drawable/ic_ab_qr"
app:showAsAction="always"/>
<item android:title="@string/qr_show_activity__title"
android:id="@+id/menu_qr_show" />
<item android:title="@string/text_secure_normal__menu_new_chat"
android:id="@+id/menu_new_chat" />
<item android:title="@string/menu_deaddrop"
android:id="@+id/menu_deaddrop" />
<item android:title="@string/text_secure_normal__menu_clear_passphrase"
android:id="@+id/menu_clear_passphrase" />
<item android:title="@string/text_secure_normal__invite_friends"
android:id="@+id/menu_invite" />
<item android:title="@string/text_secure_normal__menu_settings"
android:id="@+id/menu_settings" />
<item android:title="@string/text_secure_normal__help"
android:id="@+id/menu_help"/>
</menu>
+1 -4
View File
@@ -7,6 +7,7 @@
<attr name="attachment_document_icon_large" format="reference" />
<attr name="conversation_list_item_background" format="reference"/>
<attr name="conversation_list_deaddrop_bg_color" format="reference|color"/>
<attr name="conversation_list_item_contact_color" format="reference|color"/>
<attr name="conversation_list_item_subject_color" format="reference|color"/>
<attr name="conversation_list_item_delivery_icon_color" format="reference|color"/>
@@ -177,10 +178,6 @@
<attr name="iconColor" format="color" />
</declare-styleable>
<declare-styleable name="AlertView">
<attr name="useSmallIcon" format="boolean" />
</declare-styleable>
<declare-styleable name="AudioView">
<attr name="widgetBackground" format="color"/>
<attr name="foregroundTintColor" format="color" />
-2
View File
@@ -72,6 +72,4 @@
<dimen name="floating_action_button_margin">16dp</dimen>
<dimen name="alertview_small_icon_size">14dp</dimen>
</resources>
+52 -3
View File
@@ -41,8 +41,14 @@
<string name="ApplicationPreferencesActivity_sms_mms_summary">SMS %1$s, MMS %2$s</string>
<string name="ApplicationPreferencesActivity_privacy_summary">Screen lock %1$s, Read receipts %2$s</string>
<string name="ApplicationPreferencesActivity_appearance_summary">Theme %1$s, Language %2$s</string>
<string name="ApplicationPreferencesActivity_appearance_summary_new">Theme %1$s, Language %2$s, Background %3$s</string>
<string name="ApplicationPreferencesActivity_appearance_background_default">default</string>
<string name="ApplicationPreferencesActivity_appearance_background_custom">custom</string>
<!-- AppearancePreferenceFragment -->
<string name="AppearancePreferencesFragment_background_save_error">Background image could not be saved</string>
<string name="AppearancePreferencesFragment_background_custom_summary">Custom</string>
<string name="AppearancePreferencesFragment_background_default_summary">Default</string>
<!-- AppProtectionPreferenceFragment -->
<plurals name="AppProtectionPreferenceFragment_minutes">
@@ -164,6 +170,9 @@
<string name="ConversationActivity_signal_needs_camera_permissions_to_take_photos_or_video">Delta Chat needs Camera permissions to take photos or video</string>
<string name="ConversationActivity_quoted_contact_message">%1$s %2$s</string>
<string name="ConversationActivity_NoMessagesHint">Send message to %1$s:\n\n• It is okay if %2$s does not use Delta Chat.\n\n• Delivering the first message may take a while.</string>
<string name="ConversationActivity_MsgNewGroupDraftHint">Compose the first message, allowing others to reply within this group.\n\n• It is okay if not all members use Delta Chat.\n\n• Delivering the first message may take a while.</string>
<string name="ConversationActivity_ask_delete_chat">Delete this chat? It will no longer be shown in the chat list, its messages will remain on the server.</string>
<!-- ConversationAdapter -->
<plurals name="ConversationAdapter_n_unread_messages">
@@ -224,9 +233,9 @@
<item quantity="one">Delete selected chats?</item>
<item quantity="other">Delete selected chats?</item>
</plurals>
<plurals name="ConversationListFragment_this_will_permanently_delete_all_n_selected_conversations">
<item quantity="one">This will permanently delete the selected chats.</item>
<item quantity="other">This will permanently delete all %1$d selected chats.</item>
<plurals name="ConversationListFragment_ask_selected_chats">
<item quantity="one">Delete the selected chat? It will no longer be shown in the chat list, its messages will remain on the server.</item>
<item quantity="other">Delete %1%d selected chats? They will no longer be shown in the chat list, their messages will remain on the server.</item>
</plurals>
<string name="ConversationListFragment_deleting">Deleting</string>
<string name="ConversationListFragment_deleting_selected_conversations">Deleting selected chats...</string>
@@ -296,6 +305,7 @@
<string name="ShareActivity_share_with">Share with</string>
<string name="ShareActivity_unable_to_open_media">Can\'t find an app able to open this media.</string>
<string name="ShareActivity_file_not_found">Could not find %1$s.</string>
<string name="ShareActivity_forward_message_to_user_info">Forward selected messages to %1$s?</string>
<!-- ExperienceUpgradeActivity -->
<string name="ExperienceUpgradeActivity_welcome_to_signal_dgaf">Welcome to Delta Chat.</string>
@@ -1312,6 +1322,32 @@
<string name="new_conversation_activity__refresh">Refresh</string>
<!-- redphone_audio_popup_menu -->
<!-- qr_scan_activity -->
<string name="qr_scan_activity__title">Scan QR code</string>
<string name="qr_scan_activity__hint">Place your camera over the QR code</string>
<!-- qr_scan_handler -->
<string name="qr_scan_handler_join_verified_group">Do you want to join the verified group <![CDATA[<b>]]>%1$s<![CDATA[</b>]]>?</string>
<string name="qr_scan_handler_fingerprint_ask_oob">Verify contact and start chatting with <![CDATA[<b>]]>%1$s<![CDATA[</b>]]>?</string>
<string name="qr_scan_handler_fingerprint_ok">Contact <![CDATA[<i>]]>%1$s<![CDATA[</i>]]> verified. Start chatting?</string>
<string name="qr_scan_handler_fingerprint_mismatch">The scanned fingerprint does <![CDATA[<b>]]>not match<![CDATA[</b>]]> the fingerprint last seen for <![CDATA[<i>]]>%1$s<![CDATA[</i>]]>.</string>
<string name="qr_scan_handler_fingerprint_without_address">This QR code contains a fingerprint but no email address.\n\nFor an out-of-band-verification, please establish an encrpyted connection to the recipient first.</string>
<string name="qr_scan_handler_Scan_contains_text">Scanned QR code text:\n\n%1$s</string>
<string name="qr_scan_handler_qr_scan_contains_url">Scanned QR code URL:\n\n%1$s</string>
<string name="qr_scan_handler_fingerprint">Fingerprint</string>
<string name="qr_scan_handler_ask_start_chat_with">Chat with <![CDATA[<b>]]>%1$s<![CDATA[</b>]]>?</string>
<string name="qr_scan_handler_verfied_introduce_myself">%1$s verified, introduce myself …</string>
<!-- qr_show_activity -->
<string name="qr_show_activity__title">Show QR verify code</string>
<string name="qr_show_activity__joining">%1$s joins.</string>
<string name="qr_show_activity__verified">%1$s verified.</string>
<string name="qr_show_activity__group_joined">%1$s securely joined the group.</string>
<string name="qr_show_activity__join_verified_group_hint">Scan this to join the verified group <![CDATA[<b>]]>%1$s<![CDATA[</b>]]>.</string>
<string name="qr_show_activity__join_verified_group_title">QR invite code</string>
<string name="qr_show_activity__join_contact_title">QR verify code</string>
<string name="qr_show_activity__join_contact_hint"><![CDATA[<b>]]>%1$s<![CDATA[</b><br>]]>Scan this to set up a verified contact.</string>
<!-- Trimmer -->
<string name="trimmer__deleting">Deleting</string>
<string name="trimmer__deleting_old_messages">Deleting old messages...</string>
@@ -1487,5 +1523,18 @@
<string name="default_status_hint">Status text</string>
<string name="registration_activity__login">Login</string>
<string name="preferences__chat_background">Chat-Background</string>
<string name="copy_to_clipboard">Copy to clipboard</string>
<string name="open">Open</string>
<string name="done">Done</string>
<string name="menu_deaddrop">Contact requests</string>
<string name="not_now">Not now</string>
<string name="never">Never</string>
<string name="conversation__menu_view_profile">View profile</string>
<string name="conversation__menu_archive_chat">Archive chat</string>
<string name="conversation__menu_unarchive_chat">Unarchive chat</string>
<string name="conversation__menu_delete_chat">Delete chat</string>
<string name="conversation__no_messages">No messages.</string>
<string name="permanent_notification_subtitle">Tap to open.</string>
<string name="error_no_network">Network unavailable.</string>
</resources>
+10
View File
@@ -182,6 +182,7 @@
<style name="Button.Primary" parent="Base.Widget.AppCompat.Button.Colored">
<item name="colorAccent">@color/signal_primary</item>
<item name="colorButtonNormal">@color/signal_primary</item>
<item name="android:textColor">@color/white</item>
</style>
@@ -230,4 +231,13 @@
<item name="colorControlActivated">@color/white</item>
</style>
<style name="NoMessagesTextView">
<item name="android:textColor">@color/white</item>
<item name="android:textSize">16sp</item>
<item name="android:background">@drawable/no_message_rounded_background</item>
<item name="android:layout_marginLeft">12dp</item>
<item name="android:layout_marginRight">12dp</item>
<item name="android:padding">12dp</item>
</style>
</resources>
+2
View File
@@ -132,6 +132,7 @@
<item name="attachment_document_icon_large">@drawable/ic_document_large_light</item>
<item name="conversation_list_item_background">@drawable/conversation_list_item_background</item>
<item name="conversation_list_deaddrop_bg_color">#ffcccccc</item>
<item name="conversation_list_item_contact_color">@color/core_light_90</item>
<item name="conversation_list_item_subject_color">@color/core_light_60</item>
<item name="conversation_list_item_delivery_icon_color">@color/core_light_35</item>
@@ -275,6 +276,7 @@
<item name="attachment_document_icon_large">@drawable/ic_document_large_dark</item>
<item name="conversation_list_item_background">@drawable/conversation_list_item_background_dark</item>
<item name="conversation_list_deaddrop_bg_color">#ff333333</item>
<item name="conversation_list_item_contact_color">#ffdddddd</item>
<item name="conversation_list_item_subject_color">#ffdddddd</item>
<item name="conversation_list_item_delivery_icon_color">@color/core_dark_55</item>
+8
View File
@@ -25,4 +25,12 @@
android:title="@string/preferences__advanced"
android:icon="@drawable/ic_advanced_24dp"/>
<Preference android:key="preference_category_invite"
android:title="@string/text_secure_normal__invite_friends"
android:icon="@drawable/ic_invite_24dp"/>
<Preference android:key="preference_category_help"
android:title="@string/text_secure_normal__help"
android:icon="@drawable/ic_help_24dp"/>
</PreferenceScreen>
+1 -1
View File
@@ -16,7 +16,7 @@
android:entryValues="@array/language_values"
android:defaultValue="zz"/>
<Preference
<org.thoughtcrime.securesms.preferences.widgets.SignalPreference
android:key="pref_chat_background"
android:title="@string/preferences__chat_background"
/>
+1 -21
View File
@@ -1,28 +1,8 @@
/*******************************************************************************
*
* Delta Chat Java Adapter
* (C) 2017 Björn Petersen
* Contact: r10s@b44t.com, http://b44t.com
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see http://www.gnu.org/licenses/ .
*
******************************************************************************/
package com.b44t.messenger;
public class DcChat {
public static final int DC_CHAT_NO_CHAT = 0;
public final static int DC_CHAT_ID_DEADDROP = 1;
public final static int DC_CHAT_ID_STARRED = 5;
public final static int DC_CHAT_ID_ARCHIVED_LINK = 6;
+1 -23
View File
@@ -1,28 +1,5 @@
/*******************************************************************************
*
* Delta Chat Java Adapter
* (C) 2017 Björn Petersen
* Contact: r10s@b44t.com, http://b44t.com
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see http://www.gnu.org/licenses/ .
*
******************************************************************************/
package com.b44t.messenger;
import android.support.annotation.NonNull;
public class DcChatlist {
@@ -40,6 +17,7 @@ public class DcChatlist {
public native int getCnt ();
public native int getChatId (int index);
public @NonNull DcChat getChat (int index) { return new DcChat(getChatCPtr(index)); }
public native int getMsgId (int index);
public @NonNull DcMsg getMsg (int index) { return new DcMsg(getMsgCPtr(index)); }
public @NonNull DcLot getSummary(int index, DcChat chat) { return new DcLot(getSummaryCPtr(index, chat==null? null : chat.getChatCPtr())); }
+9 -31
View File
@@ -1,28 +1,5 @@
/*******************************************************************************
*
* Delta Chat Java Adapter
* (C) 2017 Björn Petersen
* Contact: r10s@b44t.com, http://b44t.com
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see http://www.gnu.org/licenses/ .
*
******************************************************************************/
package com.b44t.messenger;
public class DcContact {
public final static int DC_CONTACT_ID_SELF = 1;
@@ -59,14 +36,15 @@ public class DcContact {
return getAddr();
}
public native int getId ();
public native String getName ();
public native String getDisplayName();
public native String getFirstName ();
public native String getAddr ();
public native String getNameNAddr ();
public native boolean isBlocked ();
public native boolean isVerified ();
public native int getId ();
public native String getName ();
public native String getDisplayName ();
public native String getFirstName ();
public native String getAddr ();
public native String getNameNAddr ();
public native String getProfileImage();
public native boolean isBlocked ();
public native boolean isVerified ();
// working with raw c-data
private long contactCPtr; // CAVE: the name is referenced in the JNI
+7 -31
View File
@@ -1,28 +1,5 @@
/*******************************************************************************
*
* Delta Chat Java Adapter
* (C) 2017 Björn Petersen
* Contact: r10s@b44t.com, http://b44t.com
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see http://www.gnu.org/licenses/ .
*
******************************************************************************/
package com.b44t.messenger;
import android.support.annotation.NonNull;
public class DcContext {
@@ -35,6 +12,7 @@ public class DcContext {
public final static int DC_EVENT_INFO = 100;
public final static int DC_EVENT_WARNING = 300;
public final static int DC_EVENT_ERROR = 400;
public final static int DC_EVENT_ERROR_NETWORK = 401;
public final static int DC_EVENT_MSGS_CHANGED = 2000;
public final static int DC_EVENT_INCOMING_MSG = 2005;
public final static int DC_EVENT_MSG_DELIVERED = 2010;
@@ -86,17 +64,17 @@ public class DcContext {
public native void configure ();
public native void stopOngoingProcess ();
public native int isConfigured ();
public native void performJobs ();
public native void fetch ();
public native void idle ();
public native void interruptIdle ();
public native void performImapJobs ();
public native void performImapFetch ();
public native void performImapIdle ();
public native void interruptImapIdle ();
public native void performSmtpJobs ();
public native void performSmtpIdle ();
public native void interruptSmtpIdle ();
public native void maybeNetwork ();
public native void setConfig (String key, String value);
public void setConfigInt (String key, int value) { setConfig(key, Integer.toString(value)); }
public native String getConfig (String key, String def);
public int getConfigInt (String key, int def) { return Integer.parseInt(getConfig(key, Integer.toString(def))); }
public int getConfigInt (String key, int def) { try{return Integer.parseInt(getConfig(key, Integer.toString(def)));} catch(Exception e) {} return 0; }
public native String getInfo ();
public native String initiateKeyTransfer ();
public native boolean continueKeyTransfer (int msg_id, String setup_code);
@@ -145,8 +123,6 @@ public class DcContext {
public native void forwardMsgs (int msg_ids[], int chat_id);
public native int sendMsg (int chat_id, DcMsg msg);
public native int sendTextMsg (int chat_id, String text);
public native int sendVcardMsg (int chat_id, int contact_id);
public native int sendMediaMsg (int chat_id, int type, String file, String mime, int w, int h, int time_ms, String author, String trackname);
public native int checkQrCPtr (String qr);
public @NonNull DcLot checkQr (String qr) { return new DcLot(checkQrCPtr(qr)); }
public native String getSecurejoinQr (int chat_id);
+30 -37
View File
@@ -1,43 +1,35 @@
/*******************************************************************************
*
* Delta Chat Java Adapter
* (C) 2017 Björn Petersen
* Contact: r10s@b44t.com, http://b44t.com
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see http://www.gnu.org/licenses/ .
*
******************************************************************************/
package com.b44t.messenger;
import android.os.AsyncTask;
import org.thoughtcrime.securesms.util.Util;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
public class DcEventCenter {
private Hashtable<Integer, ArrayList<Object>> allObservers = new Hashtable<>();
private Hashtable<Integer, ArrayList<DcEventDelegate>> allObservers = new Hashtable<>();
private final Object LOCK = new Object();
public interface DcEventDelegate {
void handleEvent(int eventId, Object data1, Object data2);
default boolean runOnMain() {
return true;
}
}
public void addObserver(Object observer, int eventId) {
/**
* @deprecated use addObserver(int, DcEventDelegate) instead.
*/
@Deprecated
public void addObserver(DcEventDelegate observer, int eventId) {
addObserver(eventId, observer);
}
public void addObserver(int eventId, DcEventDelegate observer) {
synchronized (LOCK) {
ArrayList<Object> idObservers = allObservers.get(eventId);
ArrayList<DcEventDelegate> idObservers = allObservers.get(eventId);
if (idObservers == null) {
allObservers.put(eventId, (idObservers = new ArrayList<>()));
}
@@ -45,21 +37,19 @@ public class DcEventCenter {
}
}
public void removeObserver(Object observer, int eventId) {
public void removeObserver(int eventId, DcEventDelegate observer) {
synchronized (LOCK) {
ArrayList<Object> idObservers = allObservers.get(eventId);
ArrayList<DcEventDelegate> idObservers = allObservers.get(eventId);
if (idObservers != null) {
idObservers.remove(observer);
}
}
}
public void removeObservers(Object observer) {
public void removeObservers(DcEventDelegate observer) {
synchronized (LOCK) {
Enumeration<Integer> enumKey = allObservers.keys();
while(enumKey.hasMoreElements()) {
Integer eventId = enumKey.nextElement();
ArrayList<Object> idObservers = allObservers.get(eventId);
for(Integer eventId : allObservers.keySet()) {
ArrayList<DcEventDelegate> idObservers = allObservers.get(eventId);
if (idObservers != null) {
idObservers.remove(observer);
}
@@ -69,11 +59,14 @@ public class DcEventCenter {
public void sendToObservers(int eventId, Object data1, Object data2) {
synchronized (LOCK) {
ArrayList<Object> idObservers = allObservers.get(eventId);
ArrayList<DcEventDelegate> idObservers = allObservers.get(eventId);
if (idObservers != null) {
for (int i = 0; i < idObservers.size(); i++) {
Object observer = idObservers.get(i);
((DcEventDelegate) observer).handleEvent(eventId, data1, data2);
for (DcEventDelegate observer : idObservers) {
if(observer.runOnMain()) {
Util.runOnMain(() -> observer.handleEvent(eventId, data1, data2));
} else {
Util.runOnBackground(() -> observer.handleEvent(eventId, data1, data2));
}
}
}
}
-23
View File
@@ -1,28 +1,5 @@
/*******************************************************************************
*
* Delta Chat Java Adapter
* (C) 2017 Björn Petersen
* Contact: r10s@b44t.com, http://b44t.com
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see http://www.gnu.org/licenses/ .
*
******************************************************************************/
package com.b44t.messenger;
public class DcLot {
public final static int DC_TEXT1_DRAFT = 1;
@@ -0,0 +1,44 @@
package com.b44t.messenger;
/**
* Contains a list of media entries, their respective positions and ability to move through it.
*/
public class DcMediaGalleryElement {
final int[] mediaMsgs;
int position;
final DcContext context;
public DcMediaGalleryElement(int[] mediaMsgs, int position, DcContext context, boolean leftIsRecent) {
this.mediaMsgs = mediaMsgs;
this.position = position;
this.context = context;
// normal state is left is recent. If the ui needs right to be recent we reverse the order here.
if (!leftIsRecent) {
for (int ii = 0; ii < mediaMsgs.length / 2; ii++) {
int tmp = mediaMsgs[ii];
int opposite = mediaMsgs.length - 1 - ii;
mediaMsgs[ii] = mediaMsgs[opposite];
mediaMsgs[opposite] = tmp;
}
}
}
public int getCount() {
return mediaMsgs.length;
}
public int getPosition() {
return position;
}
public void moveToPosition(int newPosition) {
if(newPosition < 0 || newPosition >= mediaMsgs.length)
throw new IllegalArgumentException("can't move outside of known area.");
position = newPosition;
}
public DcMsg getMessage() {
return context.getMsg(mediaMsgs[position]);
}
}
+9 -38
View File
@@ -1,38 +1,11 @@
/*******************************************************************************
*
* Delta Chat Java Adapter
* (C) 2017 Björn Petersen
* Contact: r10s@b44t.com, http://b44t.com
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see http://www.gnu.org/licenses/ .
*
******************************************************************************/
package com.b44t.messenger;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.model.Quote;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientProvider;
import java.util.Collections;
import java.util.List;
import java.io.File;
import java.util.Set;
public class DcMsg {
@@ -54,6 +27,7 @@ public class DcMsg {
public final static int DC_STATE_OUT_DELIVERED = 26;
public final static int DC_STATE_OUT_MDN_RCVD = 28;
public static final int DC_MSG_NO_ID = 0;
public final static int DC_MSG_ID_MARKER1 = 1;
public final static int DC_MSG_ID_DAYMARKER = 9;
@@ -93,15 +67,14 @@ public class DcMsg {
public native int getHeight (int def);
public native int getDuration ();
public native void lateFilingMediaSize(int width, int height, int duration);
public native int getBytes ();
public @NonNull DcLot getSummary (DcChat chat) { return new DcLot(getSummaryCPtr(chat.getChatCPtr())); }
public native String getSummarytext (int approx_characters);
public native int showPadlock ();
public @NonNull DcLot getMediainfo () { return new DcLot(getMediainfoCPtr()); }
public boolean hasFile () { String file = getFile(); return file!=null && !file.isEmpty(); }
public native String getFile ();
public native String getFilemime ();
public native String getFilename ();
public native long getFilebytes ();
public native boolean isForwarded ();
public native boolean isInfo ();
public native boolean isSetupMessage ();
@@ -111,7 +84,12 @@ public class DcMsg {
public native void setFile (String file, String filemime);
public native void setDimension (int width, int height);
public native void setDuration (int duration);
public native void setMediainfo (String author, String trackname);
public File getFileAsFile() {
if(getFile()==null)
throw new AssertionError("expected a file to be present.");
return new File(getFile());
}
// aliases and higher-level tools
public static int[] msgSetToIds(final Set<DcMsg> dcMsgs) {
@@ -189,15 +167,8 @@ public class DcMsg {
return null;
}
public Recipient getIndividualRecipient() {
// TODO: remove the dependency to org.thoughtcrime.securesms.recipients.Recipient
RecipientProvider.RecipientDetails recipientDetails = new RecipientProvider.RecipientDetails("individualRecipient", null, false, null, null);
return new Recipient(Address.fromContact(getFromId()), recipientDetails);
}
// working with raw c-data
private long msgCPtr; // CAVE: the name is referenced in the JNI
private native void unrefMsgCPtr ();
private native long getSummaryCPtr (long chatCPtr);
private native long getMediainfoCPtr();
};
@@ -16,6 +16,7 @@
*/
package org.thoughtcrime.securesms;
import android.annotation.SuppressLint;
import android.arch.lifecycle.DefaultLifecycleObserver;
import android.arch.lifecycle.LifecycleOwner;
import android.arch.lifecycle.ProcessLifecycleOwner;
@@ -25,23 +26,18 @@ import android.support.annotation.NonNull;
import android.support.multidex.MultiDexApplication;
import android.util.Log;
import com.b44t.messenger.DcContext;
import com.b44t.messenger.DcEventCenter;
import org.thoughtcrime.securesms.connect.ApplicationDcContext;
import org.thoughtcrime.securesms.crypto.PRNGFixes;
import org.thoughtcrime.securesms.dependencies.AxolotlStorageModule;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule;
import org.thoughtcrime.securesms.jobmanager.JobManager;
import org.thoughtcrime.securesms.jobmanager.dependencies.DependencyInjector;
import org.thoughtcrime.securesms.jobmanager.persistence.JavaJobSerializer;
import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirementProvider;
import org.thoughtcrime.securesms.jobs.CreateSignedPreKeyJob;
import org.thoughtcrime.securesms.jobs.MultiDeviceContactUpdateJob;
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirementProvider;
import org.thoughtcrime.securesms.jobs.requirements.SqlCipherMigrationRequirementProvider;
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
import org.thoughtcrime.securesms.util.ScreenLockUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import org.webrtc.PeerConnectionFactory;
import org.webrtc.PeerConnectionFactory.InitializationOptions;
import org.webrtc.voiceengine.WebRtcAudioManager;
@@ -52,8 +48,6 @@ import org.whispersystems.libsignal.util.AndroidSignalProtocolLogger;
import java.util.HashSet;
import java.util.Set;
import dagger.ObjectGraph;
/**
* Will be called once when the TextSecure process is created.
*
@@ -68,7 +62,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
private ExpiringMessageManager expiringMessageManager;
private JobManager jobManager;
private ObjectGraph objectGraph;
private volatile boolean isAppVisible;
@@ -87,34 +80,28 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
initializeRandomNumberFix();
initializeLogging();
initializeDependencyInjection();
initializeJobManager();
initializeExpiringMessageManager();
//initializeSignedPreKeyCheck(); -- keys are generated in the core, however, not sure if this is needed for the lock screen
initializePeriodicTasks();
initializeWebRtc();
initializeIncomingMessageNotifier();
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
}
@Override
public void onStart(@NonNull LifecycleOwner owner) {
isAppVisible = true;
Log.i(TAG, "App is now visible.");
executePendingContactSync();
}
@Override
public void onStop(@NonNull LifecycleOwner owner) {
isAppVisible = false;
Log.i(TAG, "App is no longer visible.");
ScreenLockUtil.shouldLockApp = true;
}
@Override
public void injectDependencies(Object object) {
if (object instanceof InjectableType) {
objectGraph.inject(object);
}
}
public JobManager getJobManager() {
@@ -137,35 +124,43 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
SignalProtocolLoggerProvider.setProvider(new AndroidSignalProtocolLogger());
}
@SuppressLint("StaticFieldLeak")
private void initializeIncomingMessageNotifier() {
DcEventCenter dcEventCenter = dcContext.eventCenter;
dcEventCenter.addObserver(DcContext.DC_EVENT_INCOMING_MSG, new DcEventCenter.DcEventDelegate() {
@Override
public void handleEvent(int eventId, Object data1, Object data2) {
MessageNotifier.updateNotification(dcContext.context, ((Long) data1).intValue());
}
@Override
public boolean runOnMain() {
return false;
}
});
// in five seconds, the system should be up and ready so we can start issuing notifications.
Util.runOnBackgroundDelayed(() -> {
MessageNotifier.updateNotification(dcContext.context);
}, 5000);
}
private void initializeJobManager() {
this.jobManager = JobManager.newBuilder(this)
.withName("TextSecureJobs")
.withDependencyInjector(this)
.withJobSerializer(new JavaJobSerializer())
.withRequirementProviders(new MasterSecretRequirementProvider(this),
new NetworkRequirementProvider(this),
new SqlCipherMigrationRequirementProvider())
.withConsumerThreads(5)
.build();
}
private void initializeDependencyInjection() {
this.objectGraph = ObjectGraph.create(new SignalCommunicationModule(this, new SignalServiceNetworkAccess(this)),
new AxolotlStorageModule(this));
}
private void initializeSignedPreKeyCheck() {
if (!TextSecurePreferences.isSignedPreKeyRegistered(this)) {
jobManager.add(new CreateSignedPreKeyJob(this));
}
}
private void initializeExpiringMessageManager() {
this.expiringMessageManager = new ExpiringMessageManager(this);
}
private void initializePeriodicTasks() {
//RotateSignedPreKeyListener.schedule(this); -- no key rotation in the ui part
//DirectoryRefreshListener.schedule(this); -- directory in this sense seems to be the address book
//LocalBackupListener.schedule(this); -- disabled for now, there is no automatic backup; maybe the implicit IMAP backup is sufficient
@@ -208,10 +203,4 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
Log.w(TAG, e);
}
}
private void executePendingContactSync() {
if (TextSecurePreferences.needsFullContactSync(this)) {
ApplicationContext.getInstance(this).getJobManager().add(new MultiDeviceContactUpdateJob(this, true));
}
}
}
@@ -18,11 +18,13 @@
package org.thoughtcrime.securesms;
import android.annotation.TargetApi;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Build.VERSION;
import android.os.Bundle;
@@ -33,6 +35,7 @@ import android.support.v4.app.FragmentTransaction;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v7.preference.Preference;
import android.widget.Toast;
import org.thoughtcrime.securesms.preferences.AdvancedPreferenceFragment;
import org.thoughtcrime.securesms.preferences.AppProtectionPreferenceFragment;
@@ -65,6 +68,8 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
private static final String PREFERENCE_CATEGORY_APPEARANCE = "preference_category_appearance";
private static final String PREFERENCE_CATEGORY_CHATS = "preference_category_chats";
private static final String PREFERENCE_CATEGORY_ADVANCED = "preference_category_advanced";
private static final String PREFERENCE_CATEGORY_INVITE = "preference_category_invite";
private static final String PREFERENCE_CATEGORY_HELP = "preference_category_help";
public static final int REQUEST_CODE_SET_BACKGROUND = 11;
@@ -147,6 +152,10 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_CHATS));
this.findPreference(PREFERENCE_CATEGORY_ADVANCED)
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_ADVANCED));
this.findPreference(PREFERENCE_CATEGORY_INVITE)
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_INVITE));
this.findPreference(PREFERENCE_CATEGORY_HELP)
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_HELP));
if (VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
tintIcons(getActivity());
@@ -179,37 +188,36 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
.setSummary(ChatsPreferenceFragment.getSummary(getActivity()));
}
private void setCategoryVisibility() {
}
@TargetApi(11)
private void tintIcons(Context context) {
Drawable sms = DrawableCompat.wrap(ContextCompat.getDrawable(context, R.drawable.ic_textsms_white_24dp));
Drawable notifications = DrawableCompat.wrap(ContextCompat.getDrawable(context, R.drawable.ic_notifications_white_24dp));
Drawable privacy = DrawableCompat.wrap(ContextCompat.getDrawable(context, R.drawable.ic_security_white_24dp));
Drawable appearance = DrawableCompat.wrap(ContextCompat.getDrawable(context, R.drawable.ic_brightness_6_white_24dp));
Drawable chats = DrawableCompat.wrap(ContextCompat.getDrawable(context, R.drawable.ic_forum_white_24dp));
Drawable devices = DrawableCompat.wrap(ContextCompat.getDrawable(context, R.drawable.ic_laptop_white_24dp));
Drawable advanced = DrawableCompat.wrap(ContextCompat.getDrawable(context, R.drawable.ic_advanced_white_24dp));
Drawable invite = DrawableCompat.wrap(ContextCompat.getDrawable(context, R.drawable.ic_mood_white_24dp));
Drawable help = DrawableCompat.wrap(ContextCompat.getDrawable(context, R.drawable.ic_help_white_24dp));
int[] tintAttr = new int[]{R.attr.pref_icon_tint};
TypedArray typedArray = context.obtainStyledAttributes(tintAttr);
int color = typedArray.getColor(0, 0x0);
typedArray.recycle();
DrawableCompat.setTint(sms, color);
DrawableCompat.setTint(notifications, color);
DrawableCompat.setTint(privacy, color);
DrawableCompat.setTint(appearance, color);
DrawableCompat.setTint(chats, color);
DrawableCompat.setTint(devices, color);
DrawableCompat.setTint(advanced, color);
DrawableCompat.setTint(invite, color);
DrawableCompat.setTint(help, color);
this.findPreference(PREFERENCE_CATEGORY_NOTIFICATIONS).setIcon(notifications);
this.findPreference(PREFERENCE_CATEGORY_APP_PROTECTION).setIcon(privacy);
this.findPreference(PREFERENCE_CATEGORY_APPEARANCE).setIcon(appearance);
this.findPreference(PREFERENCE_CATEGORY_CHATS).setIcon(chats);
this.findPreference(PREFERENCE_CATEGORY_ADVANCED).setIcon(advanced);
this.findPreference(PREFERENCE_CATEGORY_INVITE).setIcon(invite);
this.findPreference(PREFERENCE_CATEGORY_HELP).setIcon(help);
}
private class CategoryClickListener implements Preference.OnPreferenceClickListener {
@@ -239,6 +247,16 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
case PREFERENCE_CATEGORY_ADVANCED:
fragment = new AdvancedPreferenceFragment();
break;
case PREFERENCE_CATEGORY_INVITE:
startActivity(new Intent(getActivity(), InviteActivity.class));
break;
case PREFERENCE_CATEGORY_HELP:
try {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.help_url))));
} catch (ActivityNotFoundException e) {
Toast.makeText(getActivity(), R.string.ConversationListActivity_there_is_no_browser_installed_on_your_device, Toast.LENGTH_LONG).show();
}
break;
default:
throw new AssertionError();
}
@@ -49,7 +49,8 @@ public abstract class BaseActionBarActivity extends AppCompatActivity {
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == ScreenLockUtil.REQUEST_CODE_CONFIRM_CREDENTIALS) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ScreenLockUtil.REQUEST_CODE_CONFIRM_CREDENTIALS) {
if (resultCode == RESULT_OK) {
shouldLockApp = false;
} else {
@@ -8,11 +8,8 @@ import com.b44t.messenger.DcChat;
import com.b44t.messenger.DcMsg;
import org.thoughtcrime.securesms.contactshare.Contact;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.whispersystems.libsignal.util.guava.Optional;
import java.util.List;
import java.util.Locale;
@@ -4,7 +4,6 @@ import android.support.annotation.NonNull;
import com.b44t.messenger.DcLot;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.model.ThreadRecord;
import org.thoughtcrime.securesms.mms.GlideRequests;
@@ -14,6 +13,7 @@ import java.util.Set;
public interface BindableConversationListItem extends Unbindable {
public void bind(@NonNull ThreadRecord thread,
int msgId,
@NonNull DcLot dcSummary,
@NonNull GlideRequests glideRequests, @NonNull Locale locale,
@NonNull Set<Long> selectedThreads, boolean batchMode);
@@ -24,7 +24,6 @@ import android.util.Log;
import org.thoughtcrime.securesms.components.ContactFilterToolbar;
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader.DisplayMode;
import org.thoughtcrime.securesms.util.DirectoryHelper;
import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
import org.thoughtcrime.securesms.util.DynamicTheme;
@@ -128,12 +127,6 @@ public abstract class ContactSelectionActivity extends PassphraseRequiredActionB
@Override
protected Void doInBackground(Context... params) {
try {
DirectoryHelper.refreshDirectory(params[0], true);
} catch (IOException e) {
Log.w(TAG, e);
}
return null;
}
@@ -84,6 +84,7 @@ public class ContactSelectionListFragment extends Fragment
public static final String REFRESHABLE = "refreshable";
public static final String RECENTS = "recents";
public static final String SELECT_VERIFIED_EXTRA = "select_verified";
public static final String FROM_SHARE_ACTIVITY_EXTRA = "from_share_activity";
private ApplicationDcContext dcContext;
@@ -233,6 +234,10 @@ public class ContactSelectionListFragment extends Fragment
return getActivity().getIntent().getBooleanExtra(SELECT_VERIFIED_EXTRA, false);
}
private boolean isFromShareActivity() {
return getActivity().getIntent().getBooleanExtra(FROM_SHARE_ACTIVITY_EXTRA, false);
}
private void initializeCursor() {
ContactSelectionListAdapter adapter = new ContactSelectionListAdapter(getActivity(),
GlideApp.with(this),
@@ -267,11 +272,12 @@ public class ContactSelectionListFragment extends Fragment
@Override
public Loader<DcContactsLoader.Ret> onCreateLoader(int id, Bundle args) {
boolean addCreateGroupLinks = !isMulti();
int listflags = 0;
boolean addCreateGroupLinks = isFromShareActivity() ? false : !isMulti();
int listflags = DcContext.DC_GCL_ADD_SELF;
if(isSelectVerfied()) {
listflags = DcContext.DC_GCL_VERIFIED_ONLY;
}
return new DcContactsLoader(getActivity(), listflags, cursorFilter, addCreateGroupLinks);
}
@@ -27,16 +27,15 @@ import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.PorterDuff.Mode;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Vibrator;
import android.provider.Browser;
import android.provider.ContactsContract;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.view.WindowCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
@@ -55,21 +54,20 @@ import android.view.View.OnFocusChangeListener;
import android.view.View.OnKeyListener;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.webkit.MimeTypeMap;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.b44t.messenger.DcChat;
import com.b44t.messenger.DcContact;
import com.b44t.messenger.DcContext;
import com.b44t.messenger.DcEventCenter;
import com.b44t.messenger.DcMsg;
import com.google.android.gms.location.places.ui.PlacePicker;
import com.google.protobuf.ByteString;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.audio.AudioRecorder;
import org.thoughtcrime.securesms.audio.AudioSlidePlayer;
import org.thoughtcrime.securesms.components.AnimatingToggle;
@@ -101,14 +99,9 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.DraftDatabase;
import org.thoughtcrime.securesms.database.DraftDatabase.Draft;
import org.thoughtcrime.securesms.database.DraftDatabase.Drafts;
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
import org.thoughtcrime.securesms.database.MmsSmsColumns.Types;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
import org.thoughtcrime.securesms.events.ReminderUpdateEvent;
import org.thoughtcrime.securesms.giph.ui.GiphyActivity;
import org.thoughtcrime.securesms.jobs.MultiDeviceBlockedUpdateJob;
import org.thoughtcrime.securesms.mms.AttachmentManager;
import org.thoughtcrime.securesms.mms.AttachmentManager.MediaType;
import org.thoughtcrime.securesms.mms.AudioSlide;
@@ -116,32 +109,22 @@ import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.mms.LocationSlide;
import org.thoughtcrime.securesms.mms.MediaConstraints;
import org.thoughtcrime.securesms.mms.OutgoingExpirationUpdateMessage;
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
import org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage;
import org.thoughtcrime.securesms.mms.PartAuthority;
import org.thoughtcrime.securesms.mms.QuoteId;
import org.thoughtcrime.securesms.mms.QuoteModel;
import org.thoughtcrime.securesms.mms.Slide;
import org.thoughtcrime.securesms.mms.SlideDeck;
import org.thoughtcrime.securesms.notifications.MarkReadReceiver;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.profiles.GroupShareProfileView;
import org.thoughtcrime.securesms.providers.PersistentBlobProvider;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
import org.thoughtcrime.securesms.scribbles.ScribbleActivity;
import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.sms.OutgoingEndSessionMessage;
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
import org.thoughtcrime.securesms.util.CharacterCalculator.CharacterState;
import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.ExpirationUtil;
import org.thoughtcrime.securesms.util.GroupUtil;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.ServiceUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
@@ -154,15 +137,20 @@ import org.thoughtcrime.securesms.util.views.Stub;
import org.whispersystems.libsignal.InvalidMessageException;
import org.whispersystems.libsignal.util.guava.Optional;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import static org.thoughtcrime.securesms.TransportOption.Type;
import static org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext;
/**
* Activity for displaying a message thread, as well as
@@ -175,7 +163,6 @@ import static org.whispersystems.signalservice.internal.push.SignalServiceProtos
public class ConversationActivity extends PassphraseRequiredActionBarActivity
implements ConversationFragment.ConversationFragmentListener,
AttachmentManager.AttachmentListener,
RecipientModifiedListener,
DcEventCenter.DcEventDelegate,
OnKeyboardShownListener,
AttachmentDrawerListener,
@@ -184,12 +171,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
{
private static final String TAG = ConversationActivity.class.getSimpleName();
public static final String ADDRESS_EXTRA = "address";
public static final String THREAD_ID_EXTRA = "thread_id";
public static final String IS_ARCHIVED_EXTRA = "is_archived";
public static final String TEXT_EXTRA = "draft_text";
public static final String DISTRIBUTION_TYPE_EXTRA = "distribution_type";
public static final String TIMING_EXTRA = "timing";
public static final String LAST_SEEN_EXTRA = "last_seen";
public static final String STARTING_POSITION_EXTRA = "starting_position";
@@ -213,7 +197,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
protected ConversationTitleView titleView;
private TextView charactersLeft;
private ConversationFragment fragment;
private Button unblockButton;
private InputAwareLayout container;
private View composePanel;
protected Stub<ReminderView> reminderView;
@@ -231,12 +214,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private Recipient recipient;
private ApplicationDcContext dcContext;
private DcChat dcChat = new DcChat(0);
private long threadId;
private int distributionType;
private int threadId;
private boolean archived;
private final boolean isSecureText = true;
private boolean isDefaultSms = true;
private boolean isMmsEnabled = true;
private boolean isSecurityInitialized = false;
@@ -278,7 +259,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
@Override
public void onSuccess(Boolean result) {
if (result != null && result) {
Log.i(TAG, "Finished loading draft");
Util.runOnMain(() -> {
if (fragment != null && fragment.isResumed()) {
fragment.moveToLastSeen();
@@ -292,6 +272,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
});
dcContext.marknoticedChat((int)threadId);
dcContext.eventCenter.addObserver(this, DcContext.DC_EVENT_CHAT_MODIFIED);
dcContext.eventCenter.addObserver(this, DcContext.DC_EVENT_CONTACTS_CHANGED);
}
@@ -328,7 +310,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
@Override
protected void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
@@ -343,14 +324,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
titleView.setTitle(glideRequests, dcChat);
titleView.setVerified(dcChat.isVerified());
setBlockedUserState(recipient, isSecureText, isDefaultSms);
setGroupShareProfileReminder(recipient);
calculateCharactersRemaining();
MessageNotifier.setVisibleThread(threadId);
markThreadAsRead();
Log.w(TAG, "onResume() Finished: " + (System.currentTimeMillis() - getIntent().getLongExtra(TIMING_EXTRA, 0)));
}
@Override
@@ -364,13 +342,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
fragment.setLastSeen(System.currentTimeMillis());
markLastSeen();
AudioSlidePlayer.stopAll();
EventBus.getDefault().unregister(this);
}
@Override
protected void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
@Override
@@ -388,7 +364,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
@Override
protected void onDestroy() {
saveDraft();
if (recipient != null) recipient.removeListener(this);
if (securityUpdateReceiver != null) unregisterReceiver(securityUpdateReceiver);
dcContext.eventCenter.removeObservers(this);
super.onDestroy();
@@ -436,9 +411,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
break;
case GROUP_EDIT:
recipient = Recipient.from(this, data.getParcelableExtra(GroupCreateActivity.GROUP_ADDRESS_EXTRA), true);
recipient.addListener(this);
dcChat = dcContext.getChat((int)threadId);
titleView.setTitle(glideRequests, dcChat);
setBlockedUserState(recipient, isSecureText, isDefaultSms);
supportInvalidateOptionsMenu();
break;
case TAKE_PHOTO:
@@ -448,7 +422,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
break;
case ADD_CONTACT:
recipient = Recipient.from(this, recipient.getAddress(), true);
recipient.addListener(this);
fragment.reloadList();
break;
case PICK_LOCATION:
@@ -489,50 +462,33 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
MenuInflater inflater = this.getMenuInflater();
menu.clear();
if (isSecureText) {
if (recipient.getExpireMessages() > 0) {
inflater.inflate(R.menu.conversation_expiring_on, menu);
final MenuItem item = menu.findItem(R.id.menu_expiring_messages);
final View actionView = MenuItemCompat.getActionView(item);
final TextView badgeView = actionView.findViewById(R.id.expiration_badge);
badgeView.setText(ExpirationUtil.getExpirationAbbreviatedDisplayValue(this, recipient.getExpireMessages()));
actionView.setOnClickListener(v -> onOptionsItemSelected(item));
} else {
inflater.inflate(R.menu.conversation_expiring_off, menu);
}
if(threadId==DcChat.DC_CHAT_ID_DEADDROP) {
return true;
}
if (isGroupConversation()) {
inflater.inflate(R.menu.conversation_group_options, menu);
if (!isPushGroupConversation()) {
inflater.inflate(R.menu.conversation_mms_group_options, menu);
if (distributionType == ThreadDatabase.DistributionTypes.BROADCAST) {
menu.findItem(R.id.menu_distribution_broadcast).setChecked(true);
} else {
menu.findItem(R.id.menu_distribution_conversation).setChecked(true);
}
} else if (isActiveGroup()) {
inflater.inflate(R.menu.conversation_push_group_options, menu);
}
if (recipient != null && recipient.isMuted()) {
inflater.inflate(R.menu.conversation_muted, menu);
}
else {
inflater.inflate(R.menu.conversation_unmuted, menu);
}
inflater.inflate(R.menu.conversation, menu);
if (isSingleConversation() && isSecureText) {
inflater.inflate(R.menu.conversation_secure, menu);
} else if (isSingleConversation()) {
inflater.inflate(R.menu.conversation_insecure, menu);
if (isGroupConversation()) {
if (isActiveGroup()) {
inflater.inflate(R.menu.conversation_push_group_options, menu);
}
}
if (recipient != null && recipient.isMuted()) inflater.inflate(R.menu.conversation_muted, menu);
else inflater.inflate(R.menu.conversation_unmuted, menu);
if (isSingleConversation() && getRecipient().getContactUri() == null) {
inflater.inflate(R.menu.conversation_add_to_contacts, menu);
if( dcChat.getArchived()==0 ) {
inflater.inflate(R.menu.conversation_archive, menu);
}
else {
inflater.inflate(R.menu.conversation_unarchive, menu);
}
inflater.inflate(R.menu.conversation_delete, menu);
super.onPrepareOptionsMenu(menu);
return true;
@@ -542,21 +498,16 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
switch (item.getItemId()) {
case R.id.menu_add_attachment: handleAddAttachment(); return true;
case R.id.menu_view_media: handleViewMedia(); return true;
case R.id.menu_add_to_contacts: handleAddToContacts(); return true;
case R.id.menu_reset_secure_session: handleResetSecureSession(); return true;
case R.id.menu_group_recipients: handleDisplayGroupRecipients(); return true;
case R.id.menu_distribution_broadcast: handleDistributionBroadcastEnabled(item); return true;
case R.id.menu_distribution_conversation: handleDistributionConversationEnabled(item); return true;
case R.id.menu_edit_group: handleEditPushGroup(); return true;
case R.id.menu_leave: handleLeavePushGroup(); return true;
case R.id.menu_mute_notifications: handleMuteNotifications(); return true;
case R.id.menu_unmute_notifications: handleUnmuteNotifications(); return true;
case R.id.menu_conversation_settings: handleConversationSettings(); return true;
case R.id.menu_expiring_messages_off:
case R.id.menu_expiring_messages: handleSelectMessageExpiration(); return true;
case android.R.id.home: handleReturnToConversationList(); return true;
case R.id.menu_add_attachment: handleAddAttachment(); return true;
case R.id.menu_view_media: handleViewMedia(); return true;
case R.id.menu_edit_group: handleEditPushGroup(); return true;
case R.id.menu_leave: handleLeaveGroup(); return true;
case R.id.menu_archive_chat: handleArchiveChat(); return true;
case R.id.menu_delete_chat: handleDeleteChat(); return true;
case R.id.menu_mute_notifications: handleMuteNotifications(); return true;
case R.id.menu_unmute_notifications: handleUnmuteNotifications(); return true;
case R.id.menu_conversation_settings: handleConversationSettings(); return true;
case android.R.id.home: handleReturnToConversationList(); return true;
}
return false;
@@ -574,11 +525,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
inputPanel.onKeyboardShown();
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(ReminderUpdateEvent event) {
updateReminders();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
Permissions.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
@@ -593,32 +539,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
finish();
}
private void handleSelectMessageExpiration() {
if (isPushGroupConversation() && !isActiveGroup()) {
return;
}
//noinspection CodeBlock2Expr
ExpirationDialog.show(this, recipient.getExpireMessages(), expirationTime -> {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
DatabaseFactory.getRecipientDatabase(ConversationActivity.this).setExpireMessages(recipient, expirationTime);
OutgoingExpirationUpdateMessage outgoingMessage = new OutgoingExpirationUpdateMessage(getRecipient(), System.currentTimeMillis(), expirationTime * 1000L);
MessageSender.send(ConversationActivity.this, outgoingMessage, threadId, false, null);
return null;
}
@Override
protected void onPostExecute(Void result) {
invalidateOptionsMenu();
if (fragment != null) fragment.setLastSeen(0);
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
});
}
private void handleMuteNotifications() {
MuteDialog.show(this, until -> {
recipient.setMuted(until);
@@ -658,175 +578,53 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
private void handleUnblock() {
//noinspection CodeBlock2Expr
new AlertDialog.Builder(this)
.setTitle(R.string.ConversationActivity_unblock_this_contact_question)
.setMessage(R.string.ConversationActivity_you_will_once_again_be_able_to_receive_messages_and_calls_from_this_contact)
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(R.string.ConversationActivity_unblock, (dialog, which) -> {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
DatabaseFactory.getRecipientDatabase(ConversationActivity.this)
.setBlocked(recipient, false);
ApplicationContext.getInstance(ConversationActivity.this)
.getJobManager()
.add(new MultiDeviceBlockedUpdateJob(ConversationActivity.this));
return null;
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}).show();
}
private void handleResetSecureSession() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.ConversationActivity_reset_secure_session_question);
builder.setIconAttribute(R.attr.dialog_alert_icon);
builder.setCancelable(true);
builder.setMessage(R.string.ConversationActivity_this_may_help_if_youre_having_encryption_problems);
builder.setPositiveButton(R.string.ConversationActivity_reset, (dialog, which) -> {
if (isSingleConversation()) {
final Context context = getApplicationContext();
OutgoingEndSessionMessage endSessionMessage =
new OutgoingEndSessionMessage(new OutgoingTextMessage(getRecipient(), "TERMINATE", 0, -1));
new AsyncTask<OutgoingEndSessionMessage, Void, Long>() {
@Override
protected Long doInBackground(OutgoingEndSessionMessage... messages) {
return MessageSender.send(context, messages[0], threadId, false, null);
}
@Override
protected void onPostExecute(Long result) {
sendComplete(result);
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, endSessionMessage);
}
});
builder.setNegativeButton(android.R.string.cancel, null);
builder.show();
}
private void handleViewMedia() {
Intent intent = new Intent(this, MediaOverviewActivity.class);
intent.putExtra(MediaOverviewActivity.ADDRESS_EXTRA, recipient.getAddress());
startActivity(intent);
}
private void handleLeavePushGroup() {
if (getRecipient() == null) {
Toast.makeText(this, getString(R.string.ConversationActivity_invalid_recipient),
Toast.LENGTH_LONG).show();
return;
private void handleLeaveGroup() {
new AlertDialog.Builder(this)
.setMessage(getString(R.string.ConversationActivity_are_you_sure_you_want_to_leave_this_group))
.setPositiveButton(R.string.yes, (dialog, which) -> {
dcContext.removeContactFromChat((int)threadId, DcContact.DC_CONTACT_ID_SELF);
Toast.makeText(this, getString(R.string.done), Toast.LENGTH_SHORT).show();
})
.setNegativeButton(R.string.no, null)
.show();
}
private void handleArchiveChat() {
int doArchive = dcContext.getChat((int)threadId).getArchived()==0? 1: 0;
dcContext.archiveChat((int)threadId, doArchive);
Toast.makeText(this, getString(R.string.done), Toast.LENGTH_SHORT).show();
if( doArchive == 1 ) {
finish();
}
}
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.ConversationActivity_leave_group));
builder.setIconAttribute(R.attr.dialog_info_icon);
builder.setCancelable(true);
builder.setMessage(getString(R.string.ConversationActivity_are_you_sure_you_want_to_leave_this_group));
builder.setPositiveButton(R.string.yes, (dialog, which) -> {
Context self = ConversationActivity.this;
try {
String groupId = getRecipient().getAddress().toGroupString();
DatabaseFactory.getGroupDatabase(self).setActive(groupId, false);
GroupContext context = GroupContext.newBuilder()
.setId(ByteString.copyFrom(GroupUtil.getDecodedId(groupId)))
.setType(GroupContext.Type.QUIT)
.build();
OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(getRecipient(), context, null, System.currentTimeMillis(), 0, null, Collections.emptyList());
MessageSender.send(self, outgoingMessage, threadId, false, null);
DatabaseFactory.getGroupDatabase(self).remove(groupId, Address.fromSerialized(TextSecurePreferences.getLocalNumber(self)));
initializeEnabledCheck();
} catch (IOException e) {
Log.w(TAG, e);
Toast.makeText(self, R.string.ConversationActivity_error_leaving_group, Toast.LENGTH_LONG).show();
}
});
builder.setNegativeButton(R.string.no, null);
builder.show();
private void handleDeleteChat() {
new AlertDialog.Builder(this)
.setMessage(getString(R.string.ConversationActivity_ask_delete_chat))
.setPositiveButton(R.string.yes, (dialog, which) -> {
dcContext.deleteChat((int)threadId);
Toast.makeText(this, getString(R.string.done), Toast.LENGTH_SHORT).show();
finish();
})
.setNegativeButton(R.string.no, null)
.show();
}
private void handleEditPushGroup() {
Intent intent = new Intent(ConversationActivity.this, GroupCreateActivity.class);
intent.putExtra(GroupCreateActivity.GROUP_ADDRESS_EXTRA, recipient.getAddress());
if (dcChat.isVerified()) {
intent.putExtra(GroupCreateActivity.GROUP_CREATE_VERIFIED_EXTRA, true);
}
startActivityForResult(intent, GROUP_EDIT);
}
private void handleDistributionBroadcastEnabled(MenuItem item) {
distributionType = ThreadDatabase.DistributionTypes.BROADCAST;
item.setChecked(true);
if (threadId != -1) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
DatabaseFactory.getThreadDatabase(ConversationActivity.this)
.setDistributionType(threadId, ThreadDatabase.DistributionTypes.BROADCAST);
return null;
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}
private void handleDistributionConversationEnabled(MenuItem item) {
distributionType = ThreadDatabase.DistributionTypes.CONVERSATION;
item.setChecked(true);
if (threadId != -1) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
DatabaseFactory.getThreadDatabase(ConversationActivity.this)
.setDistributionType(threadId, ThreadDatabase.DistributionTypes.CONVERSATION);
return null;
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}
private void handleDisplayGroupRecipients() {
//TODO: i think this button is not needed and the group options just go to the profile
//new GroupMembersDialog(this, getRecipient()).display();
}
private void handleAddToContacts() {
if (recipient.getAddress().isGroup()) return;
try {
final Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
if (recipient.getAddress().isEmail()) {
intent.putExtra(ContactsContract.Intents.Insert.EMAIL, recipient.getAddress().toEmailString());
} else {
intent.putExtra(ContactsContract.Intents.Insert.PHONE, recipient.getAddress().toPhoneString());
}
intent.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE);
startActivityForResult(intent, ADD_CONTACT);
} catch (ActivityNotFoundException e) {
Log.w(TAG, e);
}
}
private boolean handleDisplayQuickContact() {
if (recipient.getAddress().isGroup()) return false;
if (recipient.getContactUri() != null) {
ContactsContract.QuickContact.showQuickContact(ConversationActivity.this, titleView, recipient.getContactUri(), ContactsContract.QuickContact.MODE_LARGE, null);
} else {
handleAddToContacts();
}
return true;
}
private void handleAddAttachment() {
if (attachmentTypeSelector == null) {
attachmentTypeSelector = new AttachmentTypeSelector(this, getSupportLoaderManager(), new AttachmentTypeListener());
@@ -848,7 +646,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
calculateCharactersRemaining();
supportInvalidateOptionsMenu();
setBlockedUserState(recipient, isSecureText, isDefaultSms);
}
///// Initializers
@@ -987,7 +784,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
composeText = ViewUtil.findById(this, R.id.embedded_text_editor);
charactersLeft = ViewUtil.findById(this, R.id.space_left);
emojiDrawerStub = ViewUtil.findStubById(this, R.id.emoji_drawer_stub);
unblockButton = ViewUtil.findById(this, R.id.unblock_button);
composePanel = ViewUtil.findById(this, R.id.bottom_panel);
container = ViewUtil.findById(this, R.id.layout_container);
reminderView = ViewUtil.findStubById(this, R.id.reminder_stub);
@@ -1023,9 +819,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
});
titleView.setOnClickListener(v -> handleConversationSettings());
titleView.setOnLongClickListener(v -> handleDisplayQuickContact());
titleView.setOnBackClickedListener(view -> super.onBackPressed());
unblockButton.setOnClickListener(v -> handleUnblock());
composeText.setOnKeyListener(composeKeyPressedListener);
composeText.addTextChangedListener(composeKeyPressedListener);
@@ -1040,6 +834,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
quickCameraToggle.setVisibility(View.GONE);
quickCameraToggle.setEnabled(false);
}
String backgroundImagePath = TextSecurePreferences.getBackgroundImagePath(this);
if(!backgroundImagePath.isEmpty()) {
Drawable image = Drawable.createFromPath(backgroundImagePath);
getWindow().setBackgroundDrawable(image);
}
}
protected void initializeActionBar() {
@@ -1053,13 +853,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
private void initializeResources() {
if (recipient != null) recipient.removeListener(this);
threadId = getIntent().getLongExtra(THREAD_ID_EXTRA, -1);
threadId = getIntent().getIntExtra(THREAD_ID_EXTRA, -1);
if(threadId == DcChat.DC_CHAT_NO_CHAT)
throw new IllegalStateException("can't display a conversation for no chat.");
dcChat = dcContext.getChat((int)threadId);
recipient = dcContext.getRecipient(dcChat);
archived = getIntent().getBooleanExtra(IS_ARCHIVED_EXTRA, false);
distributionType = getIntent().getIntExtra(DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT);
glideRequests = GlideApp.with(this);
@@ -1069,20 +868,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
conversationContainer.setClipToPadding(true);
}
recipient.addListener(this);
}
public void onModified(final Recipient recipient) {
Log.w(TAG, "onModified(" + recipient.getAddress().serialize() + ")");
Util.runOnMain(() -> {
Log.w(TAG, "onModifiedRun(): " + recipient.getRegistered());
titleView.setTitle(glideRequests, dcChat);
setBlockedUserState(recipient, isSecureText, isDefaultSms);
setGroupShareProfileReminder(recipient);
updateReminders();
initializeSecurity(isSecureText, isDefaultSms);
invalidateOptionsMenu();
});
if(threadId==DcChat.DC_CHAT_ID_DEADDROP) {
composePanel.setVisibility(View.GONE);
titleView.hideAvatar();
}
}
private void initializeReceivers() {
@@ -1199,8 +988,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
return drafts;
}
protected ListenableFuture<Long> saveDraft() {
final SettableFuture<Long> future = new SettableFuture<>();
protected ListenableFuture<Integer> saveDraft() {
final SettableFuture<Integer> future = new SettableFuture<>();
if (this.recipient == null) {
future.set(threadId);
@@ -1208,32 +997,25 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
final Drafts drafts = getDraftsForCurrentState();
final long thisThreadId = this.threadId;
final int thisDistributionType = this.distributionType;
final int thisThreadId = this.threadId;
new AsyncTask<Long, Void, Long>() {
new AsyncTask<Integer, Void, Integer>() {
@Override
protected Long doInBackground(Long... params) {
ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(ConversationActivity.this);
DraftDatabase draftDatabase = DatabaseFactory.getDraftDatabase(ConversationActivity.this);
long threadId = params[0];
protected Integer doInBackground(Integer... params) {
int threadId = params[0];
if (drafts.size() > 0) {
if (threadId == -1) threadId = threadDatabase.getThreadIdFor(getRecipient(), thisDistributionType);
draftDatabase.insertDrafts(threadId, drafts);
threadDatabase.updateSnippet(threadId, drafts.getSnippet(ConversationActivity.this),
drafts.getUriSnippet(),
System.currentTimeMillis(), Types.BASE_DRAFT_TYPE, true);
if (drafts.size() > 0 && threadId>0) {
// todo: the following line only works for text drafts
dcContext.setDraft(dcChat.getId(), drafts.getSnippet(dcContext.context));
} else if (threadId > 0) {
threadDatabase.update(threadId, false);
dcContext.setDraft(dcChat.getId(), null);
}
return threadId;
}
@Override
protected void onPostExecute(Long result) {
protected void onPostExecute(Integer result) {
future.set(result);
}
@@ -1242,16 +1024,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
return future;
}
private void setBlockedUserState(Recipient recipient, boolean isSecureText, boolean isDefaultSms) {
if (false) { // TODO: do we need a unblock button here? typically, the chatlist is closed when blocked
unblockButton.setVisibility(View.VISIBLE);
composePanel.setVisibility(View.GONE);
} else {
composePanel.setVisibility(View.VISIBLE);
unblockButton.setVisibility(View.GONE);
}
}
private void setGroupShareProfileReminder(@NonNull Recipient recipient) {
if (recipient.isPushGroupRecipient() && !recipient.isProfileSharing()) {
groupShareProfileView.get().setRecipient(recipient);
@@ -1326,14 +1098,16 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
private void markThreadAsRead() {
new AsyncTask<Long, Void, Void>() {
new AsyncTask<Integer, Void, Void>() {
@Override
protected Void doInBackground(Long... params) {
protected Void doInBackground(Integer... params) {
Context context = ConversationActivity.this;
List<MarkedMessageInfo> messageIds = DatabaseFactory.getThreadDatabase(context).setRead(params[0], false);
ApplicationDcContext dcContext = DcHelper.getContext(context);
int[] messageIds = dcContext.getChatMsgs(((ConversationActivity) context).threadId, 0, 0);
dcContext.markseenMsgs(messageIds);
MessageNotifier.updateNotification(context);
MarkReadReceiver.process(context, messageIds);
MessageNotifier.updateNotification(context, threadId, false);
// MarkReadReceiver.process(context, messageIds);
return null;
}
@@ -1341,16 +1115,16 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
private void markLastSeen() {
new AsyncTask<Long, Void, Void>() {
new AsyncTask<Integer, Void, Void>() {
@Override
protected Void doInBackground(Long... params) {
DatabaseFactory.getThreadDatabase(ConversationActivity.this).setLastSeen(params[0]);
protected Void doInBackground(Integer... params) {
dcContext.marknoticedChat(params[0]);
return null;
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, threadId);
}
protected void sendComplete(long threadId) {
protected void sendComplete(int threadId) {
boolean refreshFragment = (threadId != this.threadId);
this.threadId = threadId;
@@ -1409,42 +1183,88 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
sendMediaMessage(forceSms, getMessage(), attachmentManager.buildSlideDeck(), Collections.emptyList(), expiresIn, subscriptionId, initiating);
}
private String getRealPathFromAttachment(Attachment attachment) {
try {
// get file in the blobdir as `<blobdir>/<name>[-<uniqueNumber>].<ext>`
String filename = attachment.getFileName();
String ext = "";
if(filename==null) {
filename = new SimpleDateFormat("yyyy-MM-dd-HH-mm").format(new Date());
ext = "."+MimeTypeMap.getSingleton().getExtensionFromMimeType(attachment.getContentType());
}
else {
int i = filename.lastIndexOf(".");
if(i>=0) {
ext = filename.substring(i);
filename = filename.substring(0, i);
}
}
String path = null;
for (int i=0; i<1000; i++) {
path = dcContext.getBlobdir()+"/"+filename+(i==0? "" : i<100? "-"+i : "-"+(new Date().getTime()+i))+ext;
if (!new File(path).exists()) {
break;
}
}
// copy content to this file
if(path!=null) {
InputStream inputStream = PartAuthority.getAttachmentStream(this, attachment.getDataUri());
OutputStream outputStream = new FileOutputStream(path);
Util.copy(inputStream, outputStream);
}
return path;
}
catch(Exception e) {
e.printStackTrace();
return null;
}
}
private ListenableFuture<Void> sendMediaMessage(final boolean forceSms, String body, SlideDeck slideDeck, List<Contact> contacts, final long expiresIn, final int subscriptionId, final boolean initiating) {
OutgoingMediaMessage outgoingMessageCandidate = new OutgoingMediaMessage(recipient, slideDeck, body, System.currentTimeMillis(), subscriptionId, expiresIn, distributionType, inputPanel.getQuote().orNull(), contacts);
final SettableFuture<Void> future = new SettableFuture<>();
final Context context = getApplicationContext();
final OutgoingMediaMessage outgoingMessage;
if (isSecureText && !forceSms) {
outgoingMessage = new OutgoingSecureMediaMessage(outgoingMessageCandidate);
} else {
outgoingMessage = outgoingMessageCandidate;
}
inputPanel.clearQuote();
attachmentManager.clear(glideRequests, false);
composeText.setText("");
final long id = fragment.stageOutgoingMessage(outgoingMessage);
new AsyncTask<Void, Void, Long>() {
@Override
protected Long doInBackground(Void... param) {
if (initiating) {
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(recipient, true);
try {
DcMsg msg = null;
List<Attachment> attachments = slideDeck.asAttachments();
for (Attachment attachment : attachments) {
String contentType = attachment.getContentType();
if (MediaUtil.isImageType(contentType)) {
msg = new DcMsg(dcContext, DcMsg.DC_MSG_IMAGE);
msg.setDimension(attachment.getWidth(), attachment.getHeight());
}
else if (MediaUtil.isAudioType(contentType)) {
msg = new DcMsg(dcContext,
attachment.isVoiceNote()? DcMsg.DC_MSG_VOICE : DcMsg.DC_MSG_AUDIO);
}
else if (MediaUtil.isVideoType(contentType)) {
msg = new DcMsg(dcContext, DcMsg.DC_MSG_VIDEO);
}
else {
msg = new DcMsg(dcContext, DcMsg.DC_MSG_FILE);
}
return MessageSender.send(context, outgoingMessage, threadId, false, () -> fragment.releaseOutgoingMessage(id));
String path = getRealPathFromAttachment(attachment);
msg.setFile(path, null);
}
@Override
protected void onPostExecute(Long result) {
sendComplete(result);
future.set(null);
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
msg.setText(body);
dcContext.sendMsg(dcChat.getId(), msg);
}
catch(Exception e) {
e.printStackTrace();
}
sendComplete(dcChat.getId());
future.set(null);
return future;
}
@@ -1741,7 +1561,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
@Override
public void setThreadId(long threadId) {
public void setThreadId(int threadId) {
this.threadId = threadId;
}
@@ -1821,7 +1641,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
@Override
public void handleEvent(int eventId, Object data1, Object data2) {
if (eventId==DcContext.DC_EVENT_CHAT_MODIFIED || eventId==DcContext.DC_EVENT_CONTACTS_CHANGED) {
onModified(recipient);
titleView.setTitle(glideRequests, dcChat);
setGroupShareProfileReminder(recipient);
updateReminders();
initializeSecurity(isSecureText, isDefaultSms);
invalidateOptionsMenu();
}
}
}
@@ -113,6 +113,14 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
return dcMsgList.length > 0;
}
public boolean isGroupChat(){
return dcChat.isGroup();
}
public String getChatName(){
return dcChat.getName();
}
@Override
public int getItemCount() {
return dcMsgList.length;
@@ -400,13 +408,5 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
recordCache.clear();
notifyDataSetChanged();
}
public void addFastRecord(@NonNull MessageRecord record) {
// TODO: i think this is not need, we simply should reload the view
}
public void releaseFastRecord(long id) {
// TODO: i think this is not need, we simply should reload the view
}
}
@@ -21,8 +21,6 @@ import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
@@ -41,10 +39,8 @@ import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.OnScrollListener;
import android.text.ClipboardManager;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -55,39 +51,32 @@ import android.view.Window;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ViewSwitcher;
import com.b44t.messenger.DcChat;
import com.b44t.messenger.DcContact;
import com.b44t.messenger.DcContext;
import com.b44t.messenger.DcEventCenter;
import com.b44t.messenger.DcMsg;
import com.bumptech.glide.request.RequestOptions;
import org.thoughtcrime.securesms.ConversationAdapter.HeaderViewHolder;
import org.thoughtcrime.securesms.ConversationAdapter.ItemClickListener;
import org.thoughtcrime.securesms.connect.ApplicationDcContext;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.connect.DcMsgListLoader;
import org.thoughtcrime.securesms.contactshare.Contact;
import org.thoughtcrime.securesms.contactshare.ContactUtil;
import org.thoughtcrime.securesms.contactshare.SharedContactDetailsActivity;
import org.thoughtcrime.securesms.contactshare.Contact;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
import org.thoughtcrime.securesms.util.CommunicationActions;
import org.thoughtcrime.securesms.util.ServiceUtil;
import org.thoughtcrime.securesms.util.StickyHeaderDecoration;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.ViewUtil;
import java.io.File;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
@@ -95,6 +84,8 @@ import java.util.List;
import java.util.Locale;
import java.util.Set;
import static org.thoughtcrime.securesms.ShareActivity.EXTRA_MSG_IDS;
@SuppressLint("StaticFieldLeak")
public class ConversationFragment extends Fragment
implements LoaderManager.LoaderCallbacks<int[]>,
@@ -124,8 +115,7 @@ public class ConversationFragment extends Fragment
private RecyclerView.ItemDecoration lastSeenDecoration;
private View scrollToBottomButton;
private TextView scrollDateHeader;
private FrameLayout frameLayout;
private TextView noMessageTextView;
private ApplicationDcContext dcContext;
@Override
@@ -148,7 +138,7 @@ public class ConversationFragment extends Fragment
list = ViewUtil.findById(view, android.R.id.list);
scrollToBottomButton = ViewUtil.findById(view, R.id.scroll_to_bottom_button);
scrollDateHeader = ViewUtil.findById(view, R.id.scroll_date_header);
frameLayout = ViewUtil.findById(view, R.id.conversation_container);
noMessageTextView = ViewUtil.findById(view, R.id.no_messages_text_view);
scrollToBottomButton.setOnClickListener(v -> scrollToBottom());
@@ -157,9 +147,12 @@ public class ConversationFragment extends Fragment
list.setLayoutManager(layoutManager);
list.setItemAnimator(null);
String backgroundImagePath = TextSecurePreferences.getBackgroundImagePath(getContext());
Drawable image = Drawable.createFromPath(backgroundImagePath);
frameLayout.setBackground(image);
// setLayerType() is needed to allow larger items (long texts in our case)
// with hardware layers, drawing may result in errors as "OpenGLRenderer: Path too large to be rendered into a texture"
if (android.os.Build.VERSION.SDK_INT >= 11)
{
list.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
return view;
}
@@ -171,6 +164,24 @@ public class ConversationFragment extends Fragment
initializeListAdapter();
}
private void setNoMessageText() {
if(threadId==DcChat.DC_CHAT_ID_DEADDROP) {
noMessageTextView.setText(R.string.conversation__no_messages);
}
else if(getListAdapter().isGroupChat()){
if( dcContext.getChat((int)threadId).isUnpromoted() ) {
noMessageTextView.setText(R.string.ConversationActivity_MsgNewGroupDraftHint);
}
else {
noMessageTextView.setText(R.string.conversation__no_messages);
}
}else{
String name = getListAdapter().getChatName();
String message = getString(R.string.ConversationActivity_NoMessagesHint, name, name);
noMessageTextView.setText(message);
}
}
@Override
public void onDestroy() {
dcContext.eventCenter.removeObservers(this);
@@ -207,7 +218,6 @@ public class ConversationFragment extends Fragment
public void moveToLastSeen() {
if (lastSeen <= 0) {
Log.i(TAG, "No need to move to last seen.");
return;
}
@@ -221,8 +231,8 @@ public class ConversationFragment extends Fragment
}
private void initializeResources() {
this.recipient = Recipient.from(getActivity(), getActivity().getIntent().getParcelableExtra(ConversationActivity.ADDRESS_EXTRA), true);
this.threadId = this.getActivity().getIntent().getLongExtra(ConversationActivity.THREAD_ID_EXTRA, -1);
this.threadId = this.getActivity().getIntent().getIntExtra(ConversationActivity.THREAD_ID_EXTRA, -1);
this.recipient = Recipient.from(getActivity(), Address.fromChat((int)this.threadId), true);
this.lastSeen = this.getActivity().getIntent().getLongExtra(ConversationActivity.LAST_SEEN_EXTRA, -1);
this.startingPosition = this.getActivity().getIntent().getIntExtra(ConversationActivity.STARTING_POSITION_EXTRA, -1);
this.firstLoad = true;
@@ -269,7 +279,7 @@ public class ConversationFragment extends Fragment
}
if (messageRecords.size() > 1) {
menu.findItem(R.id.menu_context_forward).setVisible(false);
// menu.findItem(R.id.menu_context_forward).setVisible(false);
menu.findItem(R.id.menu_context_reply).setVisible(false);
menu.findItem(R.id.menu_context_details).setVisible(false);
menu.findItem(R.id.menu_context_save_attachment).setVisible(false);
@@ -410,9 +420,11 @@ public class ConversationFragment extends Fragment
.show();
}
private void handleForwardMessage(DcMsg message) {
private void handleForwardMessage(final Set<DcMsg> messageRecords) {
Intent composeIntent = new Intent(getActivity(), ShareActivity.class);
composeIntent.putExtra(Intent.EXTRA_TEXT, message.getDisplayBody().toString());
int[] msgIds = DcMsg.msgSetToIds(messageRecords);
composeIntent.putExtra(EXTRA_MSG_IDS, msgIds);
// composeIntent.putExtra(Intent.EXTRA_TEXT, messageRecords.getDisplayBody().toString());
/* TODO: handle fowarding media
if (message.isMms()) {
MmsMessageRecord mediaMessage = (MmsMessageRecord) message;
@@ -533,6 +545,14 @@ public class ConversationFragment extends Fragment
previousOffset = 0;
}
if(!adapter.isActive()){
setNoMessageText();
noMessageTextView.setVisibility(View.VISIBLE);
}
else{
noMessageTextView.setVisibility(View.GONE);
}
if (lastSeenPosition <= 0) {
setLastSeen(0);
}
@@ -545,36 +565,6 @@ public class ConversationFragment extends Fragment
}
}
public long stageOutgoingMessage(OutgoingMediaMessage message) {
MessageRecord messageRecord = DatabaseFactory.getMmsDatabase(getContext()).readerFor(message, threadId).getCurrent();
if (getListAdapter() != null) {
//getListAdapter().setHeaderView(null);
setLastSeen(0);
getListAdapter().addFastRecord(messageRecord);
}
return messageRecord.getId();
}
public long stageOutgoingMessage(OutgoingTextMessage message) {
MessageRecord messageRecord = DatabaseFactory.getSmsDatabase(getContext()).readerFor(message, threadId).getCurrent();
if (getListAdapter() != null) {
//getListAdapter().setHeaderView(null);
setLastSeen(0);
getListAdapter().addFastRecord(messageRecord);
}
return messageRecord.getId();
}
public void releaseOutgoingMessage(long id) {
if (getListAdapter() != null) {
getListAdapter().releaseFastRecord(id);
}
}
private void scrollToStartingPosition(final int startingPosition) {
list.post(() -> {
list.getLayoutManager().scrollToPosition(startingPosition);
@@ -589,7 +579,7 @@ public class ConversationFragment extends Fragment
}
public interface ConversationFragmentListener {
void setThreadId(long threadId);
void setThreadId(int threadId);
void handleReplyMessage(MessageRecord messageRecord);
}
@@ -865,9 +855,9 @@ public class ConversationFragment extends Fragment
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CODE_ADD_EDIT_CONTACT && getContext() != null) {
ApplicationContext.getInstance(getContext().getApplicationContext())
.getJobManager()
.add(new DirectoryRefreshJob(getContext().getApplicationContext(), false));
// ApplicationContext.getInstance(getContext().getApplicationContext())
// .getJobManager()
// .add(new DirectoryRefreshJob(getContext().getApplicationContext(), false));
}
}
@@ -925,7 +915,8 @@ public class ConversationFragment extends Fragment
actionMode.finish();
return true;
case R.id.menu_context_forward:
handleForwardMessage(getSelectedMessageRecord());
// handleForwardMessage(getSelectedMessageRecord());
handleForwardMessage(getListAdapter().getSelectedItems());
actionMode.finish();
return true;
case R.id.menu_context_resend:
@@ -16,17 +16,15 @@
*/
package org.thoughtcrime.securesms;
import android.annotation.SuppressLint;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.net.Uri;
import android.support.annotation.DimenRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
@@ -39,13 +37,11 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.b44t.messenger.DcChat;
import com.b44t.messenger.DcContact;
import com.b44t.messenger.DcMsg;
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
import org.thoughtcrime.securesms.components.AlertView;
import org.thoughtcrime.securesms.components.AudioView;
import org.thoughtcrime.securesms.components.AvatarImageView;
import org.thoughtcrime.securesms.components.ConversationItemFooter;
@@ -56,18 +52,12 @@ import org.thoughtcrime.securesms.components.SharedContactView;
import org.thoughtcrime.securesms.connect.ApplicationDcContext;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.contactshare.Contact;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.jobs.AttachmentDownloadJob;
import org.thoughtcrime.securesms.mms.AudioSlide;
import org.thoughtcrime.securesms.mms.DocumentSlide;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.mms.PartAuthority;
import org.thoughtcrime.securesms.mms.Slide;
import org.thoughtcrime.securesms.mms.SlideClickListener;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.LongClickCopySpan;
import org.thoughtcrime.securesms.util.LongClickMovementMethod;
@@ -75,7 +65,6 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.views.Stub;
import org.whispersystems.libsignal.util.guava.Optional;
import java.util.HashSet;
import java.util.List;
@@ -91,16 +80,17 @@ import java.util.Set;
*/
public class ConversationItem extends LinearLayout
implements RecipientModifiedListener, BindableConversationItem
implements BindableConversationItem
{
private static final String TAG = ConversationItem.class.getSimpleName();
private static final int MAX_MEASURE_CALLS = 3;
private DcMsg messageRecord;
private DcChat dcChat;
private DcContact dcContact;
private Locale locale;
private boolean groupThread;
private Recipient recipient;
private GlideRequests glideRequests;
protected ViewGroup bodyBubble;
@@ -108,11 +98,9 @@ public class ConversationItem extends LinearLayout
private TextView bodyText;
private ConversationItemFooter footer;
private TextView groupSender;
private TextView groupSenderProfileName;
private View groupSenderHolder;
private AvatarImageView contactPhoto;
private ViewGroup contactPhotoHolder;
private AlertView alertView;
private ViewGroup container;
private @NonNull Set<DcMsg> batchSelected = new HashSet<>();
@@ -157,8 +145,6 @@ public class ConversationItem extends LinearLayout
this.bodyText = findViewById(R.id.conversation_item_body);
this.footer = findViewById(R.id.conversation_item_footer);
this.groupSender = findViewById(R.id.group_message_sender);
this.groupSenderProfileName = findViewById(R.id.group_message_sender_profile);
this.alertView = findViewById(R.id.indicators_parent);
this.contactPhoto = findViewById(R.id.contact_photo);
this.contactPhotoHolder = findViewById(R.id.contact_photo_container);
this.bodyBubble = findViewById(R.id.body_bubble);
@@ -188,15 +174,16 @@ public class ConversationItem extends LinearLayout
boolean pulseHighlight)
{
this.messageRecord = messageRecord;
this.dcChat = dcChat;
this.locale = locale;
this.glideRequests = glideRequests;
this.batchSelected = batchSelected;
this.conversationRecipient = recipients;
this.groupThread = dcChat.isGroup();
this.recipient = dcContext.getRecipient(dcContext.getChat(messageRecord.getChatId()));
this.recipient.addListener(this);
this.conversationRecipient.addListener(this);
if (groupThread && !messageRecord.isOutgoing()) {
this.dcContact = dcContext.getContact(messageRecord.getFromId());
}
setGutterSizes(messageRecord, groupThread);
setMessageShape(messageRecord, groupThread);
@@ -204,9 +191,8 @@ public class ConversationItem extends LinearLayout
setInteractionState(messageRecord, pulseHighlight);
setBodyText(messageRecord);
setBubbleState(messageRecord);
setStatusIcons(messageRecord);
setContactPhoto(recipient);
setGroupMessageStatus(messageRecord, recipient);
setContactPhoto();
setGroupMessageStatus();
setAuthor(messageRecord, groupThread);
setQuote(messageRecord, groupThread);
setMessageSpacing(context, messageRecord, groupThread);
@@ -283,9 +269,6 @@ public class ConversationItem extends LinearLayout
@Override
public void unbind() {
if (recipient != null) {
recipient.removeListener(this);
}
}
public DcMsg getMessageRecord() {
@@ -299,7 +282,11 @@ public class ConversationItem extends LinearLayout
bodyBubble.getBackground().setColorFilter(defaultBubbleColor, PorterDuff.Mode.MULTIPLY);
} else {
bodyBubble.getBackground().setColorFilter(defaultBubbleColor, PorterDuff.Mode.MULTIPLY);
bodyBubble.getBackground().setColorFilter(dcContext.getRecipient(messageRecord.getChatId()).getColor().toConversationColor(context), PorterDuff.Mode.MULTIPLY);
if(groupThread && dcContact!=null) {
bodyBubble.getBackground().setColorFilter(dcContext.getRecipient(dcContact).getColor().toConversationColor(context), PorterDuff.Mode.MULTIPLY);
} else {
bodyBubble.getBackground().setColorFilter(dcContext.getRecipient(dcChat).getColor().toConversationColor(context), PorterDuff.Mode.MULTIPLY);
}
}
if (audioViewStub.resolved()) {
@@ -405,7 +392,14 @@ public class ConversationItem extends LinearLayout
if (sharedContactStub.resolved()) sharedContactStub.get().setVisibility(GONE);
//noinspection ConstantConditions
audioViewStub.get().setAudio(new AudioSlide(context, messageRecord), showControls);
if(dcChat.getId() == DcChat.DC_CHAT_ID_DEADDROP) { // no audio on dead drops
// TODO: replace the currently defunct display of a play button with some notification text
// to inform the user that here would be audio, if this were a proper chat, then ask the user
// if he wants to start the chat on click.
audioViewStub.get().setEnabled(false);
audioViewStub.get().setOnClickListener(passthroughClickListener);
} else
audioViewStub.get().setAudio(new AudioSlide(context, messageRecord), showControls);
audioViewStub.get().setOnLongClickListener(passthroughClickListener);
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
@@ -501,13 +495,13 @@ public class ConversationItem extends LinearLayout
sharedContactStub.get().setSingularStyle();
}
private void setContactPhoto(@NonNull Recipient recipient) {
private void setContactPhoto() {
if (contactPhoto == null) return;
if (messageRecord.isOutgoing() || !groupThread) {
if (messageRecord.isOutgoing() || !groupThread || dcContact ==null) {
contactPhoto.setVisibility(View.GONE);
} else {
contactPhoto.setAvatar(glideRequests, recipient, true);
contactPhoto.setAvatar(glideRequests, dcContext.getRecipient(dcContact), true);
contactPhoto.setVisibility(View.VISIBLE);
}
}
@@ -526,17 +520,6 @@ public class ConversationItem extends LinearLayout
return messageBody;
}
private void setStatusIcons(DcMsg messageRecord) {
// disable the icon for for, we should use the same ui on desktop/ios here, so, for now
//bodyText.setCompoundDrawablesWithIntrinsicBounds(0, 0, messageRecord.isSetupMessage() ? R.drawable.ic_menu_login : 0, 0);
if (messageRecord.isFailed()) {
alertView.setFailed();
} else {
alertView.setNone();
}
}
private void setQuote(@NonNull DcMsg current, boolean isGroupThread) {
// if (current.isMms() && !current.isMmsNotification() && ((MediaMmsDcMsg)current).getQuote() != null) {
// Quote quote = ((MediaMmsDcMsg)current).getQuote();
@@ -619,43 +602,21 @@ public class ConversationItem extends LinearLayout
return batchSelected.isEmpty() && (messageRecord.isFailed());
}
@SuppressLint("SetTextI18n")
private void setGroupMessageStatus(DcMsg messageRecord, Recipient recipient) {
if (groupThread && !messageRecord.isOutgoing()) {
this.groupSender.setText(recipient.toShortString());
if (recipient.getName() == null && !TextUtils.isEmpty(recipient.getProfileName())) {
this.groupSenderProfileName.setText("~" + recipient.getProfileName());
this.groupSenderProfileName.setVisibility(View.VISIBLE);
} else {
this.groupSenderProfileName.setText(null);
this.groupSenderProfileName.setVisibility(View.GONE);
}
private void setGroupMessageStatus() {
if (groupThread && !messageRecord.isOutgoing() && dcContact !=null) {
this.groupSender.setText(dcContact.getDisplayName());
}
}
private void setAuthor(@NonNull DcMsg current, boolean isGroupThread) {
if (isGroupThread && !current.isOutgoing()) {
if (contactPhotoHolder != null) {
contactPhotoHolder.setVisibility(VISIBLE);
}
/*if (!previous.isPresent() || previous.get().isInfo() || current.getFromId() != previous.get().getFromId() ||
!DateUtils.isSameDay(previous.get().getTimestamp(), current.getTimestamp()))
{*/
groupSenderHolder.setVisibility(VISIBLE);
/*} else {
groupSenderHolder.setVisibility(GONE);
}*/
//if (!next.isPresent() || next.get().isInfo() || current.getFromId() != previous.get().getFromId()) {
contactPhoto.setVisibility(VISIBLE);
//} else {
// contactPhoto.setVisibility(GONE);
//}
groupSenderHolder.setVisibility(VISIBLE);
contactPhoto.setVisibility(VISIBLE);
} else {
groupSenderHolder.setVisibility(GONE);
if (contactPhotoHolder != null) {
contactPhotoHolder.setVisibility(GONE);
}
@@ -683,16 +644,6 @@ public class ConversationItem extends LinearLayout
/// Event handlers
@Override
public void onModified(final Recipient modified) {
Util.runOnMain(() -> {
setBubbleState(messageRecord);
setContactPhoto(recipient);
setGroupMessageStatus(messageRecord, recipient);
setAudioViewTint(messageRecord, conversationRecipient);
});
}
private class SharedContactEventListener implements SharedContactView.EventListener {
@Override
public void onAddToContactsClicked(@NonNull Contact contact) {
@@ -733,18 +684,33 @@ public class ConversationItem extends LinearLayout
}
}
private void handleDeadDropClick() {
new AlertDialog.Builder(context)
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
int chatId = dcContext.createChatByMsgId(messageRecord.getId());
if( chatId != 0 ) {
Intent intent = new Intent(context, ConversationActivity.class);
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, chatId);
context.startActivity(intent);
}
})
.setNegativeButton(android.R.string.cancel, null)
.setMessage(context.getString(R.string.new_conversation_activity__ask_start_chat_with, dcContext.getContact(messageRecord.getFromId()).getDisplayName()))
.show();
}
private class ThumbnailClickListener implements SlideClickListener {
public void onClick(final View v, final Slide slide) {
if (shouldInterceptClicks(messageRecord) || !batchSelected.isEmpty()) {
if (dcChat.getId() == DcChat.DC_CHAT_ID_DEADDROP) {
handleDeadDropClick();
} else if (shouldInterceptClicks(messageRecord) || !batchSelected.isEmpty()) {
performClick();
} else if (MediaPreviewActivity.isContentTypeSupported(slide.getContentType()) && slide.getUri() != null) {
Intent intent = new Intent(context, MediaPreviewActivity.class);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(slide.getUri(), slide.getContentType());
intent.putExtra(MediaPreviewActivity.DC_MSG_ID, slide.getDcMsgId());
intent.putExtra(MediaPreviewActivity.ADDRESS_EXTRA, conversationRecipient.getAddress());
intent.putExtra(MediaPreviewActivity.OUTGOING_EXTRA, messageRecord.isOutgoing());
intent.putExtra(MediaPreviewActivity.DATE_EXTRA, messageRecord.getTimestamp());
intent.putExtra(MediaPreviewActivity.SIZE_EXTRA, slide.asAttachment().getSize());
intent.putExtra(MediaPreviewActivity.LEFT_IS_RECENT_EXTRA, false);
context.startActivity(intent);
@@ -779,7 +745,9 @@ public class ConversationItem extends LinearLayout
}
public void onClick(View v) {
if (!shouldInterceptClicks(messageRecord) && parent != null) {
if (dcChat.getId() == DcChat.DC_CHAT_ID_DEADDROP) {
handleDeadDropClick();
} else if (!shouldInterceptClicks(messageRecord) && parent != null) {
parent.onClick(v);
}
}
@@ -17,12 +17,7 @@
package org.thoughtcrime.securesms;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.support.v7.widget.TooltipCompat;
@@ -31,13 +26,14 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.Toast;
import com.b44t.messenger.DcChat;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
import org.thoughtcrime.securesms.components.SearchToolbar;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.lock.RegistrationLockDialog;
import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.qr.QrScanHandler;
import org.thoughtcrime.securesms.search.SearchFragment;
import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.util.DynamicLanguage;
@@ -79,8 +75,6 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
initializeSearchListener();
RegistrationLockDialog.showReminderIfNecessary(this);
TooltipCompat.setTooltipText(searchAction, getText(R.string.SearchToolbar_search_for_conversations_contacts_and_messages));
}
@@ -158,29 +152,36 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
super.onOptionsItemSelected(item);
switch (item.getItemId()) {
case R.id.menu_new_chat: createChat(); return true;
case R.id.menu_settings: handleDisplaySettings(); return true;
case R.id.menu_clear_passphrase: handleClearPassphrase(); return true;
case R.id.menu_invite: handleInvite(); return true;
case R.id.menu_help: handleHelp(); return true;
case R.id.menu_new_chat: createChat(); return true;
case R.id.menu_settings: handleDisplaySettings(); return true;
case R.id.menu_clear_passphrase: handleClearPassphrase(); return true;
case R.id.menu_qr_scan: handleQrScan(); return true;
case R.id.menu_qr_show: handleQrShow(); return true;
case R.id.menu_deaddrop: handleDeaddrop(); return true;
}
return false;
}
@Override
public void onCreateConversation(long threadId, Recipient recipient, int distributionType, long lastSeen) {
openConversation(threadId, recipient, distributionType, lastSeen, -1);
private void handleQrScan() {
new IntentIntegrator(this).setCaptureActivity(QrScanActivity.class).initiateScan();
}
public void openConversation(long threadId, Recipient recipient, int distributionType, long lastSeen, int startingPosition) {
private void handleQrShow() {
Intent qrIntent = new Intent(this, QrShowActivity.class);
startActivity(qrIntent);
}
@Override
public void onCreateConversation(int threadId, long lastSeen) {
openConversation(threadId, lastSeen, -1);
}
public void openConversation(int threadId, long lastSeen, int startingPosition) {
searchToolbar.clearFocus();
Intent intent = new Intent(this, ConversationActivity.class);
intent.putExtra(ConversationActivity.ADDRESS_EXTRA, recipient.getAddress());
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, distributionType);
intent.putExtra(ConversationActivity.TIMING_EXTRA, System.currentTimeMillis());
intent.putExtra(ConversationActivity.LAST_SEEN_EXTRA, lastSeen);
intent.putExtra(ConversationActivity.STARTING_POSITION_EXTRA, startingPosition);
@@ -205,6 +206,12 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
startActivity(intent);
}
private void handleDeaddrop() {
Intent intent = new Intent(this, ConversationActivity.class);
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, DcChat.DC_CHAT_ID_DEADDROP);
startActivity(intent);
}
private void handleDisplaySettings() {
Intent preferencesIntent = new Intent(this, ApplicationPreferencesActivity.class);
startActivity(preferencesIntent);
@@ -216,15 +223,13 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
startService(intent);
}
private void handleInvite() {
startActivity(new Intent(this, InviteActivity.class));
}
private void handleHelp() {
try {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.help_url))));
} catch (ActivityNotFoundException e) {
Toast.makeText(this, R.string.ConversationListActivity_there_is_no_browser_installed_on_your_device, Toast.LENGTH_LONG).show();
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == IntentIntegrator.REQUEST_CODE) {
IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
QrScanHandler qrScanHandler = new QrScanHandler(this);
qrScanHandler.onScanPerformed(scanResult);
}
}
}
@@ -48,6 +48,7 @@ class ConversationListAdapter extends RecyclerView.Adapter {
private static final int MESSAGE_TYPE_SWITCH_ARCHIVE = 1;
private static final int MESSAGE_TYPE_THREAD = 2;
private static final int MESSAGE_TYPE_INBOX_ZERO = 3;
private static final int MESSAGE_TYPE_DEADDROP = 4; // DEADDROP and THREAD share the same class, however, for DEADDROP it is modified on construction so it cannot be reused
private final @NonNull ApplicationDcContext dcContext;
private @NonNull DcChatlist dcChatlist;
@@ -131,14 +132,17 @@ class ConversationListAdapter extends RecyclerView.Adapter {
ViewHolder holder = (ViewHolder)viewHolder;
DcChat chat = dcContext.getChat(dcChatlist.getChatId(i));
DcLot summary = dcChatlist.getSummary(i, chat);
holder.getItem().bind(dcContext.getThreadRecord(summary, chat), summary, glideRequests, locale, batchSet, batchMode);
holder.getItem().bind(dcContext.getThreadRecord(summary, chat), dcChatlist.getMsgId(i), summary, glideRequests, locale, batchSet, batchMode);
}
@Override
public int getItemViewType(int i) {
int chatId = dcChatlist.getChatId(i);
if (chatId == DcChat.DC_CHAT_ID_ARCHIVED_LINK) {
if (chatId==DcChat.DC_CHAT_ID_DEADDROP) {
return MESSAGE_TYPE_DEADDROP;
}
else if (chatId == DcChat.DC_CHAT_ID_ARCHIVED_LINK) {
return MESSAGE_TYPE_SWITCH_ARCHIVE;
} else if(chatId == DcChat.DC_CHAT_ID_ALLDONE_HINT) {
return MESSAGE_TYPE_INBOX_ZERO;
@@ -51,12 +51,10 @@ public class ConversationListArchiveActivity extends PassphraseRequiredActionBar
}
@Override
public void onCreateConversation(long threadId, Recipient recipient, int distributionType, long lastSeenTime) {
public void onCreateConversation(int threadId, long lastSeenTime) {
Intent intent = new Intent(this, ConversationActivity.class);
intent.putExtra(ConversationActivity.ADDRESS_EXTRA, recipient.getAddress());
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
intent.putExtra(ConversationActivity.IS_ARCHIVED_EXTRA, true);
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, distributionType);
intent.putExtra(ConversationActivity.LAST_SEEN_EXTRA, lastSeenTime);
startActivity(intent);
@@ -50,13 +50,12 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.b44t.messenger.DcChat;
import com.b44t.messenger.DcChatlist;
import com.b44t.messenger.DcContact;
import com.b44t.messenger.DcContext;
import com.b44t.messenger.DcEventCenter;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.thoughtcrime.securesms.ConversationListAdapter.ItemClickListener;
import org.thoughtcrime.securesms.components.recyclerview.DeleteItemAnimator;
import org.thoughtcrime.securesms.components.registration.PulsingFloatingActionButton;
@@ -69,9 +68,7 @@ import org.thoughtcrime.securesms.components.reminder.ShareReminder;
import org.thoughtcrime.securesms.connect.ApplicationDcContext;
import org.thoughtcrime.securesms.connect.DcChatlistLoader;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.events.ReminderUpdateEvent;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.task.SnackbarAsyncTask;
import org.whispersystems.libsignal.util.guava.Optional;
@@ -159,7 +156,6 @@ public class ConversationListFragment extends Fragment
updateReminders(true);
list.getAdapter().notifyDataSetChanged();
EventBus.getDefault().register(this);
}
@Override
@@ -167,7 +163,6 @@ public class ConversationListFragment extends Fragment
super.onPause();
fab.stopPulse();
EventBus.getDefault().unregister(this);
}
public ConversationListAdapter getListAdapter() {
@@ -270,10 +265,7 @@ public class ConversationListFragment extends Fragment
final DcContext dcContext = DcHelper.getContext(getActivity());
int conversationsCount = getListAdapter().getBatchSelections().size();
AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
alert.setIconAttribute(R.attr.dialog_alert_icon);
alert.setTitle(getActivity().getResources().getQuantityString(R.plurals.ConversationListFragment_delete_selected_conversations,
conversationsCount, conversationsCount));
alert.setMessage(getActivity().getResources().getQuantityString(R.plurals.ConversationListFragment_this_will_permanently_delete_all_n_selected_conversations,
alert.setMessage(getActivity().getResources().getQuantityString(R.plurals.ConversationListFragment_ask_selected_chats,
conversationsCount, conversationsCount));
alert.setCancelable(true);
@@ -322,8 +314,8 @@ public class ConversationListFragment extends Fragment
actionMode.setTitle(String.valueOf(getListAdapter().getBatchSelections().size()));
}
private void handleCreateConversation(long threadId, Recipient recipient, int distributionType, long lastSeen) {
((ConversationSelectedListener)getActivity()).onCreateConversation(threadId, recipient, distributionType, lastSeen);
private void handleCreateConversation(int threadId, long lastSeen) {
((ConversationSelectedListener)getActivity()).onCreateConversation(threadId, lastSeen);
}
@Override
@@ -368,8 +360,31 @@ public class ConversationListFragment extends Fragment
@Override
public void onItemClick(ConversationListItem item) {
if (actionMode == null) {
handleCreateConversation(item.getThreadId(), item.getRecipient(),
item.getDistributionType(), item.getLastSeen());
// the next line will fail for signal calls, DC uses int, though.
int threadId = (int)item.getThreadId();
if (threadId==DcChat.DC_CHAT_ID_DEADDROP) {
DcContext dcContext = DcHelper.getContext(getActivity());
int msgId = item.getMsgId();
int contactId = item.getContactId();
DcContact contact = dcContext.getContact(contactId);
new AlertDialog.Builder(getActivity())
.setMessage(getActivity().getString(R.string.new_conversation_activity__ask_start_chat_with, contact.getNameNAddr()))
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
int belongingChatId = dcContext.createChatByMsgId(msgId);
if( belongingChatId != 0 ) {
handleCreateConversation(belongingChatId, 0);
}
})
.setNegativeButton(R.string.not_now, null)
.setNeutralButton(R.string.never, (dialog, which) -> {
dcContext.blockContact(contactId, 1);
})
.show();
return;
}
handleCreateConversation(threadId, item.getLastSeen());
} else {
ConversationListAdapter adapter = (ConversationListAdapter)list.getAdapter();
adapter.toggleThreadInBatchSet(item.getThreadId());
@@ -399,7 +414,7 @@ public class ConversationListFragment extends Fragment
}
public interface ConversationSelectedListener {
void onCreateConversation(long threadId, Recipient recipient, int distributionType, long lastSeen);
void onCreateConversation(int threadId, long lastSeen);
void onSwitchToArchive();
}
@@ -450,11 +465,6 @@ public class ConversationListFragment extends Fragment
actionMode = null;
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(ReminderUpdateEvent event) {
updateReminders(false);
}
private class ArchiveListenerCallback extends ItemTouchHelper.SimpleCallback {
ArchiveListenerCallback() {
@@ -506,6 +516,12 @@ public class ConversationListFragment extends Fragment
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, threadId);
} else {
if (threadId==DcChat.DC_CHAT_ID_DEADDROP) {
int contactId = ((ConversationListItem)viewHolder.itemView).getContactId();
dcContext.marknoticedContact(contactId);
return;
}
new SnackbarAsyncTask<Long>(getView(),
getResources().getQuantityString(R.plurals.ConversationListFragment_conversations_archived, 1, 1),
getString(R.string.ConversationListFragment_undo),
@@ -17,12 +17,9 @@
package org.thoughtcrime.securesms;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.RippleDrawable;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.Spannable;
@@ -38,22 +35,24 @@ import android.widget.TextView;
import com.amulyakhare.textdrawable.TextDrawable;
import com.annimon.stream.Stream;
import com.b44t.messenger.DcChat;
import com.b44t.messenger.DcContact;
import com.b44t.messenger.DcContext;
import com.b44t.messenger.DcLot;
import com.b44t.messenger.DcMsg;
import org.thoughtcrime.securesms.components.AlertView;
import org.thoughtcrime.securesms.components.AvatarImageView;
import org.thoughtcrime.securesms.components.DeliveryStatusView;
import org.thoughtcrime.securesms.components.FromTextView;
import org.thoughtcrime.securesms.components.ThumbnailView;
import org.thoughtcrime.securesms.connect.ApplicationDcContext;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.database.model.ThreadRecord;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
import org.thoughtcrime.securesms.search.model.MessageResult;
import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.ResUtil;
import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import java.util.Collections;
@@ -62,8 +61,7 @@ import java.util.Locale;
import java.util.Set;
public class ConversationListItem extends RelativeLayout
implements RecipientModifiedListener,
BindableConversationListItem, Unbindable
implements BindableConversationListItem, Unbindable
{
@SuppressWarnings("unused")
private final static String TAG = ConversationListItem.class.getSimpleName();
@@ -75,21 +73,19 @@ public class ConversationListItem extends RelativeLayout
private Set<Long> selectedThreads;
private Recipient recipient;
private long threadId;
private int msgId;
private GlideRequests glideRequests;
private TextView subjectView;
private FromTextView fromView;
private TextView dateView;
private TextView archivedView;
private DeliveryStatusView deliveryStatusIndicator;
private AlertView alertView;
private ImageView unreadIndicator;
private ImageView groupIndicator;
private long lastSeen;
private int unreadCount;
private AvatarImageView contactPhotoImage;
private ThumbnailView thumbnailView;
private int distributionType;
public ConversationListItem(Context context) {
this(context, null);
@@ -103,15 +99,13 @@ public class ConversationListItem extends RelativeLayout
protected void onFinishInflate() {
super.onFinishInflate();
this.subjectView = findViewById(R.id.subject);
this.fromView = findViewById(R.id.from);
this.fromView = findViewById(R.id.from_text);
this.dateView = findViewById(R.id.date);
this.deliveryStatusIndicator = findViewById(R.id.delivery_status);
this.alertView = findViewById(R.id.indicators_parent);
this.contactPhotoImage = findViewById(R.id.contact_photo_image);
this.thumbnailView = findViewById(R.id.thumbnail);
this.archivedView = findViewById(R.id.archived);
this.unreadIndicator = findViewById(R.id.unread_indicator);
thumbnailView.setClickable(false);
this.groupIndicator = findViewById(R.id.group_indicator);
ViewUtil.setTextViewGravityStart(this.fromView, getContext());
ViewUtil.setTextViewGravityStart(this.subjectView, getContext());
@@ -119,16 +113,18 @@ public class ConversationListItem extends RelativeLayout
@Override
public void bind(@NonNull ThreadRecord thread,
int msgId,
@NonNull DcLot dcSummary,
@NonNull GlideRequests glideRequests,
@NonNull Locale locale,
@NonNull Set<Long> selectedThreads,
boolean batchMode)
{
bind(thread, dcSummary, glideRequests, locale, selectedThreads, batchMode, null);
bind(thread, msgId, dcSummary, glideRequests, locale, selectedThreads, batchMode, null);
}
public void bind(@NonNull ThreadRecord thread,
int msgId,
@NonNull DcLot dcSummary,
@NonNull GlideRequests glideRequests,
@NonNull Locale locale,
@@ -140,12 +136,11 @@ public class ConversationListItem extends RelativeLayout
this.selectedThreads = selectedThreads;
this.recipient = thread.getRecipient();
this.threadId = thread.getThreadId();
this.msgId = msgId;
this.glideRequests = glideRequests;
this.unreadCount = thread.getUnreadCount();
this.distributionType = thread.getDistributionType();
this.lastSeen = thread.getLastSeen();
this.recipient.addListener(this);
if (highlightSubstring != null) {
this.fromView.setText(getHighlightedSpan(locale, recipient.getName(), highlightSubstring));
} else {
@@ -160,23 +155,24 @@ public class ConversationListItem extends RelativeLayout
if (thread.getDate() > 0) {
CharSequence date = DateUtils.getBriefRelativeTimeSpanString(getContext(), locale, thread.getDate());
dateView.setText(date);
dateView.setTypeface(unreadCount == 0 ? LIGHT_TYPEFACE : BOLD_TYPEFACE);
dateView.setTextColor(unreadCount == 0 ? ThemeUtil.getThemedColor(getContext(), R.attr.conversation_list_item_date_color)
: ThemeUtil.getThemedColor(getContext(), R.attr.conversation_list_item_unread_color));
}
if (thread.isArchived()) {
this.archivedView.setVisibility(View.VISIBLE);
} else {
this.archivedView.setVisibility(View.GONE);
}
setStatusIcons(thread);
setThumbnailSnippet(thread);
setBatchState(batchMode);
setRippleColor(recipient);
setUnreadIndicator(thread);
this.contactPhotoImage.setAvatar(glideRequests, recipient, true);
setBgColor();
if(threadId==DcChat.DC_CHAT_ID_DEADDROP) {
ApplicationDcContext dcContext = DcHelper.getContext(getContext());
DcContact dcContact = dcContext.getContact(dcContext.getMsg(msgId).getFromId());
this.contactPhotoImage.setAvatar(glideRequests, dcContext.getRecipient(dcContact), true);
}
else {
this.contactPhotoImage.setAvatar(glideRequests, recipient, true);
}
fromView.setCompoundDrawablesWithIntrinsicBounds(0, 0, thread.isVerified() ? R.drawable.ic_verified : 0, 0);
groupIndicator.setVisibility(recipient.isGroupRecipient() ? VISIBLE : GONE);
int color = ResUtil.getColor(getContext(), R.attr.conversation_list_item_contact_color);
groupIndicator.setColorFilter(color);
}
public void bind(@NonNull Recipient contact,
@@ -188,19 +184,15 @@ public class ConversationListItem extends RelativeLayout
this.recipient = contact;
this.glideRequests = glideRequests;
this.recipient.addListener(this);
fromView.setText(getHighlightedSpan(locale, recipient.getName(), highlightSubstring));
subjectView.setText(getHighlightedSpan(locale, contact.getAddress().toPhoneString(), highlightSubstring));
dateView.setText("");
archivedView.setVisibility(GONE);
unreadIndicator.setVisibility(GONE);
deliveryStatusIndicator.setNone();
alertView.setNone();
thumbnailView.setVisibility(GONE);
setBatchState(false);
setRippleColor(contact);
setBgColor();
contactPhotoImage.setAvatar(glideRequests, recipient, true);
}
@@ -213,25 +205,20 @@ public class ConversationListItem extends RelativeLayout
this.recipient = messageResult.recipient;
this.glideRequests = glideRequests;
this.recipient.addListener(this);
fromView.setText(recipient, true);
subjectView.setText(getHighlightedSpan(locale, messageResult.bodySnippet, highlightSubstring));
dateView.setText(DateUtils.getBriefRelativeTimeSpanString(getContext(), locale, messageResult.receivedTimestampMs));
archivedView.setVisibility(GONE);
unreadIndicator.setVisibility(GONE);
deliveryStatusIndicator.setNone();
alertView.setNone();
thumbnailView.setVisibility(GONE);
setBatchState(false);
setRippleColor(recipient);
setBgColor();
contactPhotoImage.setAvatar(glideRequests, recipient, true);
}
@Override
public void unbind() {
if (this.recipient != null) this.recipient.removeListener(this);
}
private void setBatchState(boolean batch) {
@@ -246,90 +233,76 @@ public class ConversationListItem extends RelativeLayout
return threadId;
}
public int getUnreadCount() {
return unreadCount;
public int getMsgId() {
return msgId;
}
public int getDistributionType() {
return distributionType;
public int getContactId() {
DcContext dcContext = DcHelper.getContext(getContext());
return dcContext.getMsg(msgId).getFromId();
}
public long getLastSeen() {
return lastSeen;
}
private void setThumbnailSnippet(ThreadRecord thread) {
if (thread.getSnippetUri() != null) {
this.thumbnailView.setVisibility(View.VISIBLE);
this.thumbnailView.setImageResource(glideRequests, thread.getSnippetUri());
LayoutParams subjectParams = (RelativeLayout.LayoutParams)this.subjectView.getLayoutParams();
subjectParams.addRule(RelativeLayout.LEFT_OF, R.id.thumbnail);
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
subjectParams.addRule(RelativeLayout.START_OF, R.id.thumbnail);
}
this.subjectView.setLayoutParams(subjectParams);
this.post(new ThumbnailPositioner(thumbnailView, archivedView, deliveryStatusIndicator, dateView));
} else {
this.thumbnailView.setVisibility(View.GONE);
LayoutParams subjectParams = (RelativeLayout.LayoutParams)this.subjectView.getLayoutParams();
subjectParams.addRule(RelativeLayout.LEFT_OF, R.id.status);
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
subjectParams.addRule(RelativeLayout.START_OF, R.id.status);
}
this.subjectView.setLayoutParams(subjectParams);
}
}
private void setStatusIcons(ThreadRecord thread) {
int state = dcSummary.getState();
if (state==DcMsg.DC_STATE_IN_FRESH || state==DcMsg.DC_STATE_IN_NOTICED) {
if (thread.isArchived())
{
// archived
this.archivedView.setVisibility(View.VISIBLE);
deliveryStatusIndicator.setNone();
alertView.setNone();
} else if (state==DcMsg.DC_STATE_OUT_ERROR) {
deliveryStatusIndicator.setNone();
alertView.setFailed();
} else {
alertView.setNone();
if(state==DcMsg.DC_STATE_OUT_MDN_RCVD) {
deliveryStatusIndicator.setRead();
}
else if(state==DcMsg.DC_STATE_OUT_DELIVERED) {
deliveryStatusIndicator.setSent();
}
else if (state==DcMsg.DC_STATE_OUT_PENDING){
deliveryStatusIndicator.setPending();
}
else {
deliveryStatusIndicator.setNone();
}
}
}
private void setRippleColor(Recipient recipient) {
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
((RippleDrawable)(getBackground()).mutate())
.setColor(ColorStateList.valueOf(recipient.getColor().toConversationColor(getContext())));
}
}
private void setUnreadIndicator(ThreadRecord thread) {
if (thread.getUnreadCount() == 0) {
unreadIndicator.setVisibility(View.GONE);
return;
}
else
{
this.archivedView.setVisibility(View.GONE);
int state = dcSummary.getState();
if (state==DcMsg.DC_STATE_IN_FRESH || state==DcMsg.DC_STATE_IN_NOTICED)
{
// incoming
deliveryStatusIndicator.setNone();
int unreadCount = thread.getUnreadCount();
if(unreadCount==0) {
unreadIndicator.setVisibility(View.GONE);
}
else {
unreadIndicator.setImageDrawable(TextDrawable.builder()
.beginConfig()
.width(ViewUtil.dpToPx(getContext(), 24))
.height(ViewUtil.dpToPx(getContext(), 24))
.textColor(Color.WHITE)
.bold()
.endConfig()
.buildRound(String.valueOf(unreadCount), getResources().getColor(R.color.green_A700)));
unreadIndicator.setVisibility(View.VISIBLE);
}
}
else
{
// outgoing
unreadIndicator.setVisibility(View.GONE);
if (state == DcMsg.DC_STATE_OUT_ERROR) {
deliveryStatusIndicator.setFailed();
} else if (state == DcMsg.DC_STATE_OUT_MDN_RCVD) {
deliveryStatusIndicator.setRead();
} else if (state == DcMsg.DC_STATE_OUT_DELIVERED) {
deliveryStatusIndicator.setSent();
} else if (state == DcMsg.DC_STATE_OUT_PENDING) {
deliveryStatusIndicator.setPending();
} else {
deliveryStatusIndicator.setNone();
}
}
}
}
unreadIndicator.setImageDrawable(TextDrawable.builder()
.beginConfig()
.width(ViewUtil.dpToPx(getContext(), 24))
.height(ViewUtil.dpToPx(getContext(), 24))
.textColor(Color.WHITE)
.bold()
.endConfig()
.buildRound(String.valueOf(thread.getUnreadCount()), getResources().getColor(R.color.green_A700)));
unreadIndicator.setVisibility(View.VISIBLE);
private void setBgColor() {
if(threadId==DcChat.DC_CHAT_ID_DEADDROP) {
TypedArray ta = getContext().obtainStyledAttributes(new int[] { R.attr.conversation_list_deaddrop_bg_color});
setBackgroundColor(ta.getColor(0, 0xffffffff));
ta.recycle();
}
}
private Spanned getHighlightedSpan(@NonNull Locale locale,
@@ -369,50 +342,4 @@ public class ConversationListItem extends RelativeLayout
return spanned;
}
@Override
public void onModified(final Recipient recipient) {
Util.runOnMain(() -> {
fromView.setText(recipient, unreadCount == 0);
contactPhotoImage.setAvatar(glideRequests, recipient, true);
setRippleColor(recipient);
});
}
private static class ThumbnailPositioner implements Runnable {
private final View thumbnailView;
private final View archivedView;
private final View deliveryStatusView;
private final View dateView;
ThumbnailPositioner(View thumbnailView, View archivedView, View deliveryStatusView, View dateView) {
this.thumbnailView = thumbnailView;
this.archivedView = archivedView;
this.deliveryStatusView = deliveryStatusView;
this.dateView = dateView;
}
@Override
public void run() {
LayoutParams thumbnailParams = (RelativeLayout.LayoutParams)thumbnailView.getLayoutParams();
if (archivedView.getVisibility() == View.VISIBLE &&
(archivedView.getWidth() + deliveryStatusView.getWidth()) > dateView.getWidth())
{
thumbnailParams.addRule(RelativeLayout.LEFT_OF, R.id.status);
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
thumbnailParams.addRule(RelativeLayout.START_OF, R.id.status);
}
} else {
thumbnailParams.addRule(RelativeLayout.LEFT_OF, R.id.date);
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
thumbnailParams.addRule(RelativeLayout.START_OF, R.id.date);
}
}
thumbnailView.setLayoutParams(thumbnailParams);
}
}
}
@@ -42,7 +42,7 @@ public class ConversationListItemAction extends LinearLayout implements Bindable
}
@Override
public void bind(@NonNull ThreadRecord thread, @NonNull DcLot dcSummary, @NonNull GlideRequests glideRequests, @NonNull Locale locale, @NonNull Set<Long> selectedThreads, boolean batchMode) {
public void bind(@NonNull ThreadRecord thread, int msgId, @NonNull DcLot dcSummary, @NonNull GlideRequests glideRequests, @NonNull Locale locale, @NonNull Set<Long> selectedThreads, boolean batchMode) {
this.description.setText(thread.getRecipient().getName());
}
@@ -41,7 +41,7 @@ public class ConversationListItemInboxZero extends LinearLayout implements Binda
}
@Override
public void bind(@NonNull ThreadRecord thread, @NonNull DcLot dcSummary, @NonNull GlideRequests glideRequests, @NonNull Locale locale, @NonNull Set<Long> selectedThreads, boolean batchMode) {
public void bind(@NonNull ThreadRecord thread, int msgId, @NonNull DcLot dcSummary, @NonNull GlideRequests glideRequests, @NonNull Locale locale, @NonNull Set<Long> selectedThreads, boolean batchMode) {
}
}
@@ -77,12 +77,11 @@ public class ConversationPopupActivity extends ConversationActivity {
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_expand:
saveDraft().addListener(new ListenableFuture.Listener<Long>() {
saveDraft().addListener(new ListenableFuture.Listener<Integer>() {
@Override
public void onSuccess(Long result) {
public void onSuccess(Integer result) {
ActivityOptionsCompat transition = ActivityOptionsCompat.makeScaleUpAnimation(getWindow().getDecorView(), 0, 0, getWindow().getAttributes().width, getWindow().getAttributes().height);
Intent intent = new Intent(ConversationPopupActivity.this, ConversationActivity.class);
intent.putExtra(ConversationActivity.ADDRESS_EXTRA, getRecipient().getAddress());
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, result);
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {
@@ -113,7 +112,7 @@ public class ConversationPopupActivity extends ConversationActivity {
}
@Override
protected void sendComplete(long threadId) {
protected void sendComplete(int threadId) {
super.sendComplete(threadId);
finish();
}
@@ -26,7 +26,6 @@ public class ConversationTitleView extends RelativeLayout {
private AvatarImageView avatar;
private TextView title;
private TextView subtitle;
private ImageView verified;
public ConversationTitleView(Context context) {
this(context, null);
@@ -45,7 +44,6 @@ public class ConversationTitleView extends RelativeLayout {
this.content = ViewUtil.findById(this, R.id.content);
this.title = ViewUtil.findById(this, R.id.title);
this.subtitle = ViewUtil.findById(this, R.id.subtitle);
this.verified = ViewUtil.findById(this, R.id.verified_indicator);
this.avatar = ViewUtil.findById(this, R.id.contact_photo_image);
ViewUtil.setTextViewGravityStart(this.title, getContext());
@@ -61,7 +59,7 @@ public class ConversationTitleView extends RelativeLayout {
} else if (recipient != null && recipient.isMuted()) {
title.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_volume_off_white_18dp, 0, 0, 0);
} else*/ {
title.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
//title.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
}
if (dcChat != null) {
@@ -70,7 +68,11 @@ public class ConversationTitleView extends RelativeLayout {
}
public void setVerified(boolean verified) {
this.verified.setVisibility(verified ? View.VISIBLE : View.GONE);
title.setCompoundDrawablesWithIntrinsicBounds(0, 0, verified ? R.drawable.ic_verified : 0, 0);
}
public void hideAvatar() {
avatar.setVisibility(View.GONE);
}
@Override
@@ -1,15 +1,12 @@
package org.thoughtcrime.securesms;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -17,24 +14,16 @@ import android.widget.TextView;
import com.b44t.messenger.DcChat;
import com.b44t.messenger.DcMsg;
import org.thoughtcrime.securesms.crypto.IdentityKeyParcelable;
import org.thoughtcrime.securesms.database.IdentityDatabase;
import org.thoughtcrime.securesms.database.IdentityDatabase.IdentityRecord;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.ExpirationUtil;
import org.thoughtcrime.securesms.util.GroupUtil;
import org.thoughtcrime.securesms.util.IdentityUtil;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.concurrent.ListenableFuture;
import org.whispersystems.libsignal.util.guava.Optional;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.ExecutionException;
public class ConversationUpdateItem extends LinearLayout
implements RecipientModifiedListener, BindableConversationItem
@@ -67,8 +56,6 @@ public class ConversationUpdateItem extends LinearLayout
this.title = findViewById(R.id.conversation_update_title);
this.body = findViewById(R.id.conversation_update_body);
this.date = findViewById(R.id.conversation_update_date);
this.setOnClickListener(new InternalClickListener(null));
}
@Override
@@ -97,7 +84,7 @@ public class ConversationUpdateItem extends LinearLayout
private void bind(@NonNull DcMsg messageRecord, @NonNull Locale locale) {
this.messageRecord = messageRecord;
this.sender = messageRecord.getIndividualRecipient();
this.sender = Recipient.fromMsg(DcHelper.getContext(getContext()), messageRecord.getId());
this.locale = locale;
this.sender.addListener(this);
@@ -202,58 +189,10 @@ public class ConversationUpdateItem extends LinearLayout
Util.runOnMain(() -> bind(messageRecord, locale));
}
@Override
public void setOnClickListener(View.OnClickListener l) {
super.setOnClickListener(new InternalClickListener(l));
}
@Override
public void unbind() {
if (sender != null) {
sender.removeListener(this);
}
}
private class InternalClickListener implements View.OnClickListener {
@Nullable private final View.OnClickListener parent;
InternalClickListener(@Nullable View.OnClickListener parent) {
this.parent = parent;
}
@Override
public void onClick(View v) {
if ((!messageRecord.isIdentityUpdate() &&
!messageRecord.isIdentityDefault() &&
!messageRecord.isIdentityVerified()) ||
!batchSelected.isEmpty())
{
if (parent != null) parent.onClick(v);
return;
}
final Recipient sender = ConversationUpdateItem.this.sender;
IdentityUtil.getRemoteIdentityKey(getContext(), sender).addListener(new ListenableFuture.Listener<Optional<IdentityRecord>>() {
@Override
public void onSuccess(Optional<IdentityRecord> result) {
if (result.isPresent()) {
Intent intent = new Intent(getContext(), VerifyIdentityActivity.class);
intent.putExtra(VerifyIdentityActivity.ADDRESS_EXTRA, sender.getAddress());
intent.putExtra(VerifyIdentityActivity.IDENTITY_EXTRA, new IdentityKeyParcelable(result.get().getIdentityKey()));
intent.putExtra(VerifyIdentityActivity.VERIFIED_EXTRA, result.get().getVerifiedStatus() == IdentityDatabase.VerifiedStatus.VERIFIED);
getContext().startActivity(intent);
}
}
@Override
public void onFailure(ExecutionException e) {
Log.w(TAG, e);
}
});
}
}
}
@@ -22,6 +22,8 @@ import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewAnimationUtils;
@@ -32,17 +34,13 @@ import android.widget.TextView;
import android.widget.Toast;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.dd.CircularProgressButton;
import com.soundcloud.android.crop.Crop;
import org.thoughtcrime.securesms.components.InputAwareLayout;
import org.thoughtcrime.securesms.components.emoji.EmojiDrawer;
import org.thoughtcrime.securesms.components.emoji.EmojiToggle;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.contacts.avatars.ResourceContactPhoto;
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.jobs.MultiDeviceProfileKeyUpdateJob;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.profiles.AvatarHelper;
@@ -76,7 +74,7 @@ import javax.inject.Inject;
import static android.provider.MediaStore.EXTRA_OUTPUT;
@SuppressLint("StaticFieldLeak")
public class CreateProfileActivity extends BaseActionBarActivity implements InjectableType {
public class CreateProfileActivity extends BaseActionBarActivity {
private static final String TAG = CreateProfileActivity.class.getSimpleName();
@@ -92,17 +90,17 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
private InputAwareLayout container;
private ImageView avatar;
private CircularProgressButton finishButton;
private EditText name;
private EmojiToggle emojiToggle;
private EmojiDrawer emojiDrawer;
private TextInputEditText statusView;
private View reveal;
private MenuItem finishMenuItem;
private Intent nextIntent;
private byte[] avatarBytes;
private File captureFile;
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
@@ -115,6 +113,7 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
getSupportActionBar().setTitle(R.string.CreateProfileActivity_your_profile_info);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_close_white_24dp);
initializeResources();
initializeEmojiInput();
@@ -125,6 +124,14 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
ApplicationContext.getInstance(this).injectDependencies(this);
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuInflater inflater = this.getMenuInflater();
inflater.inflate(R.menu.preferences_create_profile_menu, menu);
finishMenuItem = menu.findItem(R.id.menu_create_profile);
return true;
}
@Override
public void onResume() {
super.onResume();
@@ -139,6 +146,9 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
case android.R.id.home:
onBackPressed();
return true;
case R.id.menu_create_profile:
handleUpload();
break;
}
return false;
@@ -226,11 +236,9 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
TextView informationLabel = ViewUtil.findById(this, R.id.information_label);
this.avatar = ViewUtil.findById(this, R.id.avatar);
this.name = ViewUtil.findById(this, R.id.name);
this.emojiToggle = ViewUtil.findById(this, R.id.emoji_toggle);
this.name = ViewUtil.findById(this, R.id.name_text);
this.emojiDrawer = ViewUtil.findById(this, R.id.emoji_drawer);
this.container = ViewUtil.findById(this, R.id.container);
this.finishButton = ViewUtil.findById(this, R.id.finish_button);
this.reveal = ViewUtil.findById(this, R.id.reveal);
this.statusView = ViewUtil.findById(this, R.id.status_text);
this.nextIntent = getIntent().getParcelableExtra(NEXT_INTENT);
@@ -250,20 +258,15 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
public void onTextChanged(CharSequence s, int start, int before, int count) {}
@Override
public void afterTextChanged(Editable s) {
if (s.toString().getBytes().length > ProfileCipher.NAME_PADDED_LENGTH) {
name.setError(getString(R.string.CreateProfileActivity_too_long));
finishButton.setEnabled(false);
} else if (name.getError() != null || !finishButton.isEnabled()) {
name.setError(null);
finishButton.setEnabled(true);
}
}
});
this.finishButton.setOnClickListener(view -> {
this.finishButton.setIndeterminateProgressMode(true);
this.finishButton.setProgress(50);
handleUpload();
if(finishMenuItem != null){
if (s.toString().getBytes().length > ProfileCipher.NAME_PADDED_LENGTH) {
name.setError(getString(R.string.CreateProfileActivity_too_long));
finishMenuItem.setEnabled(false);
} else if (name.getError() != null || !finishMenuItem.isEnabled()) {
name.setError(null);
finishMenuItem.setEnabled(true);
}
}}
});
passwordAccountSettings.setOnClickListener(view -> {
@@ -303,7 +306,7 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
private void initializeProfileAvatar(boolean excludeSystem) {
String address = DcHelper.get(this, DcHelper.CONFIG_ADDRESS);
if (AvatarHelper.getAvatarFile(this, address).exists() && AvatarHelper.getAvatarFile(this, address).length() > 0) {
if (AvatarHelper.getSelfAvatarFile(this, address).exists() && AvatarHelper.getSelfAvatarFile(this, address).length() > 0) {
new AsyncTask<Void, Void, byte[]>() {
@Override
protected byte[] doInBackground(Void... params) {
@@ -348,15 +351,6 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
}
private void initializeEmojiInput() {
this.emojiToggle.attach(emojiDrawer);
this.emojiToggle.setOnClickListener(v -> {
if (container.getCurrentInput() == emojiDrawer) {
container.showSoftkey(name);
} else {
container.show(name, emojiDrawer);
}
});
this.emojiDrawer.setEmojiEventListener(new EmojiDrawer.EmojiEventListener() {
@Override
@@ -374,7 +368,6 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
}
});
this.container.addOnKeyboardShownListener(() -> emojiToggle.setToEmoji());
this.name.setOnClickListener(v -> container.showSoftkey(name));
}
@@ -456,14 +449,14 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
TextSecurePreferences.setProfileName(context, name);
try {
AvatarHelper.setAvatar(CreateProfileActivity.this, DcHelper.get(context, DcHelper.CONFIG_ADDRESS), avatarBytes);
AvatarHelper.setSelfAvatar(CreateProfileActivity.this, DcHelper.get(context, DcHelper.CONFIG_ADDRESS), avatarBytes);
TextSecurePreferences.setProfileAvatarId(CreateProfileActivity.this, new SecureRandom().nextInt());
} catch (IOException e) {
Log.w(TAG, e);
return false;
}
ApplicationContext.getInstance(context).getJobManager().add(new MultiDeviceProfileKeyUpdateJob(context));
// ApplicationContext.getInstance(context).getJobManager().add(new MultiDeviceProfileKeyUpdateJob(context));
return true;
}
@@ -494,26 +487,17 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
}
private void handleFinishedLegacy() {
finishButton.setProgress(0);
if (nextIntent != null) startActivity(nextIntent);
finish();
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void handleFinishedLollipop() {
int[] finishButtonLocation = new int[2];
int[] revealLocation = new int[2];
finishButton.getLocationInWindow(finishButtonLocation);
reveal.getLocationInWindow(revealLocation);
int finishX = finishButtonLocation[0] - revealLocation[0];
int finishY = finishButtonLocation[1] - revealLocation[1];
finishX += finishButton.getWidth() / 2;
finishY += finishButton.getHeight() / 2;
Animator animation = ViewAnimationUtils.createCircularReveal(reveal, finishX, finishY, 0f, (float) Math.max(reveal.getWidth(), reveal.getHeight()));
Animator animation = ViewAnimationUtils.createCircularReveal(reveal, reveal.getWidth(), 0, 0f, (float) Math.max(reveal.getWidth(), reveal.getHeight()));
animation.setDuration(500);
animation.addListener(new Animator.AnimatorListener() {
@Override
@@ -521,7 +505,6 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
@Override
public void onAnimationEnd(Animator animation) {
finishButton.setProgress(0);
if (nextIntent != null) startActivity(nextIntent);
finish();
}

Some files were not shown because too many files have changed in this diff Show More