Compare commits

...

171 Commits

Author SHA1 Message Date
Dr. Tobias Quathamer 522ff32432 Prepare release 0.1.16 2017-02-06 00:37:07 +01:00
Dr. Tobias Quathamer a96cb520dd Update to backend v0.1.16 2017-02-06 00:32:19 +01:00
Dr. Tobias Quathamer fe9cd52312 Fix some syntax errors 2017-02-05 22:12:29 +01:00
Gilles MOREL d4355ad076 Added French translation 2017-02-05 21:59:37 +01:00
Dr. Tobias Quathamer 057d0eb39e Fix typo 2017-02-05 15:39:47 +01:00
Dr. Tobias Quathamer 82f35621e2 Fix method name typo 2017-02-02 20:46:06 +01:00
Dr. Tobias Quathamer 633856b350 Replace deprecated attribute singleLine with maxLines 2017-02-02 20:00:21 +01:00
Dr. Tobias Quathamer 1c0c9004c6 Convert DOS line endings CRLF to unix line endings, LF. No content changes 2017-02-02 19:59:12 +01:00
Dr. Tobias Quathamer 833533adc3 Remove wrongly lowered TargetAPI 10, project wide is API 14 2017-02-02 17:56:28 +01:00
Dr. Tobias Quathamer 846df6a164 Use a short tag for logging.
There are only 23 characters allowed, the tag
"LinearLayoutManager#LayoutState" was 31 characters.

This fixes a lint error.
2017-01-31 21:20:30 +01:00
Dr. Tobias Quathamer f5de9e8a23 Translate two missing strings 2017-01-31 21:12:01 +01:00
Dr. Tobias Quathamer 404a0ca032 Update Gradle to version 2.14.1 2017-01-31 20:50:40 +01:00
Dr. Tobias Quathamer 6e8612172b Update Android Gradle plugin to version 2.2.3 2017-01-31 20:50:25 +01:00
Dr. Tobias Quathamer aed9e39287 Bump version code for next release 2017-01-31 13:10:38 +01:00
Dr. Tobias Quathamer 597100d9e3 Use new path of backend submodule 2017-01-31 12:27:30 +01:00
Dr. Tobias Quathamer b2775e0811 Include submodule for messenger-backend 2017-01-31 12:16:58 +01:00
Björn Petersen 2425f0dcc7 Merge pull request #17 from toddy15/master
Fix some lint errors and warnings
2017-01-30 18:19:24 +01:00
Dr. Tobias Quathamer ede60340f6 Remove superfluous xmlns from TextView 2017-01-30 16:53:04 +01:00
Dr. Tobias Quathamer a9d58ab3f3 Ignore false positive lint error 2017-01-29 21:05:51 +01:00
Dr. Tobias Quathamer 6d6b6f41c9 Do not fail to build upon lint errors 2017-01-29 19:41:32 +01:00
Dr. Tobias Quathamer f5f97e4bfc Add missing string in default locale 2017-01-29 19:02:22 +01:00
Dr. Tobias Quathamer c7ed50a225 Typography: use ellipsis instead of three dots 2017-01-29 18:56:29 +01:00
Dr. Tobias Quathamer f843c531b4 Typography: use ellipsis instead of three dots 2017-01-29 18:02:33 +01:00
B. Petersen 2389a7d136 Remove bad error message. 2017-01-29 03:13:32 +01:00
B. Petersen e1d0306a29 Typo 2017-01-29 01:27:30 +01:00
B. Petersen 04cbe3f825 Speed up deleting multiple messages. 2017-01-28 18:29:01 +01:00
B. Petersen 9796ac1c53 Show the correct number of unread messages in the home page's icon. 2017-01-28 15:22:43 +01:00
B. Petersen 5721b9f86d Show forwarded headers. 2017-01-27 23:58:00 +01:00
B. Petersen aa090a9cd4 Fix calling forward function. 2017-01-27 12:40:01 +01:00
B. Petersen 03c30bef47 Ask forwarding. 2017-01-26 19:20:43 +01:00
B. Petersen c59453f31b Update colors. 2017-01-26 18:49:11 +01:00
B. Petersen 49e7f19cb7 Prepare forwarding messages. 2017-01-26 17:17:46 +01:00
B. Petersen 469c56f1a6 Pimp selection-action-bar-menu. 2017-01-26 15:17:31 +01:00
B. Petersen 239c56e77d Move copy/reply/info to a submenu in the selection-action-bar-menu. 2017-01-26 01:03:14 +01:00
B. Petersen e32ca20604 Change defaults for functions not yet implemented. 2017-01-24 16:50:15 +01:00
B. Petersen d00ef0af32 Add option to reset a user's encryption key. 2017-01-23 22:45:20 +01:00
B. Petersen e616e57be6 Add E2EE backend file. 2017-01-22 01:05:01 +01:00
B. Petersen 5485db8509 Add E2EE options. 2017-01-21 14:36:47 +01:00
B. Petersen df75d2917f Add options for e2e-encryption and for read receipts. 2017-01-19 18:16:45 +01:00
B. Petersen 0478ea5162 Separate command line stuff from program. 2017-01-19 17:30:29 +01:00
B. Petersen 433e90072f Improve 'no messages' screen and add a hint about greylisting. 2017-01-17 15:06:13 +01:00
B. Petersen 5c646ea663 Show receivers email-address when send messages from extern. 2017-01-16 21:19:43 +01:00
B. Petersen e095d3f886 Cleanup 'Not yet implemented' messages. 2017-01-15 13:18:45 +01:00
B. Petersen 9a6315d0b2 Typo 2017-01-14 17:45:55 +01:00
B. Petersen 8e81f0bb8f Update profile on remote changes.. 2017-01-14 01:47:26 +01:00
B. Petersen d6bdebc865 Localize. 2017-01-14 00:56:29 +01:00
B. Petersen 7ddf368fd1 Cleanup. 2017-01-13 23:19:23 +01:00
B. Petersen 301c6a4430 Increase version. 2017-01-13 18:49:11 +01:00
B. Petersen adaf91e383 Show an error on impossible actions. 2017-01-13 15:18:09 +01:00
B. Petersen 40de9dfe98 Ask before adding/removing members from group. 2017-01-13 11:36:11 +01:00
B. Petersen 18a8e2358c Group name changing and member adding/removing implemented. 2017-01-13 01:09:13 +01:00
B. Petersen e2a4008742 Fix scroll bug. 2017-01-12 17:46:13 +01:00
B. Petersen 258633b672 Propose a message as a draft for new created groups. 2017-01-11 14:36:43 +01:00
B. Petersen 96cc35b84d Add/remove members from group chats. 2017-01-11 01:28:08 +01:00
B. Petersen 787efa3c5d Edit group names. 2017-01-11 00:46:42 +01:00
B. Petersen 848862ae84 Fix a memory leak. 2017-01-11 00:09:50 +01:00
B. Petersen 6d3c170e96 Update avatars on renamings. 2017-01-11 00:01:56 +01:00
B. Petersen a921523014 Add SELF to chat contacts. 2017-01-10 17:07:53 +01:00
B. Petersen 29e5133c63 Create and delete groups. 2017-01-09 23:49:28 +01:00
B. Petersen 8d4aebe8e7 Cleanup. 2017-01-09 21:16:05 +01:00
B. Petersen c0139b1b49 HACK around a keyboard-focus issue. 2017-01-09 17:08:28 +01:00
B. Petersen 920d55ee6d Cleanup, remove unused AOSP files. 2017-01-09 14:53:56 +01:00
B. Petersen 4348b80b02 Show unread count in search message results only if the message itself is unread. 2017-01-09 14:27:12 +01:00
B. Petersen 1a62ed853b Show search summaries. 2017-01-09 14:11:18 +01:00
B. Petersen f858cc7747 Implement global search. 2017-01-09 02:10:10 +01:00
B. Petersen 394b439a06 Explain non-hide-floating. 2017-01-08 21:53:16 +01:00
B. Petersen b515660bac Cleanup locale. 2017-01-08 21:24:20 +01:00
B. Petersen 88719df0af Remove dead mention code. 2017-01-08 21:00:09 +01:00
B. Petersen 495dfa0f59 Force redraw when the query gets empty. 2017-01-08 14:49:57 +01:00
B. Petersen f7372819a1 Pimp in-chat-search. 2017-01-08 14:39:51 +01:00
B. Petersen 9d622ecef7 Show empty bottom overlay on in-chat-search. 2017-01-08 12:56:17 +01:00
B. Petersen 221004354e Move search up/down buttons to action bar; also show the number of hits there. 2017-01-08 02:11:14 +01:00
B. Petersen 442baa6aa9 Implement search 2017-01-07 20:27:38 +01:00
B. Petersen 2e4f748093 Allow using the menu if there is a draft; add 'Attach files' as a normal menu entry to access this function if the normal 'attach' button is replaces by the 'send' button. 2017-01-07 18:26:34 +01:00
B. Petersen 56a846ab3b Remove dead 'mentions' code from ChatActivity. 2017-01-07 15:12:42 +01:00
B. Petersen f67e24b49e Cleanup 2017-01-07 14:36:58 +01:00
B. Petersen f40a3e49cb Also use 'speech bubbles' for photos and media. 2017-01-06 15:57:34 +01:00
B. Petersen 04b815bb49 Clearify coordinates. 2017-01-06 15:39:12 +01:00
B. Petersen 3292979696 Fast loading of large chats. 2017-01-06 02:54:29 +01:00
B. Petersen 3e24ca9be1 Update chat with incoming/outgoing messages. 2017-01-05 18:41:45 +01:00
B. Petersen 38e5350219 Use a virtual listbox for the messages to allow some thousands of messages in a chat. 2017-01-05 15:32:32 +01:00
B. Petersen 39d5c40945 Cleanup keyboard code. 2017-01-05 13:25:26 +01:00
B. Petersen ebcb132acf Cleanup. 2017-01-05 13:10:11 +01:00
B. Petersen 53447c793a Remove dead sticker code. 2017-01-05 12:22:42 +01:00
B. Petersen 54a2df818b Remove unused GIF code from ChatActivity. 2017-01-05 12:10:19 +01:00
B. Petersen 09a3b3bd26 Get rid of unused context menu code. 2017-01-05 11:59:50 +01:00
B. Petersen f02d4cd21a Remove suspicious forward creation of objects. 2017-01-05 02:34:01 +01:00
B. Petersen eb650ff089 Cleanup 2017-01-05 01:10:21 +01:00
B. Petersen da263b1e56 Remove unused service messages. 2017-01-05 00:25:38 +01:00
B. Petersen 44ee4aaef7 Cleanup. 2017-01-05 00:00:45 +01:00
B. Petersen 56874bd418 Cleanup notification strings. 2017-01-04 23:52:20 +01:00
B. Petersen bf1594fdef Use correct avatars for the created widgets. 2017-01-04 01:08:08 +01:00
B. Petersen e31821cf92 Test solid wallpapers. 2017-01-03 18:43:29 +01:00
B. Petersen 4efe3b4387 Go directly to the notified chat. 2017-01-03 17:52:34 +01:00
B. Petersen 69d0537425 Prepare MrChat to get the pointer-handle directly in the C-Part. 2017-01-03 17:20:30 +01:00
B. Petersen 0852e09815 Cleanup headers. 2017-01-03 16:40:43 +01:00
B. Petersen 2fc8799241 Hide unused empty-search-field-buttons (may be seen as close-search-bar-buttons otherwise). 2017-01-03 14:45:08 +01:00
B. Petersen ea01205421 Show correct chat after sharing texts. 2017-01-02 15:35:25 +01:00
B. Petersen 1ad31aa178 Can send share texts to Delta Chat. 2017-01-02 15:25:02 +01:00
B. Petersen 349b943a7e Unify 'disabled' and 'off' strings. 2017-01-02 14:55:31 +01:00
B. Petersen 268006d027 'Repeat notifications' default to 'off'. 2017-01-02 13:02:56 +01:00
B. Petersen e2bad18153 Show number of blocked users in settings. 2017-01-02 12:35:10 +01:00
B. Petersen 4749ddf9a8 Tweak notifications. 2016-12-24 01:33:23 +01:00
B. Petersen de1c568714 Localize 2016-12-23 23:55:49 +01:00
B. Petersen 0b90e66ad8 Tweak notifications. 2016-12-23 14:47:17 +01:00
B. Petersen 90fe75a764 Play notification sounds, vibrate. 2016-12-23 02:15:48 +01:00
B. Petersen c27fd27789 Remove seen messages from notifications. Display user and group names in notifications only if they differ from each other. 2016-12-23 02:08:37 +01:00
B. Petersen 5580f5ae62 Set user and message text in notifications. 2016-12-22 18:44:24 +01:00
B. Petersen d4e94b2fbc Set Delta Chat notification icon. 2016-12-22 12:27:23 +01:00
B. Petersen bb673dd992 Make notifications generally work. 2016-12-21 23:34:28 +01:00
B. Petersen 2dfacc4858 Make 'Reset notifications and sounds' work. 2016-12-21 23:04:52 +01:00
B. Petersen cce4e31b0f Remove popup notifications, for now. 2016-12-21 22:12:40 +01:00
B. Petersen 99615999b8 Re-init stock strings after language change, fixes issue #1. 2016-12-21 21:44:56 +01:00
B. Petersen cfca25d65d Hide button 'Notifications and Sounds' for deaddrops not shown in chatlist. 2016-12-21 21:26:42 +01:00
B. Petersen 665a2cdfd0 Prepare notifications. 2016-12-21 18:13:04 +01:00
B. Petersen a2768728d3 Play in-chat sounds. 2016-12-21 17:47:11 +01:00
B. Petersen 2790082705 Cleanup. 2016-12-21 16:44:31 +01:00
B. Petersen ae8a15d524 Cleanup. 2016-12-21 16:23:10 +01:00
B. Petersen e39d7b5d4d Add an extra event for incoming messages. 2016-12-21 01:17:14 +01:00
B. Petersen 1ae26ecfa5 Cleanup notify code. 2016-12-21 00:38:22 +01:00
B. Petersen 1e58912226 Showing the default font size in the NumberPicker. 2016-12-20 23:57:20 +01:00
B. Petersen 87807db64a Do not use the android cache directory as our 'blob repository'; the cache directory may be treated as a real cache; the files may disappear at any time. Instead, we're using a normal directory beside the database (the directory that is already used by the backend for incoming messages) and delete files ourself as needed. 2016-12-20 22:43:22 +01:00
B. Petersen 6221c97283 For non-empty strings, do not use NewStringUTF() as this is buggy on some Android versions. Instead, create the string using 'new String(ByteArray, 'UTF-8');' which seems to be programmed more properly. (eg. on KitKat a simple 'SMILING FACE WITH SMILING EYES' (U+1F60A, UTF-8 F0 9F 98 8A) will let the app crash, reporting 0xF0 is a bad UTF-8 start, see http://stackoverflow.com/questions/12127817/android-ics-4-0-ndk-newstringutf-is-crashing-down-the-app ) 2016-12-20 00:21:18 +01:00
B. Petersen 80226717b6 Set up photo type. 2016-12-19 16:29:59 +01:00
B. Petersen 959f7af2ab Change intro layout (paging below pages ...). 2016-12-19 14:16:06 +01:00
B. Petersen 2308990661 Cleanup paths. 2016-12-19 13:45:44 +01:00
B. Petersen 9f304f372a Remove save-to-gallery option. We save all stuff internally; this avoids probles if a user deletes an image. Additionally, photos taken are always saved in the gallery; plus, the user can explicitly save data to the gallery (this avoids saving all files twice). 2016-12-19 13:19:16 +01:00
B. Petersen 341580191f Tuning settings dialog. 2016-12-19 00:18:27 +01:00
B. Petersen 07065676f2 Cleanup WebPage stuff. 2016-12-13 12:58:27 +01:00
B. Petersen 47c9dc6e31 Simplify rights management. 2016-12-13 00:15:12 +01:00
B. Petersen 2514494d02 Force reloading avatars, do not clear old values (looks smarter). 2016-12-12 14:32:46 +01:00
B. Petersen 1c28c2d475 Load avatars in working thread, cache avatars, reload avatars after pause (they may have been changed in another app then). 2016-12-12 14:13:04 +01:00
B. Petersen 41a92d56c4 Using a mask instead of clipping to create round avatars; this avoid problems with canvas setting sets and allows antialiasing. 2016-12-12 12:37:36 +01:00
B. Petersen 6a6b024314 Draw avatar photos. 2016-12-10 01:23:38 +01:00
B. Petersen 12c95971a2 Cleanup avatar management, route everything through ContactsController.setupAvatar(). 2016-12-09 17:18:18 +01:00
B. Petersen 62ca3b6331 Neutral language. 2016-12-09 13:58:24 +01:00
B. Petersen c69f2fd75d Add invite function. 2016-12-09 13:10:35 +01:00
B. Petersen 0fc45bc57a Disable hiding of the floating button. 2016-12-08 13:55:36 +01:00
B. Petersen 0b9614f0bd Cleanup. 2016-12-06 14:13:37 +01:00
B. Petersen e8a073a42c Cleanup. 2016-12-06 14:00:53 +01:00
B. Petersen 97b33ec9c4 Cleanup. 2016-12-06 12:56:17 +01:00
B. Petersen f6458870ae Optimize unread display. 2016-12-06 12:38:52 +01:00
B. Petersen 665f24db1e Smart 'message seen' handling. 2016-12-05 23:55:32 +01:00
B. Petersen a59be9d2af Mark incoming messages as read when seen. 2016-12-05 22:56:02 +01:00
B. Petersen 1036139cb7 Properly add date headlines. 2016-12-05 22:30:45 +01:00
B. Petersen f1854e46be Cleanup. 2016-12-05 15:10:59 +01:00
B. Petersen bfad3e57c7 Remove unneeded reply functionality. 2016-12-05 14:01:32 +01:00
B. Petersen 24ee24325b Remove unneded loading cells. 2016-12-05 13:45:10 +01:00
B. Petersen c9f6db312f Remove unneded mergeDialogId stuff from ChatActivity. 2016-12-05 13:27:54 +01:00
B. Petersen 6f60ba113e Remove ChatObject class. 2016-12-05 12:29:07 +01:00
B. Petersen db112b226e Remove DraftQuery, StickersQuery, SharedMediaQuery & Co. 2016-12-05 12:20:26 +01:00
B. Petersen a87049e443 Cleanup. 2016-12-04 23:45:41 +01:00
B. Petersen 730b018b45 Cleanup. 2016-12-04 22:46:32 +01:00
B. Petersen 60e72f14d8 Simplify chat objects. 2016-12-03 18:48:09 +01:00
B. Petersen e89b2855ce Remove UserObject.isDeleted(). 2016-12-03 18:06:52 +01:00
B. Petersen 56fb73088e Increase version. 2016-12-02 14:47:08 +01:00
B. Petersen 6623513c2a Adapt colors. 2016-12-02 01:54:00 +01:00
B. Petersen 3da3325c9b Cleanup attach dialog. 2016-12-02 00:53:56 +01:00
B. Petersen c73d3564d4 Cleanup. 2016-12-01 22:30:36 +01:00
B. Petersen 2b822ecd22 Cleanup 2016-11-30 14:18:41 +01:00
B. Petersen a81c921504 Correct flow. 2016-11-30 13:55:03 +01:00
B. Petersen c902044cc3 Show incoming messages in chat view. 2016-11-29 17:20:57 +01:00
B. Petersen 072945b237 Cleanup. 2016-11-29 15:17:13 +01:00
B. Petersen ca49e9899d Remove unneeded report functionality. 2016-11-29 12:09:50 +01:00
B. Petersen f67d82452b Simplify messagesDidLoaded event. 2016-11-29 12:00:19 +01:00
B. Petersen 1c3b7ce051 Cleanup. 2016-11-28 14:20:50 +01:00
B. Petersen cd6d8114ad Cleanup 2016-11-28 14:04:27 +01:00
B. Petersen 1baa5a5d99 Rename 'MrEditTextCell' to more generic 'EditTextCell'. 2016-11-28 13:31:08 +01:00
B. Petersen a83dac9437 Show more detailed error information. 2016-11-27 22:16:01 +01:00
B. Petersen e033c04d7a Capitalize words instead of sentences on name input. 2016-11-25 16:06:01 +01:00
B. Petersen bbd06d37da Update and translate intro strings. 2016-11-25 16:01:57 +01:00
429 changed files with 8255 additions and 27384 deletions
+3
View File
@@ -0,0 +1,3 @@
[submodule "MessengerProj/jni/messenger-backend"]
path = MessengerProj/jni/messenger-backend
url = https://github.com/r10s/messenger-backend.git
+6 -3
View File
@@ -42,6 +42,10 @@ android {
targetCompatibility JavaVersion.VERSION_1_7
}
lintOptions {
abortOnError false
}
signingConfigs {
debug {
storeFile file("config/debug.keystore")
@@ -78,7 +82,7 @@ android {
}
}
defaultConfig.versionCode = 13
defaultConfig.versionCode = 15
sourceSets.main {
jniLibs.srcDir 'libs'
@@ -129,7 +133,6 @@ android {
defaultConfig {
minSdkVersion 14 // 14: Android 4.0 Ice Cream Sandwich 2011 (Telegram default), 21: Android 5.0 Lollipop 2014 (recommended for InstantRun)
targetSdkVersion 23
versionName "0.1.3"
versionName "0.1.16"
}
}
@@ -14,7 +14,7 @@
<application
android:allowBackup="false"
android:icon="@drawable/ic_launcher"
android:label="@string/AppNameBeta"
android:label="@string/AppName"
android:theme="@style/Theme.MessengerProj.Start"
android:name=".ApplicationLoader"
android:hardwareAccelerated="@bool/useHardwareAcceleration"
+20 -18
View File
@@ -1604,24 +1604,26 @@ LOCAL_SRC_FILES += \
./image.c \
./video.c \
./gifvideo.cpp \
../../../messenger-backend/src/mrchat.c \
../../../messenger-backend/src/mrchatlist.c \
../../../messenger-backend/src/mrcontact.c \
../../../messenger-backend/src/mrimap.c \
../../../messenger-backend/src/mrjob.c \
../../../messenger-backend/src/mrlog.c \
../../../messenger-backend/src/mrloginparam.c \
../../../messenger-backend/src/mrmailbox.c \
../../../messenger-backend/src/mrmimeparser.c \
../../../messenger-backend/src/mrmsg.c \
../../../messenger-backend/src/mrosnative.c \
../../../messenger-backend/src/mrparam.c \
../../../messenger-backend/src/mrpoortext.c \
../../../messenger-backend/src/mrsimplify.c \
../../../messenger-backend/src/mrsmtp.c \
../../../messenger-backend/src/mrsqlite3.c \
../../../messenger-backend/src/mrstock.c \
../../../messenger-backend/src/mrtools.c \
./messenger-backend/src/mrchat.c \
./messenger-backend/src/mrchatlist.c \
./messenger-backend/src/mrcmdline.c \
./messenger-backend/src/mrcontact.c \
./messenger-backend/src/mre2ee.c \
./messenger-backend/src/mrimap.c \
./messenger-backend/src/mrjob.c \
./messenger-backend/src/mrlog.c \
./messenger-backend/src/mrloginparam.c \
./messenger-backend/src/mrmailbox.c \
./messenger-backend/src/mrmimeparser.c \
./messenger-backend/src/mrmsg.c \
./messenger-backend/src/mrosnative.c \
./messenger-backend/src/mrparam.c \
./messenger-backend/src/mrpoortext.c \
./messenger-backend/src/mrsimplify.c \
./messenger-backend/src/mrsmtp.c \
./messenger-backend/src/mrsqlite3.c \
./messenger-backend/src/mrstock.c \
./messenger-backend/src/mrtools.c \
./mrwrapper.c
include $(BUILD_SHARED_LIBRARY)
+255 -44
View File
@@ -1,8 +1,8 @@
/*******************************************************************************
*
* Messenger Android Frontend
* Copyright (C) 2016 Björn Petersen Software Design and Development
* Contact: r10s@b44t.com, http://b44t.com
* (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
@@ -20,7 +20,6 @@
*******************************************************************************
*
* File: mr_wrapper.c
* Authors: Björn Petersen
* Purpose: The C part of the Java<->C Wrapper, see also MrMailbox.java
*
******************************************************************************/
@@ -28,7 +27,7 @@
#include <jni.h>
#include <android/log.h>
#include "../../../messenger-backend/src/mrmailbox.h"
#include "messenger-backend/src/mrmailbox.h"
#define CHAR_REF(a) \
@@ -37,8 +36,34 @@
#define CHAR_UNREF(a) \
if(a) { (*env)->ReleaseStringUTFChars(env, (a), a##Ptr); }
#define JSTRING_NEW(a) \
(*env)->NewStringUTF(env, a? a : "") /*should handle NULL arguments, does not return NULL!*/
#define JSTRING_NEW(a) jstring_new__(env, (a))
static jstring jstring_new__(JNIEnv* env, const char* a)
{
if( a==NULL || a[0]==0 ) {
return (*env)->NewStringUTF(env, "");
}
/* for non-empty strings, do not use NewStringUTF() as this is buggy on some Android versions.
Instead, create the string using `new String(ByteArray, "UTF-8);` which seems to be programmed more properly.
(eg. on KitKat a simple "SMILING FACE WITH SMILING EYES" (U+1F60A, UTF-8 F0 9F 98 8A) will let the app crash, reporting 0xF0 is a bad UTF-8 start,
see http://stackoverflow.com/questions/12127817/android-ics-4-0-ndk-newstringutf-is-crashing-down-the-app ) */
static jclass s_strCls = NULL;
static jmethodID s_strCtor = NULL;
static jclass s_strEncode = NULL;
if( s_strCls==NULL ) {
s_strCls = (*env)->NewGlobalRef(env, (*env)->FindClass(env, "java/lang/String"));
s_strCtor = (*env)->GetMethodID(env, s_strCls, "<init>", "([BLjava/lang/String;)V");
s_strEncode = (*env)->NewGlobalRef(env, (*env)->NewStringUTF(env, "UTF-8"));
}
int a_bytes = strlen(a);
jbyteArray array = (*env)->NewByteArray(env, a_bytes);
(*env)->SetByteArrayRegion(env, array, 0, a_bytes, a);
jstring ret = (jstring) (*env)->NewObject(env, s_strCls, s_strCtor, array, s_strEncode);
(*env)->DeleteLocalRef(env, array); /* we have to delete the reference as it is not returned to Java, AFAIK */
return ret;
}
/* our log handler */
@@ -57,7 +82,7 @@ static void s_log_callback_(int type, const char* msg)
}
/* globl stuff */
/* global stuff */
static JavaVM* s_jvm = NULL;
static jclass s_MrMailbox_class = NULL;
@@ -112,9 +137,49 @@ static jintArray carray2jintArray_n_carray_free(JNIEnv *env, const carray* ca)
}
static uint32_t* jintArray2uint32Pointer(JNIEnv* env, jintArray ja, int* ret_icnt)
{
uint32_t* ret = NULL;
if( env && ja && ret_icnt )
{
int i, icnt = (*env)->GetArrayLength(env, ja);
if( icnt > 0 )
{
const jint* temp = (*env)->GetIntArrayElements(env, ja, NULL);
if( temp )
{
ret = calloc(icnt, sizeof(uint32_t));
if( ret )
{
for( i = 0; i < icnt; i++ ) {
ret[i] = (uint32_t)temp[i];
}
*ret_icnt = icnt;
}
(*env)->ReleaseIntArrayElements(env, ja, temp, 0);
}
}
}
return ret;
}
/*******************************************************************************
* MrMailbox
******************************************************************************/
static mrmailbox_t* get_mrmailbox_t(JNIEnv *env, jclass cls)
{
static jfieldID fid = 0;
if( fid == 0 ) {
fid = (*env)->GetStaticFieldID(env, cls, "m_hMailbox", "J" /*Signature, J=long*/);
}
if( fid ) {
return (mrmailbox_t*)(*env)->GetStaticLongField(env, cls, fid);
}
return NULL;
}
/* MrMailbox - new/delete */
@@ -149,20 +214,25 @@ JNIEXPORT jlong Java_com_b44t_messenger_MrMailbox_MrMailboxNew(JNIEnv *env, jcla
/* MrMailbox - open/configure/connect/fetch */
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_MrMailboxOpen(JNIEnv *env, jclass c, jlong hMailbox, jstring dbfile, jstring blobdir)
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_open(JNIEnv *env, jclass cls, jstring dbfile)
{
CHAR_REF(dbfile);
CHAR_REF(blobdir);
jint ret = mrmailbox_open((mrmailbox_t*)hMailbox, dbfilePtr, blobdirPtr);
CHAR_UNREF(blobdir);
jint ret = mrmailbox_open(get_mrmailbox_t(env, cls), dbfilePtr, NULL);
CHAR_UNREF(dbfile)
return ret;
}
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_MrMailboxClose(JNIEnv *env, jclass c, jlong hMailbox)
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_close(JNIEnv *env, jclass cls)
{
mrmailbox_close((mrmailbox_t*)hMailbox);
mrmailbox_close(get_mrmailbox_t(env, cls));
}
JNIEXPORT jstring Java_com_b44t_messenger_MrMailbox_getBlobdir(JNIEnv *env, jclass cls)
{
mrmailbox_t* ths = get_mrmailbox_t(env, cls);
return JSTRING_NEW((ths&&ths->m_blobdir)? ths->m_blobdir : NULL);
}
@@ -196,20 +266,35 @@ JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_MrMailboxFetch(JNIEnv *env, jcl
}
JNIEXPORT jstring Java_com_b44t_messenger_MrMailbox_getErrorDescr(JNIEnv *env, jclass cls)
{
char* c = mrmailbox_get_error_descr(get_mrmailbox_t(env, cls));
jstring ret = JSTRING_NEW(c);
free(c);
return ret;
}
/* MrMailbox - handle contacts */
JNIEXPORT jintArray Java_com_b44t_messenger_MrMailbox_MrMailboxGetKnownContacts(JNIEnv *env, jclass c, jlong hMailbox, jstring query)
JNIEXPORT jintArray Java_com_b44t_messenger_MrMailbox_getKnownContacts(JNIEnv *env, jclass cls, jstring query)
{
CHAR_REF(query);
carray* ca = mrmailbox_get_known_contacts((mrmailbox_t*)hMailbox, queryPtr);
CHAR_REF(query);
carray* ca = mrmailbox_get_known_contacts(get_mrmailbox_t(env, cls), queryPtr);
CHAR_UNREF(query);
return carray2jintArray_n_carray_free(env, ca);
}
JNIEXPORT jintArray Java_com_b44t_messenger_MrMailbox_MrMailboxGetBlockedContacts(JNIEnv *env, jclass c, jlong hMailbox)
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_getBlockedCount(JNIEnv *env, jclass cls)
{
carray* ca = mrmailbox_get_blocked_contacts((mrmailbox_t*)hMailbox);
return mrmailbox_get_blocked_count(get_mrmailbox_t(env, cls));
}
JNIEXPORT jintArray Java_com_b44t_messenger_MrMailbox_getBlockedContacts(JNIEnv *env, jclass cls)
{
carray* ca = mrmailbox_get_blocked_contacts(get_mrmailbox_t(env, cls));
return carray2jintArray_n_carray_free(env, ca);
}
@@ -245,9 +330,18 @@ JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_MrMailboxDeleteContact(JNIEnv *
/* MrMailbox - handle chats */
JNIEXPORT jlong Java_com_b44t_messenger_MrMailbox_MrMailboxGetChatlist(JNIEnv *env, jclass c, jlong hMailbox)
JNIEXPORT jlong Java_com_b44t_messenger_MrMailbox_MrMailboxGetChatlist(JNIEnv *env, jclass c, jlong hMailbox, jstring query)
{
return (jlong)mrmailbox_get_chatlist((mrmailbox_t*)hMailbox);
jlong ret;
if( query ) {
CHAR_REF(query);
ret = (jlong)mrmailbox_get_chatlist((mrmailbox_t*)hMailbox, queryPtr);
CHAR_UNREF(query);
}
else {
ret = (jlong)mrmailbox_get_chatlist((mrmailbox_t*)hMailbox, NULL);
}
return ret;
}
@@ -263,9 +357,15 @@ JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_MrMailboxGetChatIdByContactId(J
}
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_MrMailboxMarkseenChat(JNIEnv *env, jclass c, jlong hMailbox, jint chat_id)
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_markseenMsg(JNIEnv *env, jclass cls, jint msg_id)
{
return (jlong)mrmailbox_markseen_chat((mrmailbox_t*)hMailbox, chat_id);
return (jint)mrmailbox_markseen_msg(get_mrmailbox_t(env, cls), msg_id);
}
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_markseenChat(JNIEnv *env, jclass cls, jint chat_id)
{
return (jlong)mrmailbox_markseen_chat(get_mrmailbox_t(env, cls), chat_id);
}
@@ -275,9 +375,39 @@ JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_MrMailboxCreateChatByContactId(
}
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_MrMailboxDeleteChat(JNIEnv *env, jclass c, jlong hMailbox, jint chat_id)
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_createGroupChat(JNIEnv *env, jclass cls, jstring name)
{
mrmailbox_delete_chat((mrmailbox_t*)hMailbox, chat_id);
CHAR_REF(name);
jint ret = (jint)mrmailbox_create_group_chat(get_mrmailbox_t(env, cls), namePtr);
CHAR_UNREF(name);
return ret;
}
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_addContactToChat(JNIEnv *env, jclass cls, jint chat_id, jint contact_id)
{
return (jint)mrmailbox_add_contact_to_chat(get_mrmailbox_t(env, cls), chat_id, contact_id);
}
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_removeContactFromChat(JNIEnv *env, jclass cls, jint chat_id, jint contact_id)
{
return (jint)mrmailbox_remove_contact_from_chat(get_mrmailbox_t(env, cls), chat_id, contact_id);
}
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_setChatName(JNIEnv *env, jclass cls, jint chat_id, jstring name)
{
CHAR_REF(name);
jint ret = (jint)mrmailbox_set_chat_name(get_mrmailbox_t(env, cls), chat_id, namePtr);
CHAR_UNREF(name);
return ret;
}
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_deleteChat(JNIEnv *env, jclass cls, jint chat_id)
{
mrmailbox_delete_chat(get_mrmailbox_t(env, cls), chat_id);
}
@@ -298,9 +428,21 @@ JNIEXPORT jstring Java_com_b44t_messenger_MrMailbox_MrMailboxGetMsgInfo(JNIEnv *
}
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_MrMailboxDeleteMsg(JNIEnv *env, jclass c, jlong hMailbox, jint id)
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_deleteMsgs(JNIEnv *env, jclass cls, jintArray msg_ids)
{
mrmailbox_delete_msg((mrmailbox_t*)hMailbox, id);
int msg_ids_cnt;
const uint32_t* msg_ids_ptr = jintArray2uint32Pointer(env, msg_ids, &msg_ids_cnt);
mrmailbox_delete_msgs(get_mrmailbox_t(env, cls), msg_ids_ptr, msg_ids_cnt);
free(msg_ids_ptr);
}
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_forwardMsgs(JNIEnv *env, jclass cls, jintArray msg_ids, jint chat_id)
{
int msg_ids_cnt;
const uint32_t* msg_ids_ptr = jintArray2uint32Pointer(env, msg_ids, &msg_ids_cnt);
mrmailbox_forward_msgs(get_mrmailbox_t(env, cls), msg_ids_ptr, msg_ids_cnt, chat_id);
free(msg_ids_ptr);
}
@@ -341,19 +483,19 @@ JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_MrMailboxGetConfigInt(JNIEnv *e
/* MrMailbox - misc. */
JNIEXPORT jstring Java_com_b44t_messenger_MrMailbox_MrMailboxGetInfo(JNIEnv *env, jclass c, jlong hMailbox)
JNIEXPORT jstring Java_com_b44t_messenger_MrMailbox_getInfo(JNIEnv *env, jclass cls)
{
char* temp = mrmailbox_get_info((mrmailbox_t*)hMailbox);
char* temp = mrmailbox_get_info(get_mrmailbox_t(env, cls));
jstring ret = JSTRING_NEW(temp);
free(temp);
return ret;
}
JNIEXPORT jstring Java_com_b44t_messenger_MrMailbox_MrMailboxExecute(JNIEnv *env, jclass c, jlong hMailbox, jstring cmd)
JNIEXPORT jstring Java_com_b44t_messenger_MrMailbox_cmdline(JNIEnv *env, jclass cls, jstring cmd)
{
CHAR_REF(cmd);
char* temp = mrmailbox_execute((mrmailbox_t*)hMailbox, cmdPtr);
char* temp = mrmailbox_cmdline(get_mrmailbox_t(env, cls), cmdPtr);
jstring ret = JSTRING_NEW(temp);
free(temp);
CHAR_UNREF(cmd);
@@ -405,42 +547,63 @@ JNIEXPORT jlong Java_com_b44t_messenger_MrChatlist_MrChatlistGetSummaryByIndex(J
******************************************************************************/
static mrchat_t* get_mrchat_t(JNIEnv *env, jobject obj)
{
static jfieldID fid = 0;
if( fid == 0 ) {
jclass cls = (*env)->GetObjectClass(env, obj);
fid = (*env)->GetFieldID(env, cls, "m_hChat", "J" /*Signature, J=long*/);
}
if( fid ) {
return (mrchat_t*)(*env)->GetLongField(env, obj, fid);
}
return NULL;
}
JNIEXPORT void Java_com_b44t_messenger_MrChat_MrChatUnref(JNIEnv *env, jclass c, jlong hChat)
{
mrchat_unref((mrchat_t*)hChat);
}
JNIEXPORT jint Java_com_b44t_messenger_MrChat_MrChatGetId(JNIEnv *env, jclass c, jlong hChat)
JNIEXPORT jint Java_com_b44t_messenger_MrChat_getId(JNIEnv *env, jclass cls)
{
mrchat_t* ths = (mrchat_t*)hChat; if( ths == NULL ) { return 0; }
mrchat_t* ths = get_mrchat_t(env, cls); if( ths == NULL ) { return 0; }
return ths->m_id;
}
JNIEXPORT jint Java_com_b44t_messenger_MrChat_MrChatGetType(JNIEnv *env, jclass c, jlong hChat)
JNIEXPORT jint Java_com_b44t_messenger_MrChat_getType(JNIEnv *env, jclass cls)
{
mrchat_t* ths = (mrchat_t*)hChat; if( ths == NULL ) { return 0; }
mrchat_t* ths = get_mrchat_t(env, cls); if( ths == NULL ) { return 0; }
return ths->m_type;
}
JNIEXPORT jstring Java_com_b44t_messenger_MrChat_MrChatGetName(JNIEnv *env, jclass c, jlong hChat)
JNIEXPORT jstring Java_com_b44t_messenger_MrChat_getName(JNIEnv *env, jclass cls)
{
mrchat_t* ths = (mrchat_t*)hChat; if( ths == NULL ) { return JSTRING_NEW(NULL); }
mrchat_t* ths = get_mrchat_t(env, cls); if( ths == NULL ) { return JSTRING_NEW(NULL); }
return JSTRING_NEW(ths->m_name);
}
JNIEXPORT jstring Java_com_b44t_messenger_MrChat_MrChatGetSubtitle(JNIEnv *env, jclass c, jlong hChat)
JNIEXPORT jstring Java_com_b44t_messenger_MrChat_getSubtitle(JNIEnv *env, jclass cls)
{
const char* temp = mrchat_get_subtitle((mrchat_t*)hChat);
const char* temp = mrchat_get_subtitle(get_mrchat_t(env, cls));
jstring ret = JSTRING_NEW(temp);
free(temp);
return ret;
}
JNIEXPORT jint Java_com_b44t_messenger_MrChat_getParamInt(JNIEnv *env, jclass cls, jint key, jint def)
{
mrchat_t* ths = get_mrchat_t(env, cls);
return mrparam_get_int(ths? ths->m_param:NULL, key, def);
}
JNIEXPORT jstring Java_com_b44t_messenger_MrChat_MrChatGetDraft(JNIEnv *env, jclass c, jlong hChat) /* returns NULL for "no draft" */
{
mrchat_t* ths = (mrchat_t*)hChat;
@@ -529,17 +692,32 @@ JNIEXPORT jintArray Java_com_b44t_messenger_MrMailbox_MrMailboxGetChatMedia(JNIE
}
JNIEXPORT jintArray Java_com_b44t_messenger_MrMailbox_MrMailboxGetChatMsgs(JNIEnv *env, jclass c, jlong hMailbox, jint chat_id)
JNIEXPORT jintArray Java_com_b44t_messenger_MrMailbox_getChatMsgs(JNIEnv *env, jclass cls, jint chat_id, jint flags, jint marker1before)
{
carray* ca = mrmailbox_get_chat_msgs((mrmailbox_t*)hMailbox, chat_id);
carray* ca = mrmailbox_get_chat_msgs(get_mrmailbox_t(env, cls), chat_id, flags, marker1before);
return carray2jintArray_n_carray_free(env, ca);
}
JNIEXPORT jintArray Java_com_b44t_messenger_MrMailbox_MrMailboxGetChatContacts(JNIEnv *env, jclass c, jlong hMailbox, jint chat_id)
JNIEXPORT jintArray Java_com_b44t_messenger_MrMailbox_searchMsgs(JNIEnv *env, jclass cls, jint chat_id, jstring query)
{
carray* ca = mrmailbox_get_chat_contacts((mrmailbox_t*)hMailbox, chat_id);
CHAR_REF(query);
carray* ca = mrmailbox_search_msgs(get_mrmailbox_t(env, cls), chat_id, queryPtr);
CHAR_UNREF(query);
return carray2jintArray_n_carray_free(env, ca);
}
JNIEXPORT jintArray Java_com_b44t_messenger_MrMailbox_getUnseenMsgs(JNIEnv *env, jclass cls)
{
carray* ca = mrmailbox_get_unseen_msgs(get_mrmailbox_t(env, cls));
return carray2jintArray_n_carray_free(env, ca);
}
JNIEXPORT jintArray Java_com_b44t_messenger_MrMailbox_getChatContacts(JNIEnv *env, jclass cls, jint chat_id)
{
carray* ca = mrmailbox_get_chat_contacts(get_mrmailbox_t(env, cls), chat_id);
return carray2jintArray_n_carray_free(env, ca);
}
@@ -549,6 +727,20 @@ JNIEXPORT jintArray Java_com_b44t_messenger_MrMailbox_MrMailboxGetChatContacts(J
******************************************************************************/
static mrmsg_t* get_mrmsg_t(JNIEnv *env, jobject obj)
{
static jfieldID fid = 0;
if( fid == 0 ) {
jclass cls = (*env)->GetObjectClass(env, obj);
fid = (*env)->GetFieldID(env, cls, "m_hMsg", "J" /*Signature, J=long*/);
}
if( fid ) {
return (mrmsg_t*)(*env)->GetLongField(env, obj, fid);
}
return NULL;
}
JNIEXPORT void Java_com_b44t_messenger_MrMsg_MrMsgUnref(JNIEnv *env, jclass c, jlong hMsg)
{
mrmsg_unref((mrmsg_t*)hMsg);
@@ -626,7 +818,26 @@ JNIEXPORT jstring Java_com_b44t_messenger_MrMsg_MrMsgGetParam(JNIEnv *env, jclas
JNIEXPORT jint Java_com_b44t_messenger_MrMsg_MrMsgGetParamInt(JNIEnv *env, jclass c, jlong hMsg, jint key, jint def)
{
mrmsg_t* ths = (mrmsg_t*)hMsg;
return mrparam_get_int(ths? ths->m_param:NULL, key, def);
return mrparam_get_int(ths? ths->m_param:NULL, key, def);
}
JNIEXPORT jint Java_com_b44t_messenger_MrMsg_getBytes(JNIEnv *env, jobject obj)
{
mrmsg_t* ths = get_mrmsg_t(env, obj);
return ths? ths->m_bytes : 0;
}
JNIEXPORT jlong Java_com_b44t_messenger_MrMsg_getSummaryCPtr(JNIEnv *env, jobject obj, jlong hChat)
{
return (jlong)mrmsg_get_summary(get_mrmsg_t(env, obj), (mrchat_t*)hChat);
}
JNIEXPORT jint Java_com_b44t_messenger_MrMsg_getSummarytext(JNIEnv *env, jobject obj, jint approx_characters)
{
return JSTRING_NEW(mrmsg_get_summarytext(get_mrmsg_t(env, obj), approx_characters));
}
@@ -131,15 +131,6 @@
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:exported="true">
</activity>
<activity
android:name="com.b44t.ui.PopupNotificationActivity"
android:configChanges="keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
android:excludeFromRecents="true"
android:launchMode="singleTask"
android:taskAffinity=""
android:theme="@style/Theme.MessengerProj.PopupNotification"
android:windowSoftInputMode="adjustResize|stateHidden">
</activity>
<receiver
android:name=".AutoMessageHeardReceiver"
Binary file not shown.
-232
View File
@@ -1,232 +0,0 @@
1876;JM;Jamaica;XXX XXXX
1869;KN;Saint Kitts & Nevis;XXX XXXX
1868;TT;Trinidad & Tobago;XXX XXXX
1784;VC;Saint Vincent & the Grenadines;XXX XXXX
1767;DM;Dominica;XXX XXXX
1758;LC;Saint Lucia;XXX XXXX
1721;SX;Sint Maarten;XXX XXXX
1684;AS;American Samoa;XXX XXXX
1671;GU;Guam;XXX XXXX
1670;MP;Northern Mariana Islands;XXX XXXX
1664;MS;Montserrat;XXX XXXX
1649;TC;Turks & Caicos Islands;XXX XXXX
1473;GD;Grenada;XXX XXXX
1441;BM;Bermuda;XXX XXXX
1345;KY;Cayman Islands;XXX XXXX
1340;VI;US Virgin Islands;XXX XXXX
1284;VG;British Virgin Islands;XXX XXXX
1268;AG;Antigua & Barbuda;XXX XXXX
1264;AI;Anguilla;XXX XXXX
1246;BB;Barbados;XXX XXXX
1242;BS;Bahamas;XXX XXXX
998;UZ;Uzbekistan;XX XXXXXXX
996;KG;Kyrgyzstan;XXX XXXXXX
995;GE;Georgia;XXX XXX XXX
994;AZ;Azerbaijan;XX XXX XXXX
993;TM;Turkmenistan;XX XXXXXX
992;TJ;Tajikistan;XX XXX XXXX
977;NP;Nepal;XX XXXX XXXX
976;MN;Mongolia;XX XX XXXX
975;BT;Bhutan;XX XXX XXX
974;QA;Qatar;XX XXX XXX
973;BH;Bahrain;XXXX XXXX
972;IL;Israel;XX XXX XXXX
971;AE;United Arab Emirates;XX XXX XXXX
970;PS;Palestine;XXX XX XXXX
968;OM;Oman;XXXX XXXX
967;YE;Yemen;XXX XXX XXX
966;SA;Saudi Arabia;XX XXX XXXX
965;KW;Kuwait;XXXX XXXX
964;IQ;Iraq;XXX XXX XXXX
963;SY;Syria;XXX XXX XXX
962;JO;Jordan;X XXXX XXXX
961;LB;Lebanon
960;MV;Maldives;XXX XXXX
886;TW;Taiwan;XXX XXX XXX
880;BD;Bangladesh
856;LA;Laos;XX XX XXX XXX
855;KH;Cambodia
853;MO;Macau;XXXX XXXX
852;HK;Hong Kong;X XXX XXXX
850;KP;North Korea
692;MH;Marshall Islands
691;FM;Micronesia
690;TK;Tokelau
689;PF;French Polynesia
688;TV;Tuvalu
687;NC;New Caledonia
686;KI;Kiribati
685;WS;Samoa
683;NU;Niue
682;CK;Cook Islands
681;WF;Wallis & Futuna
680;PW;Palau
679;FJ;Fiji
678;VU;Vanuatu
677;SB;Solomon Islands
676;TO;Tonga
675;PG;Papua New Guinea
674;NR;Nauru
673;BN;Brunei Darussalam;XXX XXXX
672;NF;Norfolk Island
670;TL;Timor-Leste
599;BQ;Bonaire, Sint Eustatius & Saba
599;CW;Curaçao
598;UY;Uruguay;X XXX XXXX
597;SR;Suriname;XXX XXXX
596;MQ;Martinique
595;PY;Paraguay;XXX XXX XXX
594;GF;French Guiana
593;EC;Ecuador;XX XXX XXXX
592;GY;Guyana
591;BO;Bolivia;X XXX XXXX
590;GP;Guadeloupe;XXX XX XX XX
509;HT;Haiti
508;PM;Saint Pierre & Miquelon
507;PA;Panama;XXXX XXXX
506;CR;Costa Rica;XXXX XXXX
505;NI;Nicaragua;XXXX XXXX
504;HN;Honduras;XXXX XXXX
503;SV;El Salvador;XXXX XXXX
502;GT;Guatemala;X XXX XXXX
501;BZ;Belize
500;FK;Falkland Islands
423;LI;Liechtenstein
421;SK;Slovakia;XXX XXX XXX
420;CZ;Czech Republic;XXX XXX XXX
389;MK;Macedonia;XX XXX XXX
387;BA;Bosnia & Herzegovina;XX XXX XXX
386;SI;Slovenia;XX XXX XXX
385;HR;Croatia
382;ME;Montenegro
381;RS;Serbia;XX XXX XXXX
380;UA;Ukraine;XX XXX XX XX
378;SM;San Marino;XXX XXX XXXX
377;MC;Monaco;XXXX XXXX
376;AD;Andorra;XX XX XX
375;BY;Belarus;XX XXX XXXX
374;AM;Armenia;XX XXX XXX
373;MD;Moldova;XX XXX XXX
372;EE;Estonia
371;LV;Latvia;XXX XXXXX
370;LT;Lithuania;XXX XXXXX
359;BG;Bulgaria
358;FI;Finland
357;CY;Cyprus;XXXX XXXX
356;MT;Malta;XX XX XX XX
355;AL;Albania;XX XXX XXXX
354;IS;Iceland;XXX XXXX
353;IE;Ireland;XX XXX XXXX
352;LU;Luxembourg
351;PT;Portugal;X XXXX XXXX
350;GI;Gibraltar;XXXX XXXX
299;GL;Greenland;XXX XXX
298;FO;Faroe Islands;XXX XXX
297;AW;Aruba;XXX XXXX
291;ER;Eritrea;X XXX XXX
290;SH;Saint Helena;XX XXX
269;KM;Comoros;XXX XXXX
268;SZ;Swaziland;XXXX XXXX
267;BW;Botswana;XX XXX XXX
266;LS;Lesotho;XX XXX XXX
265;MW;Malawi;77 XXX XXXX
264;NA;Namibia;XX XXX XXXX
263;ZW;Zimbabwe;XX XXX XXXX
262;RE;Réunion;XXX XXX XXX
261;MG;Madagascar;XX XX XXX XX
260;ZM;Zambia;XX XXX XXXX
258;MZ;Mozambique;XX XXX XXXX
257;BI;Burundi;XX XX XXXX
256;UG;Uganda;XX XXX XXXX
255;TZ;Tanzania;XX XXX XXXX
254;KE;Kenya;XXX XXX XXX
253;DJ;Djibouti;XX XX XX XX
252;SO;Somalia;XX XXX XXX
251;ET;Ethiopia;XX XXX XXXX
250;RW;Rwanda;XXX XXX XXX
249;SD;Sudan;XX XXX XXXX
248;SC;Seychelles;X XX XX XX
247;SH;Saint Helena;XXXX
246;IO;Diego Garcia;XXX XXXX
245;GW;Guinea-Bissau;XXX XXXX
244;AO;Angola;XXX XXX XXX
243;CD;Congo (Dem. Rep.);XX XXX XXXX
242;CG;Congo (Rep.);XX XXX XXXX
241;GA;Gabon;X XX XX XX
240;GQ;Equatorial Guinea;XXX XXX XXX
239;ST;São Tomé & Príncipe;XX XXXXX
238;CV;Cape Verde;XXX XXXX
237;CM;Cameroon;XXXX XXXX
236;CF;Central African Rep.;XX XX XX XX
235;TD;Chad;XX XX XX XX
234;NG;Nigeria
233;GH;Ghana
232;SL;Sierra Leone;XX XXX XXX
231;LR;Liberia
230;MU;Mauritius
229;BJ;Benin;XX XXX XXX
228;TG;Togo;XX XXX XXX
227;NE;Niger;XX XX XX XX
226;BF;Burkina Faso;XX XX XX XX
225;CI;Côte d`Ivoire;XX XXX XXX
224;GN;Guinea;XXX XXX XXX
223;ML;Mali;XXXX XXXX
222;MR;Mauritania;XXXX XXXX
221;SN;Senegal;XX XXX XXXX
220;GM;Gambia;XXX XXXX
218;LY;Libya;XX XXX XXXX
216;TN;Tunisia;XX XXX XXX
213;DZ;Algeria;XXX XX XX XX
212;MA;Morocco;XX XXX XXXX
211;SS;South Sudan;XX XXX XXXX
98;IR;Iran;XXX XXX XXXX
95;MM;Myanmar
94;LK;Sri Lanka;XX XXX XXXX
93;AF;Afghanistan;XXX XXX XXX
92;PK;Pakistan;XXX XXX XXXX
91;IN;India;XXXXX XXXXX
90;TR;Turkey;XXX XXX XXXX
86;CN;China;XXX XXXX XXXX
84;VN;Vietnam
82;KR;South Korea
81;JP;Japan;XX XXXX XXXX
66;TH;Thailand;X XXXX XXXX
65;SG;Singapore;XXXX XXXX
64;NZ;New Zealand
63;PH;Philippines;XXX XXX XXXX
62;ID;Indonesia
61;AU;Australia;XXX XXX XXX
60;MY;Malaysia
58;VE;Venezuela;XXX XXX XXXX
57;CO;Colombia;XXX XXX XXXX
56;CL;Chile;X XXXX XXXX
55;BR;Brazil;XX XXXXX XXXX
54;AR;Argentina
53;CU;Cuba;XXXX XXXX
52;MX;Mexico
51;PE;Peru;XXX XXX XXX
49;DE;Germany
48;PL;Poland;XX XXX XXXX
47;NO;Norway;XXXX XXXX
46;SE;Sweden;XX XXX XXXX
45;DK;Denmark;XXXX XXXX
44;GB;United Kingdom;XXXX XXXXXX
43;AT;Austria
42;YL;Y-land
41;CH;Switzerland;XX XXX XXXX
40;RO;Romania;XXX XXX XXX
39;IT;Italy
36;HU;Hungary;XXX XXX XXX
34;ES;Spain;XXX XXX XXX
33;FR;France;X XX XX XX XX
32;BE;Belgium;XXX XX XX XX
31;NL;Netherlands;X XX XX XX XX
30;GR;Greece;XXX XXX XXXX
27;ZA;South Africa;XX XXX XXXX
20;EG;Egypt;XX XXXX XXXX
7;KZ;Kazakhstan;XXX XXX XX XX
7;RU;Russian Federation;XXX XXX XXXX
1;PR;Puerto Rico;XXX XXX XXXX
1;DO;Dominican Rep.;XXX XXX XXXX
1;CA;Canada;XXX XXX XXXX
1;US;USA;XXX XXX XXXX
Binary file not shown.
@@ -1,10 +1,24 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -83,10 +97,6 @@ public class AndroidUtilities {
private static final Hashtable<String, Typeface> typefaceCache = new Hashtable<>();
private static int prevOrientation = -10;
private static boolean waitingForSms = false;
private static boolean waitingForCall = false;
private static final Object smsLock = new Object();
private static final Object callLock = new Object();
public static int statusBarHeight = 0;
public static float density = 1;
@@ -98,9 +108,6 @@ public class AndroidUtilities {
private static Boolean isTablet = null;
private static int adjustOwnerClassGuid = 0;
private static Paint roundPaint;
private static RectF bitmapRect;
public static Pattern WEB_URL = null;
static {
try {
@@ -247,34 +254,6 @@ public class AndroidUtilities {
}
}
public static boolean isGoogleMapsInstalled(final BaseFragment fragment) {
try {
ApplicationLoader.applicationContext.getPackageManager().getApplicationInfo("com.google.android.apps.maps", 0);
return true;
} catch (PackageManager.NameNotFoundException e) {
if (fragment.getParentActivity() == null) {
return false;
}
AlertDialog.Builder builder = new AlertDialog.Builder(fragment.getParentActivity());
builder.setMessage("Install Google Maps?");
builder.setCancelable(true);
builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
try {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=com.google.android.apps.maps"));
fragment.getParentActivity().startActivityForResult(intent, 500);
} catch (Exception e) {
FileLog.e("messenger", e);
}
}
});
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
fragment.showDialog(builder.create());
return false;
}
}
public static boolean isInternalUri(Uri uri) {
String pathString = uri.getPath();
if (pathString == null) {
@@ -361,34 +340,6 @@ public class AndroidUtilities {
}
}
public static boolean isWaitingForSms() {
boolean value;
synchronized (smsLock) {
value = waitingForSms;
}
return value;
}
public static void setWaitingForSms(boolean value) {
synchronized (smsLock) {
waitingForSms = value;
}
}
public static boolean isWaitingForCall() {
boolean value;
synchronized (callLock) {
value = waitingForCall;
}
return value;
}
public static void setWaitingForCall(boolean value) {
synchronized (callLock) {
waitingForCall = value;
}
}
public static void showKeyboard(View view) {
if (view == null) {
return;
@@ -429,6 +380,7 @@ public class AndroidUtilities {
}
}
/*
public static File getCacheDir() {
String state = null;
try {
@@ -456,6 +408,7 @@ public class AndroidUtilities {
}
return new File("");
}
*/
public static int dp(float value) {
if (value == 0) {
@@ -502,10 +455,6 @@ public class AndroidUtilities {
return (cm / 2.54f) * (isX ? displayMetrics.xdpi : displayMetrics.ydpi);
}
public static int getPeerLayerVersion(int layer) {
return (layer >> 16) & 0xffff;
}
public static void runOnUIThread(Runnable runnable) {
runOnUIThread(runnable, 0);
}
@@ -583,78 +532,6 @@ public class AndroidUtilities {
}
}
/*
public static AlertDialog.Builder buildTTLAlert(final Context context, final TLRPC.EncryptedChat encryptedChat) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(LocaleController.getString("MessageLifetime", R.string.MessageLifetime));
final NumberPicker numberPicker = new NumberPicker(context);
numberPicker.setMinValue(0);
numberPicker.setMaxValue(20);
if (encryptedChat.ttl > 0 && encryptedChat.ttl < 16) {
numberPicker.setValue(encryptedChat.ttl);
} else if (encryptedChat.ttl == 30) {
numberPicker.setValue(16);
} else if (encryptedChat.ttl == 60) {
numberPicker.setValue(17);
} else if (encryptedChat.ttl == 60 * 60) {
numberPicker.setValue(18);
} else if (encryptedChat.ttl == 60 * 60 * 24) {
numberPicker.setValue(19);
} else if (encryptedChat.ttl == 60 * 60 * 24 * 7) {
numberPicker.setValue(20);
} else if (encryptedChat.ttl == 0) {
numberPicker.setValue(0);
}
numberPicker.setFormatter(new NumberPicker.Formatter() {
@Override
public String format(int value) {
if (value == 0) {
return LocaleController.getString("ShortMessageLifetimeForever", R.string.ShortMessageLifetimeForever);
} else if (value >= 1 && value < 16) {
return AndroidUtilities.formatTTLString(value);
} else if (value == 16) {
return AndroidUtilities.formatTTLString(30);
} else if (value == 17) {
return AndroidUtilities.formatTTLString(60);
} else if (value == 18) {
return AndroidUtilities.formatTTLString(60 * 60);
} else if (value == 19) {
return AndroidUtilities.formatTTLString(60 * 60 * 24);
} else if (value == 20) {
return AndroidUtilities.formatTTLString(60 * 60 * 24 * 7);
}
return "";
}
});
builder.setView(numberPicker);
builder.setNegativeButton(LocaleController.getString("Done", R.string.Done), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int oldValue = encryptedChat.ttl;
which = numberPicker.getValue();
if (which >= 0 && which < 16) {
encryptedChat.ttl = which;
} else if (which == 16) {
encryptedChat.ttl = 30;
} else if (which == 17) {
encryptedChat.ttl = 60;
} else if (which == 18) {
encryptedChat.ttl = 60 * 60;
} else if (which == 19) {
encryptedChat.ttl = 60 * 60 * 24;
} else if (which == 20) {
encryptedChat.ttl = 60 * 60 * 24 * 7;
}
if (oldValue != encryptedChat.ttl) {
//SecretChatHelper.getInstance().sendTTLMessage(encryptedChat, null);
//MessagesStorage.getInstance().updateEncryptedChatTTL(encryptedChat);
}
}
});
return builder;
}
*/
public static void clearCursorDrawable(EditText editText) {
if (editText == null) {
return;
@@ -681,58 +558,13 @@ public class AndroidUtilities {
}
}
private static Intent createShortcutIntent(long did, boolean forDelete) {
private static Intent createShortcutIntent(int did, Bitmap bitmap) {
Intent shortcutIntent = new Intent(ApplicationLoader.applicationContext, OpenChatReceiver.class);
/*
int lower_id = (int) did;
int high_id = (int) (did >> 32);
TLRPC.User user = null;
TLRPC.Chat chat = null;
if (lower_id == 0) {
shortcutIntent.putExtra("encId", high_id);
TLRPC.EncryptedChat encryptedChat = MessagesController.getInstance().getEncryptedChat(high_id);
if (encryptedChat == null) {
return null;
}
user = MessagesController.getInstance().getUser(encryptedChat.user_id);
} else if (lower_id > 0) {
shortcutIntent.putExtra("userId", lower_id);
user = MessagesController.getInstance().getUser(lower_id);
} else if (lower_id < 0) {
chat = MessagesController.getInstance().getChat(-lower_id);
shortcutIntent.putExtra("chatId", -lower_id);
} else {
return null;
}
if (user == null && chat == null) {
return null;
}
String name;
TLRPC.FileLocation photo = null;
if (user != null) {
name = ContactsController.formatName(user.first_name, user.last_name);
if (user.photo != null) {
photo = user.photo.photo_small;
}
} else {
name = chat.title;
if (chat.photo != null) {
photo = chat.photo.photo_small;
}
}
*/
TLRPC.FileLocation photo = null;
shortcutIntent.putExtra("chatId", did);
MrChat mrChat = MrMailbox.getChat((int)did);
MrChat mrChat = MrMailbox.getChat(did);
if( mrChat.getId() == 0 ) { return null; }
String name = mrChat.getName();
shortcutIntent.setAction("com.b44t.messenger.openchat" + did);
shortcutIntent.addFlags(0x4000000);
@@ -740,70 +572,15 @@ public class AndroidUtilities {
addIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
addIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, name);
addIntent.putExtra("duplicate", false);
if (!forDelete) {
Bitmap bitmap = null;
if (photo != null) {
try {
File path = FileLoader.getPathToAttach(photo, true);
bitmap = BitmapFactory.decodeFile(path.toString());
if (bitmap != null) {
int size = AndroidUtilities.dp(58);
Bitmap result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
result.eraseColor(Color.TRANSPARENT);
Canvas canvas = new Canvas(result);
BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
if (roundPaint == null) {
roundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
bitmapRect = new RectF();
}
float scale = size / (float) bitmap.getWidth();
canvas.save();
canvas.scale(scale, scale);
roundPaint.setShader(shader);
bitmapRect.set(0, 0, bitmap.getWidth(), bitmap.getHeight());
canvas.drawRoundRect(bitmapRect, bitmap.getWidth(), bitmap.getHeight(), roundPaint);
canvas.restore();
Drawable drawable = ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.book_logo);
int w = AndroidUtilities.dp(15);
int left = size - w - AndroidUtilities.dp(2);
int top = size - w - AndroidUtilities.dp(2);
drawable.setBounds(left, top, left + w, top + w);
drawable.draw(canvas);
try {
canvas.setBitmap(null);
} catch (Exception e) {
//don't promt, this will crash on 2.x
}
bitmap = result;
}
} catch (Throwable e) {
FileLog.e("messenger", e);
}
}
if (bitmap != null) {
addIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON, bitmap);
} else {
/*if (user != null) {
if (user.bot) {
addIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext(ApplicationLoader.applicationContext, R.drawable.book_bot));
} else {
addIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext(ApplicationLoader.applicationContext, R.drawable.book_user));
}
} else if (chat != null) {
if (ChatObject.isChannel(chat) && !chat.megagroup) {
addIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext(ApplicationLoader.applicationContext, R.drawable.book_channel));
} else {*/
addIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext(ApplicationLoader.applicationContext, R.drawable.book_group));
/*}
}*/
}
if( bitmap != null ) {
addIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON, bitmap);
}
return addIntent;
}
public static void installShortcut(long did) {
public static void installShortcut(int did, Bitmap bitmap) {
try {
Intent addIntent = createShortcutIntent(did, false);
Intent addIntent = createShortcutIntent(did, bitmap);
addIntent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
ApplicationLoader.applicationContext.sendBroadcast(addIntent);
} catch (Exception e) {
@@ -811,9 +588,9 @@ public class AndroidUtilities {
}
}
public static void uninstallShortcut(long did) {
public static void uninstallShortcut(int did) {
try {
Intent addIntent = createShortcutIntent(did, true);
Intent addIntent = createShortcutIntent(did, null);
addIntent.setAction("com.android.launcher.action.UNINSTALL_SHORTCUT");
ApplicationLoader.applicationContext.sendBroadcast(addIntent);
} catch (Exception e) {
@@ -1007,55 +784,6 @@ public class AndroidUtilities {
animatorSet.start();
}
/*public static String ellipsize(String text, int maxLines, int maxWidth, TextPaint paint) {
if (text == null || paint == null) {
return null;
}
int count;
int offset = 0;
StringBuilder result = null;
TextView
for (int a = 0; a < maxLines; a++) {
count = paint.breakText(text, true, maxWidth, null);
if (a != maxLines - 1) {
if (result == null) {
result = new StringBuilder(count * maxLines + 1);
}
boolean foundSpace = false;
for (int c = count - 1; c >= offset; c--) {
if (text.charAt(c) == ' ') {
foundSpace = true;
result.append(text.substring(offset, c - 1));
offset = c - 1;
}
}
if (!foundSpace) {
offset = count;
}
text = text.substring(0, offset);
} else if (maxLines == 1) {
return text.substring(0, count);
} else {
result.append(text.substring(0, count));
}
}
return result.toString();
}*/
/*public static void turnOffHardwareAcceleration(Window window) {
if (window == null || Build.MODEL == null) {
return;
}
if (Build.MODEL.contains("GT-S5301") ||
Build.MODEL.contains("GT-S5303") ||
Build.MODEL.contains("GT-B5330") ||
Build.MODEL.contains("GT-S5302") ||
Build.MODEL.contains("GT-S6012B") ||
Build.MODEL.contains("MegaFon_SP-AI")) {
window.clearFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
}
}*/
public static void addToClipboard(CharSequence str) {
try {
android.content.ClipboardManager clipboard = (android.content.ClipboardManager) ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE);
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -223,23 +238,19 @@ public class ApplicationLoader extends Application {
editor.commit();
}
// open() sqlite file (you can inspect the file eg. with "Tools / Android Device Monitor / File Explorer")
// open() should be called before MessagesController.getInstance() as this also initilizes directories based upon getBlobdir().
File dbfile = new File(getFilesDirFixed(), "messenger.db");
MrMailbox.open(dbfile.getAbsolutePath());
MrMailbox.connect();
// create other default objects
MessagesController.getInstance();
ConnectionsManager.getInstance().init(deviceModel, systemVersion, appVersion, langCode, configPath, FileLog.getNetworkLogPath(), UserConfig.getClientUserId(), enablePushConnection);
if (UserConfig.getCurrentUser() != null) {
MessagesController.getInstance().putUser(UserConfig.getCurrentUser(), true);
SendMessagesHelper.getInstance().checkUnsentMessages();
}
ApplicationLoader app = (ApplicationLoader)ApplicationLoader.applicationContext;
FileLog.e("messenger", "app initied");
//ContactsController.getInstance().checkAppAccount();
MediaController.getInstance();
// EDIT BY MR - open my sqlite file (you can inspect the file eg. with "Tools / Android Device Monitor / File Explorer")
File dbfile = new File(getFilesDirFixed(), "messenger.db");
MrMailbox.open(dbfile.getAbsolutePath(), "");
MrMailbox.connect();
}
@Override
@@ -255,45 +266,13 @@ public class ApplicationLoader extends Application {
// however, we may want to to have a look at onPause() eg. of activities (eg. for flushing data, if needed)
MrMailbox.MrCallback(0, 0, 0); // do not remove this call; this makes sure, the function is not removed from build or warnings are printed!
MrMailbox.init();
MrMailbox.MrStockAddStr(1, LocaleController.getString("NoMessages", R.string.NoMessages));
MrMailbox.MrStockAddStr(2, LocaleController.getString("FromSelf", R.string.FromSelf));
MrMailbox.MrStockAddStr(3, LocaleController.getString("Draft", R.string.Draft));
MrMailbox.MrStockAddStr(4, LocaleController.getString("MemberSg", R.string.MemberSg));
MrMailbox.MrStockAddStr(5, LocaleController.getString("MemberPl", R.string.MemberPl));
MrMailbox.MrStockAddStr(6, LocaleController.getString("ContactSg", R.string.ContactSg));
MrMailbox.MrStockAddStr(7, LocaleController.getString("ContactPl", R.string.ContactPl));
MrMailbox.MrStockAddStr(8, LocaleController.getString("Deaddrop", R.string.Deaddrop));
MrMailbox.MrStockAddStr(9, LocaleController.getString("AttachPhoto", R.string.AttachPhoto));
MrMailbox.MrStockAddStr(10, LocaleController.getString("AttachVideo", R.string.AttachVideo));
MrMailbox.MrStockAddStr(11, LocaleController.getString("AttachAudio", R.string.AttachAudio));
MrMailbox.MrStockAddStr(12, LocaleController.getString("AttachDocument", R.string.AttachDocument));
MrMailbox.MrStockAddStr(13, LocaleController.getString("DefaultStatusText", R.string.DefaultStatusText));
MrMailbox.MrStockAddStr(14, LocaleController.getString("SubjectPrefix", R.string.SubjectPrefix));
MrMailbox.initStockStrings();
applicationHandler = new Handler(applicationContext.getMainLooper());
startPushService();
}
/*public static void sendRegIdToBackend(final String token) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
UserConfig.pushString = token;
UserConfig.registeredForPush = false;
UserConfig.saveConfig(false);
if (UserConfig.getClientUserId() != 0) {
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
MessagesController.getInstance().registerForPush(token);
}
});
}
}
});
}*/
public static void startPushService() {
SharedPreferences preferences = applicationContext.getSharedPreferences("Notifications", MODE_PRIVATE);
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -22,6 +37,7 @@ public class AutoMessageHeardReceiver extends BroadcastReceiver {
if (dialog_id == 0 || max_id == 0) {
return;
}
MessagesController.getInstance().markDialogAsRead(dialog_id, max_id, max_id, 0, true, false);
MrMailbox.markseenChat((int)dialog_id);
NotificationsController.getInstance().removeSeenMessages();
}
}
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -32,7 +47,8 @@ public class AutoMessageReplyReceiver extends BroadcastReceiver {
if (dialog_id == 0 || max_id == 0) {
return;
}
SendMessagesHelper.getInstance().sendMessageText(text.toString(), dialog_id, null, null, true, null, null);
MessagesController.getInstance().markDialogAsRead(dialog_id, max_id, max_id, 0, true, false);
SendMessagesHelper.getInstance().sendMessageText(text.toString(), dialog_id, null, null);
MrMailbox.markseenChat((int)dialog_id);
NotificationsController.getInstance().removeSeenMessages();
}
}
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -1,10 +1,24 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (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;
@@ -1,30 +0,0 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
package com.b44t.messenger;
public class ChatObject {
public static final int CHAT_TYPE_CHAT = 0;
public static boolean isNotInChat(TLRPC.Chat chat) {
return chat == null || chat instanceof TLRPC.TL_chatEmpty || chat.left || chat.kicked || chat.deactivated;
}
public static boolean isChannel(TLRPC.Chat chat) {
return false;
}
public static boolean isChannel(int chatId) {
return false;
}
public static boolean canWriteToChat(TLRPC.Chat chat) {
return true;
}
}
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -29,6 +44,7 @@ public class ClearCacheService extends IntentService {
protected void onHandleIntent(Intent intent) {
ApplicationLoader.postInitApplication();
/*
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
final int keepMedia = preferences.getInt("keep_media", 2);
if (keepMedia == 2) {
@@ -78,5 +94,6 @@ public class ClearCacheService extends IntentService {
}
}
});
*/
}
}
@@ -1,51 +1,71 @@
/*
* This is the source code of Telegram for Android v. 1.3.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (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/ .
*
*******************************************************************************
*
* File: ContactsController.java
* Authors: Björn Petersen
*
******************************************************************************/
package com.b44t.messenger;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.net.Uri;
import android.os.Build;
import android.provider.ContactsContract;
import android.util.Log;
import android.view.View;
import com.b44t.ui.Components.AvatarDrawable;
import java.io.InputStream;
import java.util.HashMap;
public class ContactsController {
static ContentResolver s_cr;
private static final String TAG = "ContactsController";
public static class Contact {
public String name;
public String email;
}
private String[] projectionNames = {
private final static String[] projectionNames = {
ContactsContract.Data.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Email.ADDRESS
};
private static volatile ContactsController Instance = null;
public static ContactsController getInstance() {
ContactsController localInstance = Instance;
if (localInstance == null) {
synchronized (ContactsController.class) {
localInstance = Instance;
if (localInstance == null) {
Instance = localInstance = new ContactsController();
}
}
}
return localInstance;
}
public ContactsController() {
}
public String readContactsFromPhoneBook() {
public static String readContactsFromPhoneBook() {
HashMap<String, String> contactsMap = new HashMap<String, String>();
String allContacts = "";
try {
@@ -77,7 +97,7 @@ public class ContactsController {
return allContacts;
}
private boolean hasContactsPermission() {
private static boolean hasContactsPermission() {
if (Build.VERSION.SDK_INT >= 23) {
return ApplicationLoader.applicationContext.checkSelfPermission(android.Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED;
}
@@ -89,14 +109,14 @@ public class ContactsController {
return false;
}
} catch (Exception e) {
FileLog.e("messenger", e);
;
} finally {
try {
if (cursor != null) {
cursor.close();
}
} catch (Exception e) {
FileLog.e("messenger", e);
;
}
}
return true;
@@ -134,4 +154,233 @@ public class ContactsController {
}
return result.toString();
}
/* Handle contact images
**********************************************************************************************/
static class AvtCacheEntry {
public Bitmap m_avatarBitmap;
public String m_fallbackName;
public boolean m_needsReload;
AvtCacheEntry(Bitmap avatarBitmap, String fallbackName) {
m_avatarBitmap = avatarBitmap;
m_fallbackName = fallbackName;
m_needsReload = false;
}
}
private final static String[] s_projectionAvatars = new String[]{
ContactsContract.Contacts._ID,
ContactsContract.Contacts.PHOTO_ID,
ContactsContract.CommonDataKinds.Email.ADDRESS
//ContactsContract.CommonDataKinds.Email.DISPLAY_NAME,
};
private static final Object s_sync = new Object();
private static HashMap<String, AvtCacheEntry> s_avtCache = new HashMap<>();
public static void cleanupAvatarCache() {
// to detect changes of the avatar images eg. in the Contacts App,
// this function should be called whenever the App goes to background or back to foreground.
// instead of emptying the cache, we force a reloading (looks smarter - most times, the avatars do not change)
synchronized (s_sync) {
for (AvtCacheEntry cacheEntry : s_avtCache.values()) {
cacheEntry.m_needsReload = true;
}
}
}
public static void setupAvatar(final View avtView,
final ImageReceiver avtImageReceiver,
final AvatarDrawable avtDrawable,
MrContact mrContact,
MrChat mrChat)
{
// get email/name to search avatar image for
String tempEmail = null;
String tempName = "";
if (mrContact != null) {
tempEmail = mrContact.getAddr();
tempName = mrContact.getDisplayName();
} else if (mrChat != null) {
tempName = mrChat.getName();
if (mrChat.getType() == MrChat.MR_CHAT_NORMAL) {
int[] contact_ids = MrMailbox.getChatContacts(mrChat.getId());
if (contact_ids.length == 1) {
MrContact mrc = MrMailbox.getContact(contact_ids[0]);
tempEmail = mrc.getAddr();
tempName = mrc.getDisplayName();
}
}
}
setupAvatarByStrings(avtView, avtImageReceiver, avtDrawable, tempEmail, tempName);
}
public static void setupAvatarByStrings(final View avtView,
final ImageReceiver avtImageReceiver,
final AvatarDrawable avtDrawable,
String tempEmail,
String tempName)
{
if( tempEmail == null ) {
tempEmail = "fallback:" + tempName;
}
final String email = tempEmail;
final String fallbackName = tempName;
// bind e-mail+name address to view object to detect overwrites and discard loading old images (may happen on fast scrolling)
// moreover, check if the avatar is in cache
AvtCacheEntry cacheEntry;
synchronized (s_sync) {
avtImageReceiver.m_userDataUnique = email+fallbackName;
cacheEntry = s_avtCache.get(email+fallbackName);
}
if( cacheEntry != null )
{
// can use avatar from cache, very fine
if (cacheEntry.m_avatarBitmap != null) {
avtImageReceiver.setImageBitmap(cacheEntry.m_avatarBitmap);
} else {
avtDrawable.setInfoByName(cacheEntry.m_fallbackName);
avtImageReceiver.setImage(null, "50_50", avtDrawable, null, false);
}
}
else
{
// avatar is not in cache, empty the image (may be the bitmap of another use as we re-use the objects)
avtImageReceiver.setImage(null, "50_50", null, null, false);
}
if( cacheEntry==null || cacheEntry.m_needsReload )
{
// avatar is not in cache or needs reloading:
// load avatar in a working thread (when loaded, we'll add it to cache and invalidate back in the GUI thread)
Utilities.searchQueue.postRunnable(new Runnable() {
@Override
public void run() {
// is the avatar still desired?
synchronized (s_sync) {
if (!avtImageReceiver.m_userDataUnique.equals(email+fallbackName)) {
return;
}
}
// try to get avatar image from the address book
Bitmap tempBitmap = null;
if (!email.startsWith("fallback:")) {
try {
if (s_cr == null) {
s_cr = ApplicationLoader.applicationContext.getContentResolver();
}
Uri uri = Uri.withAppendedPath(ContactsContract.CommonDataKinds.Email.CONTENT_LOOKUP_URI, Uri.encode(email));
Cursor pCur = s_cr.query(uri, s_projectionAvatars, null, null, null);
if (pCur != null) {
if (pCur.getCount() > 0) {
while (pCur.moveToNext()) {
int contact_id = pCur.getInt(0);
int photo_id = pCur.getInt(1);
String addr = pCur.getString(2);
if (addr.equalsIgnoreCase(email) && contact_id > 0 && photo_id > 0) {
Bitmap tempBitmap2 = loadContactPhoto(s_cr, contact_id, photo_id);
if (tempBitmap2 != null) {
tempBitmap = createRoundBitmap(tempBitmap2);
}
break;
}
}
}
pCur.close();
}
} catch (Exception e) {
;
}
}
final Bitmap photoBitmap = tempBitmap;
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
// is the avatar still desired?
synchronized (s_sync) {
if (!avtImageReceiver.m_userDataUnique.equals(email+fallbackName)) {
return;
}
}
if (photoBitmap != null) {
avtImageReceiver.setImageBitmap(photoBitmap);
} else {
avtDrawable.setInfoByName(fallbackName);
avtImageReceiver.setImage(null, "50_50", avtDrawable, null, false);
}
avtView.invalidate();
synchronized (s_sync) {
s_avtCache.put(email+fallbackName, new AvtCacheEntry(photoBitmap, fallbackName));
}
}
});
}
});
}
}
// from http://stackoverflow.com/questions/2383580/how-do-i-load-a-contact-photo
public static Bitmap loadContactPhoto(ContentResolver cr, long contact_id, long photo_id)
{
// first try using photo_id
byte[] photoBytes = null;
Uri photoUri = ContentUris.withAppendedId(ContactsContract.Data.CONTENT_URI, photo_id);
Cursor c = cr.query(photoUri, new String[] {ContactsContract.CommonDataKinds.Photo.PHOTO}, null, null, null);
if( c != null ) {
try {
if (c.moveToFirst()) {
photoBytes = c.getBlob(0);
}
} catch (Exception e) {
;
} finally {
c.close();
}
}
if (photoBytes != null) {
return BitmapFactory.decodeByteArray(photoBytes, 0, photoBytes.length);
}
// second try using contact_id
Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contact_id);
InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(cr, uri);
if (input != null) {
return BitmapFactory.decodeStream(input);
}
return null;
}
private static Paint roundPaint;
private static RectF bitmapRect;
private static Bitmap createRoundBitmap(Bitmap bitmap) {
try {
Bitmap result = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
result.eraseColor(Color.TRANSPARENT);
Canvas canvas = new Canvas(result);
BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
if (roundPaint == null) {
roundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
bitmapRect = new RectF();
}
roundPaint.setShader(shader);
bitmapRect.set(0, 0, bitmap.getWidth(), bitmap.getHeight());
canvas.drawRoundRect(bitmapRect, bitmap.getWidth(), bitmap.getHeight(), roundPaint);
return result;
} catch (Throwable e) {
;
}
return null;
}
}
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -77,11 +92,13 @@ public class FileLoader {
mediaDirs = dirs;
}
/*
public File checkDirectory(int type) {
return mediaDirs.get(type);
}
*/
public File getDirectory(int type) {
public File getDirectory(int type) { // always returns the cache directory as this is the only one set in mediaDirs[] - we do not use the other directories at the moment
File dir = mediaDirs.get(type);
if (dir == null && type != MEDIA_DIR_CACHE) {
dir = mediaDirs.get(MEDIA_DIR_CACHE);
@@ -507,7 +524,7 @@ public class FileLoader {
if (message == null) {
return "";
}
if (message instanceof TLRPC.TL_messageService) {
/*if (message instanceof TLRPC.TL_messageService) {
if (message.action.photo != null) {
ArrayList<TLRPC.PhotoSize> sizes = message.action.photo.sizes;
if (sizes.size() > 0) {
@@ -517,7 +534,7 @@ public class FileLoader {
}
}
}
} else {
} else*/ {
if (message.media instanceof TLRPC.TL_messageMediaDocument) {
return getAttachFileName(message.media.document);
} else if (message.media instanceof TLRPC.TL_messageMediaPhoto) {
@@ -528,7 +545,7 @@ public class FileLoader {
return getAttachFileName(sizeFull);
}
}
} else if (message.media instanceof TLRPC.TL_messageMediaWebPage) {
} /*else if (message.media instanceof TLRPC.TL_messageMediaWebPage) {
if (message.media.webpage.photo != null) {
ArrayList<TLRPC.PhotoSize> sizes = message.media.webpage.photo.sizes;
if (sizes.size() > 0) {
@@ -540,7 +557,7 @@ public class FileLoader {
} else if (message.media.webpage.document != null) {
return getAttachFileName(message.media.webpage.document);
}
}
}*/
}
return "";
}
@@ -549,7 +566,7 @@ public class FileLoader {
if (message == null) {
return new File("");
}
if (message instanceof TLRPC.TL_messageService) {
/*if (message instanceof TLRPC.TL_messageService) {
if (message.action.photo != null) {
ArrayList<TLRPC.PhotoSize> sizes = message.action.photo.sizes;
if (sizes.size() > 0) {
@@ -559,7 +576,7 @@ public class FileLoader {
}
}
}
} else {
} else*/ {
if (message.media instanceof TLRPC.TL_messageMediaDocument) {
return getPathToAttach(message.media.document);
} else if (message.media instanceof TLRPC.TL_messageMediaPhoto) {
@@ -570,7 +587,7 @@ public class FileLoader {
return getPathToAttach(sizeFull);
}
}
} else if (message.media instanceof TLRPC.TL_messageMediaWebPage) {
} /*else if (message.media instanceof TLRPC.TL_messageMediaWebPage) {
if (message.media.webpage.document != null) {
return getPathToAttach(message.media.webpage.document);
} else if (message.media.webpage.photo != null) {
@@ -582,7 +599,7 @@ public class FileLoader {
}
}
}
}
}*/
}
return new File("");
}
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -1159,11 +1174,11 @@ public class ImageLoader {
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
if (MediaController.getInstance().canSaveToGallery() && messengerPath != null && finalFile != null && (location.endsWith(".mp4") || location.endsWith(".jpg"))) {
/*if (MediaController.getInstance().canSaveToGallery() && messengerPath != null && finalFile != null && (location.endsWith(".mp4") || location.endsWith(".jpg"))) {
if (finalFile.toString().startsWith(messengerPath.toString())) {
AndroidUtilities.addMediaToGallery(finalFile.toString());
}
}
}*/
NotificationCenter.getInstance().postNotificationName(NotificationCenter.FileDidLoaded, location);
ImageLoader.this.fileDidLoaded(location, finalFile, type);
}
@@ -1228,27 +1243,21 @@ public class ImageLoader {
filter.addDataScheme("file");
ApplicationLoader.applicationContext.registerReceiver(receiver, filter);
HashMap<Integer, File> mediaDirs = new HashMap<>();
File cachePath = AndroidUtilities.getCacheDir();
if (!cachePath.isDirectory()) {
try {
cachePath.mkdirs();
} catch (Exception e) {
FileLog.e("messenger", e);
}
}
try {
new File(cachePath, ".nomedia").createNewFile();
} catch (Exception e) {
FileLog.e("messenger", e);
}
mediaDirs.put(FileLoader.MEDIA_DIR_CACHE, cachePath);
FileLoader.getInstance().setMediaDirs(mediaDirs);
checkMediaPaths();
}
public void checkMediaPaths() {
HashMap<Integer, File> mediaDirs = new HashMap<>();
File cachePath = new File(MrMailbox.getBlobdir());
try {
new File(cachePath, ".nomedia").createNewFile();
} catch (Exception e) {
}
mediaDirs.put(FileLoader.MEDIA_DIR_CACHE, cachePath);
FileLoader.getInstance().setMediaDirs(mediaDirs);
/*
cacheOutQueue.postRunnable(new Runnable() {
@Override
public void run() {
@@ -1261,9 +1270,11 @@ public class ImageLoader {
});
}
});
*/
}
public HashMap<Integer, File> createMediaPaths() {
/*
public HashMap<Integer, File> createMediaPaths() { // not sure, but it seems as if these paths are not needed
HashMap<Integer, File> mediaDirs = new HashMap<>();
File cachePath = AndroidUtilities.getCacheDir();
if (!cachePath.isDirectory()) {
@@ -1344,6 +1355,7 @@ public class ImageLoader {
return mediaDirs;
}
*/
private boolean canMoveFiles(File from, File to, int type) {
RandomAccessFile file = null;
@@ -2230,6 +2242,7 @@ public class ImageLoader {
return ext;
}
/*
public static void saveMessageThumbs(TLRPC.Message message) {
TLRPC.PhotoSize photoSize = null;
if (message.media instanceof TLRPC.TL_messageMediaPhoto) {
@@ -2243,16 +2256,17 @@ public class ImageLoader {
if (message.media.document.thumb instanceof TLRPC.TL_photoCachedSize) {
photoSize = message.media.document.thumb;
}
} else if (message.media instanceof TLRPC.TL_messageMediaWebPage) {
if (message.media.webpage.photo != null) {
for (TLRPC.PhotoSize size : message.media.webpage.photo.sizes) {
if (size instanceof TLRPC.TL_photoCachedSize) {
photoSize = size;
break;
}
}
}
}
//else if (message.media instanceof TLRPC.TL_messageMediaWebPage) {
// if (message.media.webpage.photo != null) {
// for (TLRPC.PhotoSize size : message.media.webpage.photo.sizes) {
// if (size instanceof TLRPC.TL_photoCachedSize) {
// photoSize = size;
// break;
// }
// }
// }
//}
if (photoSize != null && photoSize.bytes != null && photoSize.bytes.length != 0) {
if (photoSize.location instanceof TLRPC.TL_fileLocationUnavailable) {
photoSize.location = new TLRPC.TL_fileLocation();
@@ -2287,17 +2301,20 @@ public class ImageLoader {
}
} else if (message.media instanceof TLRPC.TL_messageMediaDocument) {
message.media.document.thumb = newPhotoSize;
} else if (message.media instanceof TLRPC.TL_messageMediaWebPage) {
for (int a = 0; a < message.media.webpage.photo.sizes.size(); a++) {
if (message.media.webpage.photo.sizes.get(a) instanceof TLRPC.TL_photoCachedSize) {
message.media.webpage.photo.sizes.set(a, newPhotoSize);
break;
}
}
}
//else if (message.media instanceof TLRPC.TL_messageMediaWebPage) {
// for (int a = 0; a < message.media.webpage.photo.sizes.size(); a++) {
// if (message.media.webpage.photo.sizes.get(a) instanceof TLRPC.TL_photoCachedSize) {
// message.media.webpage.photo.sizes.set(a, newPhotoSize);
// break;
// }
// }
//}
}
}
*/
/*
public static void saveMessagesThumbs(ArrayList<TLRPC.Message> messages) {
if (messages == null || messages.isEmpty()) {
return;
@@ -2307,4 +2324,5 @@ public class ImageLoader {
saveMessageThumbs(message);
}
}
*/
}
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 1.3.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -14,6 +29,7 @@ import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
@@ -27,6 +43,7 @@ import com.b44t.ui.Components.AnimatedFileDrawable;
public class ImageReceiver implements NotificationCenter.NotificationCenterDelegate {
public interface ImageReceiverDelegate {
void didSetImage(ImageReceiver imageReceiver, boolean set, boolean thumb);
}
@@ -43,6 +60,11 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
public String ext;
}
public String m_userDataUnique = ""; // used to discard images loaded and no longer required as there was a new request
// before, we used "private static HashMap<View, String> s_viewBindings = new HashMap<>();" in ContactsController -
// however, this was a bad idea as this resulted in _lots_ of objects that were never freed...
private View parentView;
private Integer tag;
private Integer thumbTag;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 1.3.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -64,8 +79,6 @@ public class LocaleController {
private String languageOverride;
private boolean changingConfiguration = false;
private HashMap<String, String> translitChars;
private class TimeZoneChangedReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
@@ -887,580 +900,6 @@ public class LocaleController {
}
*/
public static String formatUserStatus(TLRPC.User user) {
if (user != null && user.status != null && user.status.expires == 0) {
if (user.status instanceof TLRPC.TL_userStatusRecently) {
user.status.expires = -100;
} else if (user.status instanceof TLRPC.TL_userStatusLastWeek) {
user.status.expires = -101;
} else if (user.status instanceof TLRPC.TL_userStatusLastMonth) {
user.status.expires = -102;
}
}
if (user != null && user.status != null && user.status.expires <= 0) {
if (MessagesController.getInstance().onlinePrivacy.containsKey(user.id)) {
return getString("Online", R.string.Online);
}
}
if (user == null || user.status == null || user.status.expires == 0 || UserObject.isDeleted(user) ) {
return getString("ALongTimeAgo", R.string.ALongTimeAgo);
} else {
int currentTime = ConnectionsManager.getInstance().getCurrentTime();
if (user.status.expires > currentTime) {
return getString("Online", R.string.Online);
} else {
if (user.status.expires == -1) {
return getString("Invisible", R.string.Invisible);
} else if (user.status.expires == -100) {
return getString("Lately", R.string.Lately);
} else if (user.status.expires == -101) {
return getString("WithinAWeek", R.string.WithinAWeek);
} else if (user.status.expires == -102) {
return getString("WithinAMonth", R.string.WithinAMonth);
} else {
return formatDateOnline(user.status.expires);
}
}
}
}
public String getTranslitString(String src) {
if (translitChars == null) {
translitChars = new HashMap<>(520);
translitChars.put("ȼ", "c");
translitChars.put("", "n");
translitChars.put("ɖ", "d");
translitChars.put("ỿ", "y");
translitChars.put("", "o");
translitChars.put("ø", "o");
translitChars.put("", "a");
translitChars.put("ʯ", "h");
translitChars.put("ŷ", "y");
translitChars.put("ʞ", "k");
translitChars.put("", "u");
translitChars.put("", "aa");
translitChars.put("ij", "ij");
translitChars.put("", "l");
translitChars.put("ɪ", "i");
translitChars.put("", "b");
translitChars.put("ʀ", "r");
translitChars.put("ě", "e");
translitChars.put("", "ffi");
translitChars.put("ơ", "o");
translitChars.put("", "r");
translitChars.put("", "o");
translitChars.put("ǐ", "i");
translitChars.put("", "p");
translitChars.put("ý", "y");
translitChars.put("", "e");
translitChars.put("", "o");
translitChars.put("", "a");
translitChars.put("ʙ", "b");
translitChars.put("", "e");
translitChars.put("ƈ", "c");
translitChars.put("ɦ", "h");
translitChars.put("", "b");
translitChars.put("", "s");
translitChars.put("đ", "d");
translitChars.put("", "o");
translitChars.put("ɟ", "j");
translitChars.put("", "a");
translitChars.put("ɏ", "y");
translitChars.put("л", "l");
translitChars.put("ʌ", "v");
translitChars.put("", "p");
translitChars.put("", "fi");
translitChars.put("", "k");
translitChars.put("", "d");
translitChars.put("", "l");
translitChars.put("ė", "e");
translitChars.put("ё", "yo");
translitChars.put("", "k");
translitChars.put("ċ", "c");
translitChars.put("ʁ", "r");
translitChars.put("ƕ", "hv");
translitChars.put("ƀ", "b");
translitChars.put("", "o");
translitChars.put("ȣ", "ou");
translitChars.put("ǰ", "j");
translitChars.put("", "g");
translitChars.put("", "n");
translitChars.put("ɉ", "j");
translitChars.put("ǧ", "g");
translitChars.put("dz", "dz");
translitChars.put("ź", "z");
translitChars.put("", "au");
translitChars.put("ǖ", "u");
translitChars.put("", "g");
translitChars.put("ȯ", "o");
translitChars.put("ɐ", "a");
translitChars.put("ą", "a");
translitChars.put("õ", "o");
translitChars.put("ɻ", "r");
translitChars.put("", "o");
translitChars.put("ǟ", "a");
translitChars.put("ȴ", "l");
translitChars.put("ʂ", "s");
translitChars.put("", "fl");
translitChars.put("ȉ", "i");
translitChars.put("", "e");
translitChars.put("", "n");
translitChars.put("ï", "i");
translitChars.put("ñ", "n");
translitChars.put("", "i");
translitChars.put("ʇ", "t");
translitChars.put("", "z");
translitChars.put("", "y");
translitChars.put("ȳ", "y");
translitChars.put("", "s");
translitChars.put("ɽ", "r");
translitChars.put("ĝ", "g");
translitChars.put("в", "v");
translitChars.put("", "u");
translitChars.put("", "k");
translitChars.put("", "et");
translitChars.put("ī", "i");
translitChars.put("ť", "t");
translitChars.put("", "c");
translitChars.put("ʟ", "l");
translitChars.put("", "av");
translitChars.put("û", "u");
translitChars.put("æ", "ae");
translitChars.put("и", "i");
translitChars.put("ă", "a");
translitChars.put("ǘ", "u");
translitChars.put("", "s");
translitChars.put("", "r");
translitChars.put("", "a");
translitChars.put("ƃ", "b");
translitChars.put("", "h");
translitChars.put("", "s");
translitChars.put("", "e");
translitChars.put("ʜ", "h");
translitChars.put("", "x");
translitChars.put("", "k");
translitChars.put("", "d");
translitChars.put("ƣ", "oi");
translitChars.put("", "p");
translitChars.put("ħ", "h");
translitChars.put("", "v");
translitChars.put("", "w");
translitChars.put("ǹ", "n");
translitChars.put("ɯ", "m");
translitChars.put("ɡ", "g");
translitChars.put("ɴ", "n");
translitChars.put("", "p");
translitChars.put("", "v");
translitChars.put("ū", "u");
translitChars.put("", "b");
translitChars.put("", "p");
translitChars.put("ь", "");
translitChars.put("å", "a");
translitChars.put("ɕ", "c");
translitChars.put("", "o");
translitChars.put("", "a");
translitChars.put("ƒ", "f");
translitChars.put("ǣ", "ae");
translitChars.put("", "vy");
translitChars.put("", "ff");
translitChars.put("", "r");
translitChars.put("ô", "o");
translitChars.put("ǿ", "o");
translitChars.put("", "u");
translitChars.put("ȥ", "z");
translitChars.put("", "f");
translitChars.put("", "d");
translitChars.put("ȇ", "e");
translitChars.put("ȕ", "u");
translitChars.put("п", "p");
translitChars.put("ȵ", "n");
translitChars.put("ʠ", "q");
translitChars.put("", "a");
translitChars.put("ǩ", "k");
translitChars.put("ĩ", "i");
translitChars.put("", "u");
translitChars.put("ŧ", "t");
translitChars.put("ɾ", "r");
translitChars.put("ƙ", "k");
translitChars.put("", "t");
translitChars.put("", "q");
translitChars.put("", "a");
translitChars.put("н", "n");
translitChars.put("ʄ", "j");
translitChars.put("ƚ", "l");
translitChars.put("", "f");
translitChars.put("д", "d");
translitChars.put("", "s");
translitChars.put("", "r");
translitChars.put("", "v");
translitChars.put("ɵ", "o");
translitChars.put("", "c");
translitChars.put("", "u");
translitChars.put("", "z");
translitChars.put("", "u");
translitChars.put("ň", "n");
translitChars.put("ʍ", "w");
translitChars.put("", "a");
translitChars.put("lj", "lj");
translitChars.put("ɓ", "b");
translitChars.put("ɼ", "r");
translitChars.put("ò", "o");
translitChars.put("", "w");
translitChars.put("ɗ", "d");
translitChars.put("", "ay");
translitChars.put("ư", "u");
translitChars.put("", "b");
translitChars.put("ǜ", "u");
translitChars.put("", "e");
translitChars.put("ǡ", "a");
translitChars.put("ɥ", "h");
translitChars.put("", "o");
translitChars.put("ǔ", "u");
translitChars.put("ʎ", "y");
translitChars.put("ȱ", "o");
translitChars.put("", "e");
translitChars.put("ế", "e");
translitChars.put("ĭ", "i");
translitChars.put("", "e");
translitChars.put("", "t");
translitChars.put("", "d");
translitChars.put("", "h");
translitChars.put("", "s");
translitChars.put("ë", "e");
translitChars.put("", "m");
translitChars.put("ö", "o");
translitChars.put("é", "e");
translitChars.put("ı", "i");
translitChars.put("ď", "d");
translitChars.put("", "m");
translitChars.put("", "y");
translitChars.put("я", "ya");
translitChars.put("ŵ", "w");
translitChars.put("", "e");
translitChars.put("", "u");
translitChars.put("ƶ", "z");
translitChars.put("ĵ", "j");
translitChars.put("", "d");
translitChars.put("ŭ", "u");
translitChars.put("ʝ", "j");
translitChars.put("ж", "zh");
translitChars.put("ê", "e");
translitChars.put("ǚ", "u");
translitChars.put("ġ", "g");
translitChars.put("", "r");
translitChars.put("ƞ", "n");
translitChars.put("ъ", "");
translitChars.put("", "e");
translitChars.put("", "s");
translitChars.put("", "d");
translitChars.put("ķ", "k");
translitChars.put("", "ae");
translitChars.put("ɘ", "e");
translitChars.put("", "o");
translitChars.put("ḿ", "m");
translitChars.put("", "f");
translitChars.put("а", "a");
translitChars.put("", "a");
translitChars.put("", "oo");
translitChars.put("", "m");
translitChars.put("", "p");
translitChars.put("ц", "ts");
translitChars.put("", "u");
translitChars.put("", "k");
translitChars.put("", "h");
translitChars.put("ţ", "t");
translitChars.put("", "p");
translitChars.put("", "m");
translitChars.put("á", "a");
translitChars.put("", "n");
translitChars.put("", "v");
translitChars.put("è", "e");
translitChars.put("", "z");
translitChars.put("", "d");
translitChars.put("", "p");
translitChars.put("м", "m");
translitChars.put("ɫ", "l");
translitChars.put("", "z");
translitChars.put("ɱ", "m");
translitChars.put("", "r");
translitChars.put("", "v");
translitChars.put("ũ", "u");
translitChars.put("ß", "ss");
translitChars.put("т", "t");
translitChars.put("ĥ", "h");
translitChars.put("", "t");
translitChars.put("ʐ", "z");
translitChars.put("", "r");
translitChars.put("ɲ", "n");
translitChars.put("à", "a");
translitChars.put("", "y");
translitChars.put("", "y");
translitChars.put("", "oe");
translitChars.put("ы", "i");
translitChars.put("", "x");
translitChars.put("ȗ", "u");
translitChars.put("", "j");
translitChars.put("", "a");
translitChars.put("ʑ", "z");
translitChars.put("", "s");
translitChars.put("", "i");
translitChars.put("", "ao");
translitChars.put("ɀ", "z");
translitChars.put("ÿ", "y");
translitChars.put("ǝ", "e");
translitChars.put("ǭ", "o");
translitChars.put("", "d");
translitChars.put("", "l");
translitChars.put("ù", "u");
translitChars.put("", "a");
translitChars.put("", "b");
translitChars.put("", "u");
translitChars.put("к", "k");
translitChars.put("", "a");
translitChars.put("", "t");
translitChars.put("ƴ", "y");
translitChars.put("", "t");
translitChars.put("з", "z");
translitChars.put("", "l");
translitChars.put("ȷ", "j");
translitChars.put("", "z");
translitChars.put("", "h");
translitChars.put("", "w");
translitChars.put("", "k");
translitChars.put("", "o");
translitChars.put("î", "i");
translitChars.put("ģ", "g");
translitChars.put("ȅ", "e");
translitChars.put("ȧ", "a");
translitChars.put("", "a");
translitChars.put("щ", "sch");
translitChars.put("ɋ", "q");
translitChars.put("", "t");
translitChars.put("", "um");
translitChars.put("", "c");
translitChars.put("", "x");
translitChars.put("", "u");
translitChars.put("", "i");
translitChars.put("", "r");
translitChars.put("ś", "s");
translitChars.put("", "o");
translitChars.put("", "y");
translitChars.put("", "s");
translitChars.put("nj", "nj");
translitChars.put("ȁ", "a");
translitChars.put("", "t");
translitChars.put("ĺ", "l");
translitChars.put("ž", "z");
translitChars.put("", "th");
translitChars.put("ƌ", "d");
translitChars.put("ș", "s");
translitChars.put("š", "s");
translitChars.put("", "u");
translitChars.put("", "e");
translitChars.put("", "s");
translitChars.put("ɇ", "e");
translitChars.put("", "u");
translitChars.put("", "o");
translitChars.put("ȿ", "s");
translitChars.put("", "v");
translitChars.put("", "is");
translitChars.put("", "o");
translitChars.put("ɛ", "e");
translitChars.put("ǻ", "a");
translitChars.put("", "ffl");
translitChars.put("", "o");
translitChars.put("ȋ", "i");
translitChars.put("", "ue");
translitChars.put("ȡ", "d");
translitChars.put("", "z");
translitChars.put("", "w");
translitChars.put("", "a");
translitChars.put("", "t");
translitChars.put("ğ", "g");
translitChars.put("ɳ", "n");
translitChars.put("ʛ", "g");
translitChars.put("", "u");
translitChars.put("ф", "f");
translitChars.put("", "a");
translitChars.put("", "n");
translitChars.put("ɨ", "i");
translitChars.put("", "r");
translitChars.put("ǎ", "a");
translitChars.put("ſ", "s");
translitChars.put("у", "u");
translitChars.put("ȫ", "o");
translitChars.put("ɿ", "r");
translitChars.put("ƭ", "t");
translitChars.put("", "i");
translitChars.put("ǽ", "ae");
translitChars.put("", "v");
translitChars.put("ɶ", "oe");
translitChars.put("", "m");
translitChars.put("ż", "z");
translitChars.put("ĕ", "e");
translitChars.put("", "av");
translitChars.put("", "o");
translitChars.put("", "e");
translitChars.put("ɬ", "l");
translitChars.put("", "i");
translitChars.put("", "d");
translitChars.put("", "st");
translitChars.put("", "l");
translitChars.put("ŕ", "r");
translitChars.put("", "ou");
translitChars.put("ʈ", "t");
translitChars.put("ā", "a");
translitChars.put("э", "e");
translitChars.put("", "e");
translitChars.put("", "o");
translitChars.put("ç", "c");
translitChars.put("", "s");
translitChars.put("", "a");
translitChars.put("ų", "u");
translitChars.put("", "a");
translitChars.put("ǥ", "g");
translitChars.put("р", "r");
translitChars.put("", "k");
translitChars.put("", "z");
translitChars.put("ŝ", "s");
translitChars.put("", "e");
translitChars.put("ɠ", "g");
translitChars.put("", "l");
translitChars.put("", "f");
translitChars.put("", "x");
translitChars.put("х", "h");
translitChars.put("ǒ", "o");
translitChars.put("ę", "e");
translitChars.put("", "o");
translitChars.put("ƫ", "t");
translitChars.put("ǫ", "o");
translitChars.put("", "i");
translitChars.put("", "n");
translitChars.put("ć", "c");
translitChars.put("", "g");
translitChars.put("", "w");
translitChars.put("", "d");
translitChars.put("", "l");
translitChars.put("ч", "ch");
translitChars.put("œ", "oe");
translitChars.put("", "r");
translitChars.put("ļ", "l");
translitChars.put("ȑ", "r");
translitChars.put("ȭ", "o");
translitChars.put("", "n");
translitChars.put("", "ae");
translitChars.put("ŀ", "l");
translitChars.put("ä", "a");
translitChars.put("ƥ", "p");
translitChars.put("", "o");
translitChars.put("į", "i");
translitChars.put("ȓ", "r");
translitChars.put("dž", "dz");
translitChars.put("", "g");
translitChars.put("", "u");
translitChars.put("ō", "o");
translitChars.put("ľ", "l");
translitChars.put("", "w");
translitChars.put("ț", "t");
translitChars.put("ń", "n");
translitChars.put("ɍ", "r");
translitChars.put("ȃ", "a");
translitChars.put("ü", "u");
translitChars.put("", "l");
translitChars.put("", "o");
translitChars.put("", "o");
translitChars.put("", "b");
translitChars.put("ɹ", "r");
translitChars.put("", "r");
translitChars.put("ʏ", "y");
translitChars.put("", "f");
translitChars.put("", "h");
translitChars.put("ŏ", "o");
translitChars.put("ú", "u");
translitChars.put("", "r");
translitChars.put("ʮ", "h");
translitChars.put("ó", "o");
translitChars.put("ů", "u");
translitChars.put("", "o");
translitChars.put("", "p");
translitChars.put("", "i");
translitChars.put("", "u");
translitChars.put("ã", "a");
translitChars.put("", "i");
translitChars.put("", "t");
translitChars.put("", "e");
translitChars.put("", "u");
translitChars.put("í", "i");
translitChars.put("ɔ", "o");
translitChars.put("с", "s");
translitChars.put("й", "i");
translitChars.put("ɺ", "r");
translitChars.put("ɢ", "g");
translitChars.put("ř", "r");
translitChars.put("", "h");
translitChars.put("ű", "u");
translitChars.put("ȍ", "o");
translitChars.put("ш", "sh");
translitChars.put("", "l");
translitChars.put("", "h");
translitChars.put("ȶ", "t");
translitChars.put("ņ", "n");
translitChars.put("", "e");
translitChars.put("ì", "i");
translitChars.put("", "w");
translitChars.put("б", "b");
translitChars.put("ē", "e");
translitChars.put("", "e");
translitChars.put("ł", "l");
translitChars.put("", "o");
translitChars.put("ɭ", "l");
translitChars.put("", "y");
translitChars.put("", "j");
translitChars.put("", "k");
translitChars.put("ṿ", "v");
translitChars.put("ȩ", "e");
translitChars.put("â", "a");
translitChars.put("ş", "s");
translitChars.put("ŗ", "r");
translitChars.put("ʋ", "v");
translitChars.put("", "a");
translitChars.put("", "c");
translitChars.put("", "e");
translitChars.put("ɰ", "m");
translitChars.put("е", "e");
translitChars.put("", "w");
translitChars.put("ȏ", "o");
translitChars.put("č", "c");
translitChars.put("ǵ", "g");
translitChars.put("ĉ", "c");
translitChars.put("ю", "yu");
translitChars.put("", "o");
translitChars.put("", "k");
translitChars.put("", "q");
translitChars.put("г", "g");
translitChars.put("", "o");
translitChars.put("", "s");
translitChars.put("", "o");
translitChars.put("ȟ", "h");
translitChars.put("ő", "o");
translitChars.put("", "tz");
translitChars.put("", "e");
translitChars.put("о", "o");
}
StringBuilder dst = new StringBuilder(src.length());
int len = src.length();
for (int a = 0; a < len; a++) {
String ch = src.substring(a, a + 1);
String tch = translitChars.get(ch);
if (tch != null) {
dst.append(tch);
} else {
dst.append(ch);
}
}
return dst.toString();
}
abstract public static class PluralRules {
abstract int quantityForNumber(int n);
}
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 1.3.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -51,7 +66,6 @@ import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import com.b44t.messenger.audioinfo.AudioInfo;
import com.b44t.messenger.query.SharedMediaQuery;
import com.b44t.messenger.video.InputSurface;
import com.b44t.messenger.video.MP4Builder;
import com.b44t.messenger.video.Mp4Movie;
@@ -274,8 +288,8 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
private ArrayList<DownloadObject> videoDownloadQueue = new ArrayList<>();
private HashMap<String, DownloadObject> downloadQueueKeys = new HashMap<>();
private boolean saveToGallery = true;
private boolean autoplayGifs = true;
private final boolean saveToGallery = false;
private final boolean autoplayGifs = true;
private boolean raiseToSpeak = true;
private boolean directShare = true;
private boolean shuffleMusic;
@@ -504,11 +518,6 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
private ExternalObserver externalObserver = null;
private InternalObserver internalObserver = null;
private long lastSecretChatEnterTime = 0;
private long lastSecretChatLeaveTime = 0;
private long lastMediaCheckTime = 0;
private TLRPC.EncryptedChat lastSecretChat = null;
private ArrayList<Long> lastSecretChatVisibleMessages = null;
private int startObserverToken = 0;
private StopMediaObserverRunnable stopMediaObserverRunnable = null;
@@ -604,8 +613,8 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
mobileDataDownloadMask = preferences.getInt("mobileDataDownloadMask", AUTODOWNLOAD_MASK_PHOTO | AUTODOWNLOAD_MASK_AUDIO | AUTODOWNLOAD_MASK_MUSIC | AUTODOWNLOAD_MASK_GIF);
wifiDownloadMask = preferences.getInt("wifiDownloadMask", AUTODOWNLOAD_MASK_PHOTO | AUTODOWNLOAD_MASK_AUDIO | AUTODOWNLOAD_MASK_MUSIC | AUTODOWNLOAD_MASK_GIF);
roamingDownloadMask = preferences.getInt("roamingDownloadMask", 0);
saveToGallery = preferences.getBoolean("save_gallery", false);
autoplayGifs = preferences.getBoolean("autoplay_gif", true);
//saveToGallery = preferences.getBoolean("save_gallery", false);
//autoplayGifs = preferences.getBoolean("autoplay_gif", true);
raiseToSpeak = preferences.getBoolean("raise_to_speak", true);
directShare = preferences.getBoolean("direct_share", true);
shuffleMusic = preferences.getBoolean("shuffleMusic", false);
@@ -620,7 +629,6 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
NotificationCenter.getInstance().addObserver(MediaController.this, NotificationCenter.FileDidLoaded);
NotificationCenter.getInstance().addObserver(MediaController.this, NotificationCenter.FileLoadProgressChanged);
NotificationCenter.getInstance().addObserver(MediaController.this, NotificationCenter.FileUploadProgressChanged);
NotificationCenter.getInstance().addObserver(MediaController.this, NotificationCenter.removeAllMessagesFromDialog);
NotificationCenter.getInstance().addObserver(MediaController.this, NotificationCenter.musicDidLoaded);
}
});
@@ -1359,11 +1367,6 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
}
}
}
} else if (id == NotificationCenter.removeAllMessagesFromDialog) {
long did = (Long) args[0];
if (playingMessageObject != null && playingMessageObject.getDialogId() == did) {
cleanupPlayer(false, true);
}
} else if (id == NotificationCenter.musicDidLoaded) {
long did = (Long) args[0];
if (playingMessageObject != null && playingMessageObject.isMusic() && playingMessageObject.getDialogId() == did) {
@@ -1995,7 +1998,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
currentPlaylistNum = 0;
}
if (loadMusic) {
SharedMediaQuery.loadMusic(current.getDialogId(), playlist.get(0).getId());
//SharedMediaQuery.loadMusic(current.getDialogId(), playlist.get(0).getId());
}
}
return playAudio(current);
@@ -2512,7 +2515,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
try {
Vibrator v = (Vibrator) ApplicationLoader.applicationContext.getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(50);
//NotificationsController.getInstance().playRecordSound();
//NotificationsController.getInstance().playRecordSound(); -- was also disabled in Telegram; playing a sound while recording may result in a feedback
} catch (Exception e) {
FileLog.e("messenger", e);
}
@@ -2973,6 +2976,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
return null;
}
/*
public void toggleSaveToGallery() {
saveToGallery = !saveToGallery;
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
@@ -2989,6 +2993,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
editor.putBoolean("autoplay_gif", autoplayGifs);
editor.commit();
}
*/
public void toogleRaiseToSpeak() {
raiseToSpeak = !raiseToSpeak;
@@ -3006,7 +3011,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
editor.commit();
}
public void checkSaveToGalleryFiles() {
public void checkSaveToGalleryFiles() { // not sure, but it seems as if these paths are not needed
try {
File messengerPath = new File(Environment.getExternalStorageDirectory(), "Delta Chat");
File imagePath = new File(messengerPath, "Delta Chat Images");
@@ -3034,9 +3039,11 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
}
}
/*
public boolean canSaveToGallery() {
return saveToGallery;
}
*/
public boolean canAutoplayGifs() {
return autoplayGifs;
@@ -1,31 +1,37 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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.graphics.Paint;
import android.graphics.Typeface;
import android.text.Layout;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.style.URLSpan;
import android.text.util.Linkify;
import com.b44t.ui.ActionBar.Theme;
import com.b44t.ui.Components.TypefaceSpan;
import com.b44t.ui.Components.URLSpanNoUnderline;
import com.b44t.ui.Components.URLSpanNoUnderlineBold;
import com.b44t.ui.Components.URLSpanReplacement;
import com.b44t.ui.Components.URLSpanUserMention;
import java.io.File;
import java.util.AbstractMap;
@@ -43,14 +49,11 @@ public class MessageObject {
public TLRPC.Message messageOwner;
public CharSequence messageText;
public CharSequence linkDescription;
public CharSequence caption;
public MessageObject replyMessageObject;
public int type = 1000;
public int contentType;
public int type = 1000; // 13: sticker
public int contentType; // one of ChatActivity.ROWTYPE_MESSAGE_CELL, .ROWTYPE_ACTION_CELL or .ROWTYPE_UNREAD_CELL
public String dateKey;
public String monthKey;
public boolean deleted;
public float audioProgress;
public int audioProgressSec;
public ArrayList<TLRPC.PhotoSize> photoThumbs;
@@ -110,7 +113,7 @@ public class MessageObject {
}
}
if (message instanceof TLRPC.TL_messageService) {
/*if (message instanceof TLRPC.TL_messageService) {
if (message.action != null) {
if (message.action instanceof TLRPC.TL_messageActionChatCreate) {
if (isOut()) {
@@ -203,7 +206,7 @@ public class MessageObject {
messageText = LocaleController.getString("HistoryCleared", R.string.HistoryCleared);
}
}
} else if (!isMediaEmpty()) {
} else*/ if (!isMediaEmpty()) {
if (message.media instanceof TLRPC.TL_messageMediaPhoto) {
messageText = LocaleController.getString("AttachPhoto", R.string.AttachPhoto);
} else if (isVideo()) {
@@ -253,7 +256,6 @@ public class MessageObject {
int dateYear = rightNow.get(Calendar.YEAR);
int dateMonth = rightNow.get(Calendar.MONTH);
dateKey = String.format("%d_%02d_%02d", dateYear, dateMonth, dateDay);
monthKey = String.format("%d_%02d", dateYear, dateMonth);
if (messageOwner.message != null && messageOwner.id < 0 && messageOwner.message.length() > 6 && isVideo()) {
videoEditedInfo = new VideoEditedInfo();
@@ -317,29 +319,28 @@ public class MessageObject {
type = 9;
}
}
} else if (messageOwner instanceof TLRPC.TL_messageService) {
/*if (messageOwner.action instanceof TLRPC.TL_messageActionLoginUnknownLocation) {
} /*else if (messageOwner instanceof TLRPC.TL_messageService) {
if (messageOwner.action instanceof TLRPC.TL_messageActionLoginUnknownLocation) {
type = 0;
} else */
if (messageOwner.action instanceof TLRPC.TL_messageActionChatEditPhoto || messageOwner.action instanceof TLRPC.TL_messageActionUserUpdatedPhoto) {
contentType = 1;
} else if (messageOwner.action instanceof TLRPC.TL_messageActionChatEditPhoto || messageOwner.action instanceof TLRPC.TL_messageActionUserUpdatedPhoto) {
contentType = ChatActivity.ROWTYPE_ACTION_CELL;
type = 11;
/*} else if (messageOwner.action instanceof TLRPC.TL_messageEncryptedAction) {
} else if (messageOwner.action instanceof TLRPC.TL_messageEncryptedAction) {
if (messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages || messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL) {
contentType = 1;
contentType = ChatActivity.ROWTYPE_ACTION_CELL;
type = 10;
} else {
contentType = -1;
type = -1;
}*/
}
} else if (messageOwner.action instanceof TLRPC.TL_messageActionHistoryClear) {
contentType = -1;
type = -1;
} else {
contentType = 1;
contentType = ChatActivity.ROWTYPE_ACTION_CELL;
type = 10;
}
}
}*/
if (oldType != 1000 && oldType != type) {
generateThumbs(false);
}
@@ -373,7 +374,7 @@ public class MessageObject {
}
public void generateThumbs(boolean update) {
if (messageOwner instanceof TLRPC.TL_messageService) {
/*if (messageOwner instanceof TLRPC.TL_messageService) {
if (messageOwner.action instanceof TLRPC.TL_messageActionChatEditPhoto) {
if (!update) {
photoThumbs = new ArrayList<>(messageOwner.action.photo.sizes);
@@ -393,7 +394,7 @@ public class MessageObject {
}
}
}
} else if (messageOwner.media != null && !(messageOwner.media instanceof TLRPC.TL_messageMediaEmpty)) {
} else*/ if (messageOwner.media != null && !(messageOwner.media instanceof TLRPC.TL_messageMediaEmpty)) {
if (messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) {
if (!update || photoThumbs != null && photoThumbs.size() != messageOwner.media.photo.sizes.size()) {
photoThumbs = new ArrayList<>(messageOwner.media.photo.sizes);
@@ -424,7 +425,7 @@ public class MessageObject {
photoObject.h = messageOwner.media.document.thumb.h;
}
}
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaWebPage) {
} /* else if (messageOwner.media instanceof TLRPC.TL_messageMediaWebPage) {
if (messageOwner.media.webpage.photo != null) {
if (!update || photoThumbs == null) {
photoThumbs = new ArrayList<>(messageOwner.media.webpage.photo.sizes);
@@ -454,10 +455,11 @@ public class MessageObject {
}
}
}
}
} */
}
}
/*
public CharSequence replaceWithLink(CharSequence source, String param, ArrayList<Integer> uids, AbstractMap<Integer, TLRPC.User> usersDict) {
int start = TextUtils.indexOf(source, param);
if (start >= 0) {
@@ -506,6 +508,7 @@ public class MessageObject {
}
return source;
}
*/
/*
public String getExtension() {
@@ -537,9 +540,9 @@ public class MessageObject {
return FileLoader.getAttachFileName(sizeFull);
}
}
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaWebPage) {
} /*else if (messageOwner.media instanceof TLRPC.TL_messageMediaWebPage) {
return FileLoader.getAttachFileName(messageOwner.media.webpage.document);
}
} */
return "";
}
@@ -617,7 +620,7 @@ public class MessageObject {
}
public void generateLinkDescription() {
if (linkDescription != null) {
/*if (linkDescription != null) {
return;
}
if (messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && messageOwner.media.webpage instanceof TLRPC.TL_webPage && messageOwner.media.webpage.description != null) {
@@ -630,7 +633,7 @@ public class MessageObject {
}
}
linkDescription = Emoji.replaceEmoji(linkDescription, textPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false);
}
}*/
}
public void generateCaption() {
@@ -704,25 +707,10 @@ public class MessageObject {
generateLinkDescription();
textLayoutBlocks = new ArrayList<>();
boolean hasEntities;
if (messageOwner.send_state != MESSAGE_SEND_STATE_SENT) {
hasEntities = false;
for (int a = 0; a < messageOwner.entities.size(); a++) {
if (!(messageOwner.entities.get(a) instanceof TLRPC.TL_inputMessageEntityMentionName)) {
hasEntities = true;
break;
}
}
} else {
hasEntities = !messageOwner.entities.isEmpty();
}
final boolean useManualParse = true; // false only add links to phone numbers; was used in Telegram for incoming messages that were already parsed (?)
if (useManualParse) {
/*final boolean useManualParse = true; // false only add links to phone numbers; was used in Telegram for incoming messages that were already parsed (?)
if (useManualParse) {*/
addLinks(messageText);
} else {
/*} else {
if (messageText instanceof Spannable && messageText.length() < 200) {
try {
Linkify.addLinks((Spannable) messageText, Linkify.PHONE_NUMBERS);
@@ -730,14 +718,14 @@ public class MessageObject {
FileLog.e("messenger", e);
}
}
}
}*/
if (messageText instanceof Spannable) {
/*if (messageText instanceof Spannable) {
Spannable spannable = (Spannable) messageText;
int count = messageOwner.entities.size();
int count = messageOwner.entities_.size();
URLSpan[] spans = spannable.getSpans(0, messageText.length(), URLSpan.class);
for (int a = 0; a < count; a++) {
TLRPC.MessageEntity entity = messageOwner.entities.get(a);
TLRPC.MessageEntity entity = messageOwner.entities_.get(a);
if (entity.length <= 0 || entity.offset < 0 || entity.offset >= messageOwner.message.length()) {
continue;
} else if (entity.offset + entity.length > messageOwner.message.length()) {
@@ -783,7 +771,7 @@ public class MessageObject {
}
}
}
}
}*/
int maxWidth;
if (AndroidUtilities.isTablet()) {
@@ -799,9 +787,9 @@ public class MessageObject {
maxWidth = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) - AndroidUtilities.dp(80);
}
}
if (fromUser != null && fromUser.bot || (isMegagroup() || messageOwner.fwd_from != null && messageOwner.fwd_from.channel_id != 0) && !isOut()) {
/*if ( (messageOwner.fwd_from != null && messageOwner.fwd_from.channel_id != 0) && !isOut()) {
maxWidth -= AndroidUtilities.dp(20);
}
}*/
StaticLayout textLayout;
@@ -993,14 +981,6 @@ public class MessageObject {
return false;
}
public boolean isMegagroup() {
return false;
}
public static boolean isMegagroup(TLRPC.Message message) {
return false;
}
public static boolean isOut(TLRPC.Message message) {
return message.out;
}
@@ -1101,9 +1081,9 @@ public class MessageObject {
}
public TLRPC.Document getDocument() {
if (messageOwner.media instanceof TLRPC.TL_messageMediaWebPage) {
/*if (messageOwner.media instanceof TLRPC.TL_messageMediaWebPage) {
return messageOwner.media.webpage.document;
}
}*/
return messageOwner.media != null ? messageOwner.media.document : null;
}
@@ -1112,23 +1092,23 @@ public class MessageObject {
}
public static boolean isMusicMessage(TLRPC.Message message) {
if (message.media instanceof TLRPC.TL_messageMediaWebPage) {
/*if (message.media instanceof TLRPC.TL_messageMediaWebPage) {
return isMusicDocument(message.media.webpage.document);
}
}*/
return message.media != null && message.media.document != null && isMusicDocument(message.media.document);
}
public static boolean isVoiceMessage(TLRPC.Message message) {
if (message.media instanceof TLRPC.TL_messageMediaWebPage) {
/*if (message.media instanceof TLRPC.TL_messageMediaWebPage) {
return isVoiceDocument(message.media.webpage.document);
}
}*/
return message.media != null && message.media.document != null && isVoiceDocument(message.media.document);
}
public static boolean isVideoMessage(TLRPC.Message message) {
if (message.media instanceof TLRPC.TL_messageMediaWebPage) {
/*if (message.media instanceof TLRPC.TL_messageMediaWebPage) {
return isVideoDocument(message.media.webpage.document);
}
}*/
return message.media != null && message.media.document != null && isVideoDocument(message.media.document);
}
@@ -1157,9 +1137,16 @@ public class MessageObject {
return null;
}
public boolean isSelectable() {
if (type == 6 || type == 10 || type == 11) {
return false;
}
return true;
}
public int getApproximateHeight() {
if (type == 0) {
int height = textHeight + (messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && messageOwner.media.webpage instanceof TLRPC.TL_webPage ? AndroidUtilities.dp(100) : 0);
int height = textHeight /*+ (messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && messageOwner.media.webpage instanceof TLRPC.TL_webPage ? AndroidUtilities.dp(100) : 0)*/;
if (isReply()) {
height += AndroidUtilities.dp(42);
}
@@ -1283,7 +1270,7 @@ public class MessageObject {
}
public boolean isWebpageDocument() {
return messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && messageOwner.media.webpage.document != null && !isGifDocument(messageOwner.media.webpage.document);
return false;
}
public boolean isNewGif() {
@@ -1343,24 +1330,14 @@ public class MessageObject {
TLRPC.DocumentAttribute attribute = document.attributes.get(a);
if (attribute instanceof TLRPC.TL_documentAttributeAudio) {
if (attribute.voice) {
if (isOutOwner() || messageOwner.fwd_from != null && messageOwner.fwd_from.from_id == UserConfig.getClientUserId()) {
if (isOutOwner() ) {
return LocaleController.getString("FromSelf", R.string.FromSelf);
}
TLRPC.User user = null;
TLRPC.Chat chat = null;
if (messageOwner.fwd_from != null && messageOwner.fwd_from.channel_id != 0) {
chat = MessagesController.getInstance().getChat(messageOwner.fwd_from.channel_id);
} else if (messageOwner.fwd_from != null && messageOwner.fwd_from.from_id != 0) {
user = MessagesController.getInstance().getUser(messageOwner.fwd_from.from_id);
} else if (messageOwner.from_id < 0) {
chat = MessagesController.getInstance().getChat(-messageOwner.from_id);
else if (messageOwner.fwd_from != null ) {
return messageOwner.fwd_from.m_name;
} else {
user = MessagesController.getInstance().getUser(messageOwner.from_id);
}
if (user != null) {
TLRPC.User user = MessagesController.getInstance().getUser(messageOwner.from_id);
return UserObject.getUserName(user);
} else if (chat != null) {
return chat.title;
}
}
String performer = attribute.performer;
@@ -1394,17 +1371,12 @@ public class MessageObject {
}
public static boolean isMediaEmpty(TLRPC.Message message) {
return message == null || message.media == null || message.media instanceof TLRPC.TL_messageMediaEmpty || message.media instanceof TLRPC.TL_messageMediaWebPage;
return message == null || message.media == null || message.media instanceof TLRPC.TL_messageMediaEmpty;
}
public String getForwardedName() {
if (messageOwner.fwd_from != null) {
if (messageOwner.fwd_from.from_id != 0) {
TLRPC.User user = MessagesController.getInstance().getUser(messageOwner.fwd_from.from_id);
if (user != null) {
return UserObject.getUserName(user);
}
}
return messageOwner.fwd_from.m_name;
}
return null;
}
@@ -1,67 +1,52 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
import com.b44t.messenger.query.DraftQuery;
import com.b44t.messenger.query.MessagesQuery;
import com.b44t.messenger.query.SearchQuery;
import com.b44t.ui.ActionBar.BaseFragment;
import com.b44t.ui.ChatActivity;
import com.b44t.ui.ProfileActivity;
import com.b44t.ui.SettingsActivity;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Semaphore;
public class MessagesController implements NotificationCenter.NotificationCenterDelegate {
private ConcurrentHashMap<Integer, TLRPC.Chat> chats = new ConcurrentHashMap<>(100, 1.0f, 2);
private ConcurrentHashMap<Integer, TLRPC.EncryptedChat> encryptedChats = new ConcurrentHashMap<>(10, 1.0f, 2);
private ConcurrentHashMap<Integer, TLRPC.User> users = new ConcurrentHashMap<>(100, 1.0f, 2);
private ConcurrentHashMap<String, TLRPC.User> usersByUsernames = new ConcurrentHashMap<>(100, 1.0f, 2);
public ArrayList<TLRPC.TL_dialog> dialogs = new ArrayList<>();
public ArrayList<TLRPC.TL_dialog> dialogsServerOnly = new ArrayList<>();
public ArrayList<TLRPC.TL_dialog> dialogsGroupsOnly = new ArrayList<>();
public int nextDialogsCacheOffset;
public ConcurrentHashMap<Long, TLRPC.TL_dialog> dialogs_dict = new ConcurrentHashMap<>(100, 1.0f, 2);
public HashMap<Long, MessageObject> dialogMessage = new HashMap<>();
public HashMap<Long, MessageObject> dialogMessagesByRandomIds = new HashMap<>();
public HashMap<Integer, MessageObject> dialogMessagesByIds = new HashMap<>();
public HashMap<Long, CharSequence> printingStrings = new HashMap<>();
public ConcurrentHashMap<Integer, Integer> onlinePrivacy = new ConcurrentHashMap<>(20, 1.0f, 2);
private ArrayList<Long> createdDialogIds = new ArrayList<>();
private ArrayList<Integer> loadedFullUsers = new ArrayList<>();
private ArrayList<Integer> loadedFullChats = new ArrayList<>();
private HashMap<String, ArrayList<MessageObject>> reloadingWebpages = new HashMap<>();
public boolean loadingDialogs = false;
public boolean dialogsEndReached = false;
public int secretWebpagePreview = 2;
private String uploadingAvatar = null;
public boolean enableJoined = true;
public int fontSize = AndroidUtilities.dp(16);
public int ratingDecay;
@@ -72,32 +57,13 @@ public class MessagesController implements NotificationCenter.NotificationCenter
public static final int UPDATE_MASK_CHAT_NAME = 16;
public static final int UPDATE_MASK_CHAT_MEMBERS = 32;
public static final int UPDATE_MASK_USER_PRINT = 64;
public static final int UPDATE_MASK_USER_PHONE = 128;
public static final int UPDATE_MASK_READ_DIALOG_MESSAGE = 256;
public static final int UPDATE_MASK_SELECT_DIALOG = 512;
public static final int UPDATE_MASK_NEW_MESSAGE = 2048;
public static final int UPDATE_MASK_SEND_STATE = 4096;
public static final int UPDATE_MASK_CHANNEL = 8192;
public static final int UPDATE_MASK_CHAT_ADMINS = 16384;
private static volatile MessagesController Instance = null;
private final Comparator<TLRPC.TL_dialog> dialogComparator = new Comparator<TLRPC.TL_dialog>() {
@Override
public int compare(TLRPC.TL_dialog dialog1, TLRPC.TL_dialog dialog2) {
TLRPC.DraftMessage draftMessage = DraftQuery.getDraft(dialog1.id);
int date1 = draftMessage != null && draftMessage.date >= dialog1.last_message_date ? draftMessage.date : dialog1.last_message_date;
draftMessage = DraftQuery.getDraft(dialog2.id);
int date2 = draftMessage != null && draftMessage.date >= dialog2.last_message_date ? draftMessage.date : dialog2.last_message_date;
if (date1 < date2) {
return 1;
} else if (date1 > date2) {
return -1;
}
return 0;
}
};
public static MessagesController getInstance() {
MessagesController localInstance = Instance;
if (localInstance == null) {
@@ -113,21 +79,19 @@ public class MessagesController implements NotificationCenter.NotificationCenter
public MessagesController() {
ImageLoader.getInstance();
//MessagesStorage.getInstance();
NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileDidUpload);
NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileDidFailUpload);
NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileDidLoaded);
NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileDidFailedLoad);
NotificationCenter.getInstance().addObserver(this, NotificationCenter.messageReceivedByServer);
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE);
enableJoined = preferences.getBoolean("EnableContactJoined", true);
preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
secretWebpagePreview = preferences.getInt("secretWebpage2", 2);
ratingDecay = preferences.getInt("ratingDecay", 2419200);
fontSize = preferences.getInt("fons_size", AndroidUtilities.isTablet() ? 18 : 16);
fontSize = preferences.getInt("msg_font_size", SettingsActivity.defMsgFontSize());
}
/*
public static TLRPC.InputUser getInputUser(TLRPC.User user) {
if (user == null) {
return new TLRPC.TL_inputUserEmpty();
@@ -138,7 +102,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter
} else {
inputUser = new TLRPC.TL_inputUser();
inputUser.user_id = user.id;
inputUser.access_hash = user.access_hash;
}
return inputUser;
}
@@ -147,36 +110,23 @@ public class MessagesController implements NotificationCenter.NotificationCenter
TLRPC.User user = getInstance().getUser(user_id);
return getInputUser(user);
}
*/
public static TLRPC.InputPeer getInputPeer(int id) {
TLRPC.InputPeer inputPeer;
/*if (id < 0) {
TLRPC.Chat chat = getInstance().getChat(-id);
if (ChatObject.isChannel(chat)) {
inputPeer = new TLRPC.TL_inputPeerChannel();
inputPeer.channel_id = -id;
inputPeer.access_hash = chat.access_hash;
} else {
inputPeer = new TLRPC.TL_inputPeerChat();
inputPeer.chat_id = -id;
}
} else */ {
TLRPC.User user = getInstance().getUser(id);
{
inputPeer = new TLRPC.TL_inputPeerUser();
inputPeer.user_id = id;
if (user != null) {
inputPeer.access_hash = user.access_hash;
}
}
return inputPeer;
}
public static TLRPC.Peer getPeer(int id) {
TLRPC.Peer inputPeer;
if (id < 0) {
/*if (id < 0) {
inputPeer = new TLRPC.TL_peerChat();
inputPeer.chat_id = -id;
} else {
} else*/ {
inputPeer = new TLRPC.TL_peerUser();
inputPeer.user_id = id;
}
@@ -243,117 +193,9 @@ public class MessagesController implements NotificationCenter.NotificationCenter
if (uploadingAvatar != null && uploadingAvatar.equals(location)) {
uploadingAvatar = null;
}
} else if (id == NotificationCenter.messageReceivedByServer) {
Integer msgId = (Integer) args[0];
Integer newMsgId = (Integer) args[1];
Long did = (Long) args[3];
MessageObject obj = dialogMessage.get(did);
if (obj != null && obj.getId() == msgId) {
obj.messageOwner.id = newMsgId;
obj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SENT;
TLRPC.TL_dialog dialog = dialogs_dict.get(did);
if (dialog != null) {
if (dialog.top_message == msgId) {
dialog.top_message = newMsgId;
}
}
NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload);
}
obj = dialogMessagesByIds.remove(msgId);
if (obj != null) {
dialogMessagesByIds.put(newMsgId, obj);
}
}
}
/*
public void cleanup() {
ContactsController.getInstance().cleanup();
MediaController.getInstance().cleanup();
NotificationsController.getInstance().cleanup();
SendMessagesHelper.getInstance().cleanup();
//SecretChatHelper.getInstance().cleanup();
StickersQuery.cleanup();
SearchQuery.cleanup();
DraftQuery.cleanup();
reloadingWebpages.clear();
reloadingWebpagesPending.clear();
dialogs_dict.clear();
dialogs_read_inbox_max.clear();
dialogs_read_outbox_max.clear();
dialogs.clear();
channelViewsToSend.clear();
channelViewsToReload.clear();
dialogsServerOnly.clear();
dialogsGroupsOnly.clear();
dialogMessagesByIds.clear();
dialogMessagesByRandomIds.clear();
users.clear();
usersByUsernames.clear();
chats.clear();
dialogMessage.clear();
printingUsers.clear();
printingStrings.clear();
printingStringsTypes.clear();
onlinePrivacy.clear();
loadingPeerSettings.clear();
lastPrintingStringCount = 0;
nextDialogsCacheOffset = 0;
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
gettingUnknownChannels.clear();
createdDialogIds.clear();
gettingDifference = false;
}
});
blockedUsers.clear();
sendingTypings.clear();
loadingFullUsers.clear();
loadedFullUsers.clear();
reloadingMessages.clear();
loadingFullChats.clear();
loadingFullParticipants.clear();
loadedFullParticipants.clear();
loadedFullChats.clear();
currentDeletingTaskTime = 0;
currentDeletingTaskMids = null;
gettingNewDeleteTask = false;
loadingDialogs = false;
dialogsEndReached = false;
loadingBlockedUsers = false;
firstGettingTask = false;
updatingState = false;
offlineSent = false;
registeringForPush = false;
uploadingAvatar = null;
statusRequest = 0;
statusSettingState = 0;
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
//ConnectionsManager.getInstance().setIsUpdating(false);
updatesQueueChannels.clear();
updatesStartWaitTimeChannels.clear();
gettingDifferenceChannels.clear();
channelsPts.clear();
shortPollChannels.clear();
needShortPollChannels.clear();
}
});
if (currentDeleteTaskRunnable != null) {
Utilities.stageQueue.cancelRunnable(currentDeleteTaskRunnable);
currentDeleteTaskRunnable = null;
}
NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload);
}
*/
public TLRPC.User getUser(Integer id) {
// EDIT BY MR - additional information should be loaded as needed by the caller
TLRPC.User u = new TLRPC.User();
@@ -361,270 +203,11 @@ public class MessagesController implements NotificationCenter.NotificationCenter
return u;
}
public TLRPC.User getUser(String username) {
if (username == null || username.length() == 0) {
return null;
}
return usersByUsernames.get(username.toLowerCase());
}
public ConcurrentHashMap<Integer, TLRPC.User> getUsers() {
return users;
}
public TLRPC.Chat getChat(Integer id) {
return chats.get(id);
return null;
}
public TLRPC.EncryptedChat getEncryptedChat(Integer id) {
return encryptedChats.get(id);
}
public void setLastCreatedDialogId(final long dialog_id, final boolean set) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
if (set) {
createdDialogIds.add(dialog_id);
} else {
createdDialogIds.remove(dialog_id);
}
}
});
}
public boolean putUser(TLRPC.User user, boolean fromCache) {
if (user == null) {
return false;
}
fromCache = fromCache && user.id / 1000 != 333 && user.id != 777000;
TLRPC.User oldUser = users.get(user.id);
if (oldUser != null && oldUser.username != null && oldUser.username.length() > 0) {
usersByUsernames.remove(oldUser.username);
}
if (user.username != null && user.username.length() > 0) {
usersByUsernames.put(user.username.toLowerCase(), user);
}
if (user.min) {
if (oldUser != null) {
if (!fromCache) {
if (user.username != null) {
oldUser.username = user.username;
oldUser.flags |= 8;
} else {
oldUser.username = null;
oldUser.flags = oldUser.flags &~ 8;
}
if (user.photo != null) {
oldUser.photo = user.photo;
oldUser.flags |= 32;
} else {
oldUser.photo = null;
oldUser.flags = oldUser.flags &~ 32;
}
}
} else {
users.put(user.id, user);
}
} else {
if (!fromCache) {
users.put(user.id, user);
if (user.id == UserConfig.getClientUserId()) {
UserConfig.setCurrentUser(user);
UserConfig.saveConfig(true);
}
if (oldUser != null && user.status != null && oldUser.status != null && user.status.expires != oldUser.status.expires) {
return true;
}
} else if (oldUser == null) {
users.put(user.id, user);
} else if (oldUser.min) {
user.min = false;
if (oldUser.username != null) {
user.username = oldUser.username;
user.flags |= 8;
} else {
user.username = null;
user.flags = user.flags &~ 8;
}
if (oldUser.photo != null) {
user.photo = oldUser.photo;
user.flags |= 32;
} else {
user.photo = null;
user.flags = user.flags &~ 32;
}
users.put(user.id, user);
}
}
return false;
}
public void putUsers(ArrayList<TLRPC.User> users, boolean fromCache) {
if (users == null || users.isEmpty()) {
return;
}
boolean updateStatus = false;
int count = users.size();
for (int a = 0; a < count; a++) {
TLRPC.User user = users.get(a);
if (putUser(user, fromCache)) {
updateStatus = true;
}
}
if (updateStatus) {
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
NotificationCenter.getInstance().postNotificationName(NotificationCenter.updateInterfaces, UPDATE_MASK_STATUS);
}
});
}
}
/*
public void putChat(TLRPC.Chat chat, boolean fromCache) {
if (chat == null) {
return;
}
TLRPC.Chat oldChat = chats.get(chat.id);
if (chat.min) {
if (oldChat != null) {
if (!fromCache) {
oldChat.title = chat.title;
oldChat.photo = chat.photo;
//oldChat.broadcast = chat.broadcast;
oldChat.verified = chat.verified;
//oldChat.megagroup = chat.megagroup;
oldChat.democracy = chat.democracy;
if (chat.username != null) {
oldChat.username = chat.username;
oldChat.flags |= 64;
} else {
oldChat.username = null;
oldChat.flags = oldChat.flags &~ 64;
}
}
} else {
chats.put(chat.id, chat);
}
} else {
if (!fromCache) {
if (oldChat != null && chat.version != oldChat.version) {
loadedFullChats.remove((Integer) chat.id);
}
chats.put(chat.id, chat);
} else if (oldChat == null) {
chats.put(chat.id, chat);
} else if (oldChat.min) {
chat.min = false;
chat.title = oldChat.title;
chat.photo = oldChat.photo;
//chat.broadcast = oldChat.broadcast;
chat.verified = oldChat.verified;
//chat.megagroup = oldChat.megagroup;
chat.democracy = oldChat.democracy;
if (oldChat.username != null) {
chat.username = oldChat.username;
chat.flags |= 64;
} else {
chat.username = null;
chat.flags = chat.flags &~ 64;
}
chats.put(chat.id, chat);
}
}
}
*/
/*
public void putChats(ArrayList<TLRPC.Chat> chats, boolean fromCache) {
if (chats == null || chats.isEmpty()) {
return;
}
int count = chats.size();
for (int a = 0; a < count; a++) {
TLRPC.Chat chat = chats.get(a);
putChat(chat, fromCache);
}
}
*/
/*
protected void clearFullUsers() {
loadedFullUsers.clear();
loadedFullChats.clear();
}
*/
/*
public void loadDialogPhotos(final int did, final int offset, final int count, final long max_id, final boolean fromCache, final int classGuid) {
if (fromCache) {
MessagesStorage.getInstance().getDialogPhotos(did, offset, count, max_id, classGuid);
} else {
if (did > 0) {
TLRPC.User user = getUser(did);
if (user == null) {
return;
}
TLRPC.TL_photos_getUserPhotos req = new TLRPC.TL_photos_getUserPhotos();
req.limit = count;
req.offset = offset;
req.max_id = (int) max_id;
req.user_id = getInputUser(user);
int reqId = ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error == null) {
TLRPC.photos_Photos res = (TLRPC.photos_Photos) response;
processLoadedUserPhotos(res, did, offset, count, max_id, false, classGuid);
}
}
});
ConnectionsManager.getInstance().bindRequestToGuid(reqId, classGuid);
} else if (did < 0) {
TLRPC.TL_messages_search req = new TLRPC.TL_messages_search();
req.filter = new TLRPC.TL_inputMessagesFilterChatPhotos();
req.limit = count;
req.offset = offset;
req.max_id = (int) max_id;
req.q = "";
req.peer = MessagesController.getInputPeer(did);
int reqId = ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error == null) {
TLRPC.messages_Messages messages = (TLRPC.messages_Messages) response;
TLRPC.TL_photos_photos res = new TLRPC.TL_photos_photos();
res.count = messages.count;
res.users.addAll(messages.users);
for (int a = 0; a < messages.messages.size(); a++) {
TLRPC.Message message = messages.messages.get(a);
if (message.action == null || message.action.photo == null) {
continue;
}
res.photos.add(message.action.photo);
}
processLoadedUserPhotos(res, did, offset, count, max_id, false, classGuid);
}
}
});
ConnectionsManager.getInstance().bindRequestToGuid(reqId, classGuid);
}
}
}
*/
public void deleteMessages(ArrayList<Integer> messages, ArrayList<Long> randoms, TLRPC.EncryptedChat encryptedChat, final int channelId) {
}
public void deleteDialog(final long did, final int onlyHistory) {
deleteDialog(did, true, onlyHistory, 0);
}
private void deleteDialog(final long did, final boolean first, final int onlyHistory, final int max_id) {
public void deleteMessages(ArrayList<Integer> messages, ArrayList<Long> randoms, Object encryptedChat, final int channelId) {
}
@@ -652,142 +235,15 @@ public class MessagesController implements NotificationCenter.NotificationCenter
return searchImage;
}
public void loadChatInfo(final int chat_id, Semaphore semaphore, boolean force) {
//MessagesStorage.getInstance().loadChatInfo(chat_id, semaphore, force, false);
}
public void cancelTyping(int action, long dialog_id) {
}
public void sendTyping(final long dialog_id, final int action, int classGuid) {
}
public void loadMessages(final long dialog_id, final int count, final int max_id, boolean fromCache, int midDate, final int classGuid, final int load_type, final int last_message_id, final boolean isChannel, final int loadIndex) {
loadMessages(dialog_id, count, max_id, fromCache, midDate, classGuid, load_type, last_message_id, isChannel, loadIndex, 0, 0, 0, false);
}
public void loadMessages(final long dialog_id, final int count, final int max_id, boolean fromCache, int midDate, final int classGuid, final int load_type, final int last_message_id, final boolean isChannel, final int loadIndex, final int first_unread, final int unread_count, final int last_date, final boolean queryFromServer) {
}
public void reloadWebPages(final long dialog_id, HashMap<String, ArrayList<MessageObject>> webpagesToReload) {
for (HashMap.Entry<String, ArrayList<MessageObject>> entry : webpagesToReload.entrySet()) {
final String url = entry.getKey();
final ArrayList<MessageObject> messages = entry.getValue();
ArrayList<MessageObject> arrayList = reloadingWebpages.get(url);
if (arrayList == null) {
arrayList = new ArrayList<>();
reloadingWebpages.put(url, arrayList);
}
arrayList.addAll(messages);
/*TLRPC.TL_messages_getWebPagePreview req = new TLRPC.TL_messages_getWebPagePreview();
req.message = url;
ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
@Override
public void run(final TLObject response, final TLRPC.TL_error error) {
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
ArrayList<MessageObject> arrayList = reloadingWebpages.remove(url);
if (arrayList == null) {
return;
}
TLRPC.TL_messages_messages messagesRes = new TLRPC.TL_messages_messages();
if (!(response instanceof TLRPC.TL_messageMediaWebPage)) {
for (int a = 0; a < arrayList.size(); a++) {
arrayList.get(a).messageOwner.media.webpage = new TLRPC.TL_webPageEmpty();
messagesRes.messages.add(arrayList.get(a).messageOwner);
}
} else {
TLRPC.TL_messageMediaWebPage media = (TLRPC.TL_messageMediaWebPage) response;
if (media.webpage instanceof TLRPC.TL_webPage || media.webpage instanceof TLRPC.TL_webPageEmpty) {
for (int a = 0; a < arrayList.size(); a++) {
arrayList.get(a).messageOwner.media.webpage = media.webpage;
if (a == 0) {
ImageLoader.saveMessageThumbs(arrayList.get(a).messageOwner);
}
messagesRes.messages.add(arrayList.get(a).messageOwner);
}
} else {
reloadingWebpagesPending.put(media.webpage.id, arrayList);
}
}
if (!messagesRes.messages.isEmpty()) {
//MessagesStorage.getInstance().putMessages(messagesRes, dialog_id, -2, 0, false);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.replaceMessagesObjects, dialog_id, arrayList);
}
}
});
}
});*/
}
}
public void loadDialogs(final int offset, final int count, boolean fromCache) {
if (loadingDialogs) {
return;
}
loadingDialogs = true;
NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload);
FileLog.e("messenger", "load cacheOffset = " + offset + " count = " + count + " cache = " + fromCache);
if (fromCache) {
//MessagesStorage.getInstance().getDialogs(offset == 0 ? 0 : nextDialogsCacheOffset, count);
} else {
/*
TLRPC.TL_messages_getDialogs req = new TLRPC.TL_messages_getDialogs();
req.limit = count;
boolean found = false;
for (int a = dialogs.size() - 1; a >= 0; a--) {
TLRPC.TL_dialog dialog = dialogs.get(a);
int lower_id = (int) dialog.id;
int high_id = (int) (dialog.id >> 32);
if (lower_id != 0 && high_id != 1 && dialog.top_message > 0) {
MessageObject message = dialogMessage.get(dialog.id);
if (message != null && message.getId() > 0) {
req.offset_date = message.messageOwner.date;
req.offset_id = message.messageOwner.id;
int id;
if (message.messageOwner.to_id.channel_id != 0) {
id = -message.messageOwner.to_id.channel_id;
} else if (message.messageOwner.to_id.chat_id != 0) {
id = -message.messageOwner.to_id.chat_id;
} else {
id = message.messageOwner.to_id.user_id;
}
req.offset_peer = getInputPeer(id);
found = true;
break;
}
}
}
if (!found) {
req.offset_peer = new TLRPC.TL_inputPeerEmpty();
}
*/
/*ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error == null) {
//final TLRPC.messages_Dialogs dialogsRes = (TLRPC.messages_Dialogs) response;
//processLoadedDialogs(dialogsRes, null, 0, count, 0, false, false);
}
}
});*/
}
}
public void markMessageContentAsRead(final MessageObject messageObject) {
}
public void markMessageAsRead(final long dialog_id, final long random_id, int ttl) {
if (random_id == 0 || dialog_id == 0 || ttl <= 0 && ttl != Integer.MIN_VALUE) {
return;
}
}
public void markDialogAsRead(final long dialog_id, final int max_id, final int max_positive_id, final int max_date, final boolean was, final boolean popup) {
}
public void addUserToChat(final int chat_id, final TLRPC.User user, final TLRPC.ChatFull info, int count_fwd, String botHash, final BaseFragment fragment) {
}
@@ -842,7 +298,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter
searchImage.date = date;
searchImage.id = "" + searchImage.document.id;
arrayList.add(searchImage);
//MessagesStorage.getInstance().putWebRecent(arrayList);
}
protected void updateInterfaceWithMessages(final long uid, final ArrayList<MessageObject> messages, boolean isBroadcast) {
@@ -850,26 +305,19 @@ public class MessagesController implements NotificationCenter.NotificationCenter
return;
}
boolean isEncryptedChat = ((int) uid) == 0;
final boolean isEncryptedChat = false;
MessageObject lastMessage = null;
int channelId = 0;
boolean updateRating = false;
for (int a = 0; a < messages.size(); a++) {
MessageObject message = messages.get(a);
if (lastMessage == null || (!isEncryptedChat && message.getId() > lastMessage.getId() || (isEncryptedChat || message.getId() < 0 && lastMessage.getId() < 0) && message.getId() < lastMessage.getId()) || message.messageOwner.date > lastMessage.messageOwner.date) {
lastMessage = message;
if (message.messageOwner.to_id.channel_id != 0) {
channelId = message.messageOwner.to_id.channel_id;
}
}
if (message.isOut() && message.isNewGif() && !message.isSending() && !message.isForwarded()) {
addNewGifToRecent(message.messageOwner.media.document, message.messageOwner.date);
}
if (message.isOut() && message.isSent()) {
updateRating = true;
}
}
MessagesQuery.loadReplyMessagesForMessages(messages, uid);
//MessagesQuery.loadReplyMessagesForMessages(messages, uid);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.didReceivedNewMessages, uid, messages);
if (lastMessage == null) {
@@ -877,12 +325,10 @@ public class MessagesController implements NotificationCenter.NotificationCenter
}
TLRPC.TL_dialog dialog = dialogs_dict.get(uid);
boolean changed = false;
if (dialog == null) {
if (!isBroadcast) {
TLRPC.Chat chat = getChat(channelId);
if (channelId != 0 && chat == null || chat != null && chat.left) {
if (channelId != 0 && chat == null || chat != null && false/*chat.left*/) {
return;
}
dialog = new TLRPC.TL_dialog();
@@ -901,7 +347,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter
}
}
nextDialogsCacheOffset++;
changed = true;
}
} else {
if ((dialog.top_message > 0 && lastMessage.getId() > 0 && lastMessage.getId() > dialog.top_message) ||
@@ -914,7 +359,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter
dialog.top_message = lastMessage.getId();
if (!isBroadcast) {
dialog.last_message_date = lastMessage.messageOwner.date;
changed = true;
}
dialogMessage.put(uid, lastMessage);
if (lastMessage.messageOwner.to_id.channel_id == 0) {
@@ -925,173 +369,5 @@ public class MessagesController implements NotificationCenter.NotificationCenter
}
}
}
if (changed) {
sortDialogs(null);
}
if (updateRating) {
SearchQuery.increasePeerRaiting(uid);
}
}
public void sortDialogs(HashMap<Integer, TLRPC.Chat> chatsDict) {
dialogsServerOnly.clear();
dialogsGroupsOnly.clear();
Collections.sort(dialogs, dialogComparator);
for (int a = 0; a < dialogs.size(); a++) {
TLRPC.TL_dialog d = dialogs.get(a);
int high_id = (int) (d.id >> 32);
int lower_id = (int) d.id;
if (lower_id != 0 && high_id != 1) {
dialogsServerOnly.add(d);
/*if (DialogObject.isChannel(d)) {
TLRPC.Chat chat = getChat(-lower_id);
if (chat != null && (chat.megagroup && chat.editor || chat.creator)) {
dialogsGroupsOnly.add(d);
}
} else*/ if (lower_id < 0) {
/*if (chatsDict != null) {
TLRPC.Chat chat = chatsDict.get(-lower_id);
if (chat != null && chat.migrated_to != null) {
dialogs.remove(a);
a--;
continue;
}
}*/
dialogsGroupsOnly.add(d);
}
}
}
}
private static String getRestrictionReason(String reason) {
if (reason == null || reason.length() == 0) {
return null;
}
int index = reason.indexOf(": ");
if (index > 0) {
String type = reason.substring(0, index);
if (type.contains("-all") || type.contains("-android")) {
return reason.substring(index + 2);
}
}
return null;
}
private static void showCantOpenAlert(BaseFragment fragment, String reason) {
AlertDialog.Builder builder = new AlertDialog.Builder(fragment.getParentActivity());
builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null);
builder.setMessage(reason);
fragment.showDialog(builder.create());
}
public static boolean checkCanOpenChat(Bundle bundle, BaseFragment fragment) {
return true;
}
public static void openChatOrProfileWith(TLRPC.User user, TLRPC.Chat chat, BaseFragment fragment, int type) {
if (user == null && chat == null || fragment == null) {
return;
}
String reason = null;
boolean closeLast = false;
if (chat != null) {
reason = getRestrictionReason(chat.restriction_reason);
} else if (user != null) {
reason = getRestrictionReason(user.restriction_reason);
if (user.bot) {
type = 1;
closeLast = true;
}
}
if (reason != null) {
showCantOpenAlert(fragment, reason);
} else {
Bundle args = new Bundle();
if (chat != null) {
args.putInt("chat_id", chat.id);
} else {
args.putInt("user_id", user.id);
}
if (type == 0) {
fragment.presentFragment(new ProfileActivity(args));
} else {
fragment.presentFragment(new ChatActivity(args), closeLast);
}
}
}
public static void openByUserName(String username, final BaseFragment fragment, final int type) {
if (username == null || fragment == null) {
return;
}
TLRPC.User user = getInstance().getUser(username);
if (user != null) {
openChatOrProfileWith(user, null, fragment, type);
} else {
if (fragment.getParentActivity() == null) {
return;
}
final ProgressDialog progressDialog = new ProgressDialog(fragment.getParentActivity());
progressDialog.setMessage(LocaleController.getString("Loading", R.string.Loading));
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.setCancelable(false);
/*TLRPC.TL_contacts_resolveUsername req = new TLRPC.TL_contacts_resolveUsername();
req.username = username;*/
final int reqId = 0; /*ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
@Override
public void run(final TLObject response, final TLRPC.TL_error error) {
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
try {
progressDialog.dismiss();
} catch (Exception e) {
FileLog.e("messenger", e);
}
fragment.setVisibleDialog(null);
if (error == null) {
TLRPC.TL_contacts_resolvedPeer res = (TLRPC.TL_contacts_resolvedPeer) response;
getInstance().putUsers(res.users, false);
getInstance().putChats(res.chats, false);
//MessagesStorage.getInstance().putUsersAndChats(res.users, res.chats, false, true);
if (!res.chats.isEmpty()) {
openChatOrProfileWith(null, res.chats.get(0), fragment, 1);
} else if (!res.users.isEmpty()) {
openChatOrProfileWith(res.users.get(0), null, fragment, type);
}
} else {
if (fragment != null && fragment.getParentActivity() != null) {
try {
Toast.makeText(fragment.getParentActivity(), LocaleController.getString("NoUsernameFound", R.string.NoUsernameFound), Toast.LENGTH_SHORT).show();
} catch (Exception e) {
FileLog.e("messenger", e);
}
}
}
}
});
}
});
*/
progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, LocaleController.getString("Cancel", R.string.Cancel), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ConnectionsManager.getInstance().cancelRequest(reqId, true);
try {
dialog.dismiss();
} catch (Exception e) {
FileLog.e("messenger", e);
}
if (fragment != null) {
fragment.setVisibleDialog(null);
}
}
});
fragment.setVisibleDialog(progressDialog);
progressDialog.show();
}
}
}
@@ -1,8 +1,8 @@
/*******************************************************************************
*
* Messenger Android Frontend
* Copyright (C) 2016 Björn Petersen Software Design and Development
* Contact: r10s@b44t.com, http://b44t.com
* (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
@@ -20,13 +20,14 @@
*******************************************************************************
*
* File: MrChat.java
* Authors: Björn Petersen
* Purpose: Wrap around mrchat_t
*
******************************************************************************/
package com.b44t.messenger;
import android.text.TextUtils;
public class MrChat {
public final static int MR_CHAT_UNDEFINED = 0;
@@ -44,20 +45,13 @@ public class MrChat {
MrChatUnref(m_hChat);
}
public int getId() {
return MrChatGetId(m_hChat);
}
public int getType() {
return MrChatGetType(m_hChat);
}
public native int getId();
public native int getType();
public native String getName();
public native String getSubtitle();
public String getName() {
return MrChatGetName(m_hChat);
}
public String getSubtitle() {
return MrChatGetSubtitle(m_hChat);
}
public static int MR_CHAT_PARAM_UNPROMOTED = 'U';
public native int getParamInt(int key, int def);
public String getDraft() {
return MrChatGetDraft(m_hChat);
@@ -90,19 +84,14 @@ public class MrChat {
return MrChatSendMedia(m_hChat, type, file, mime, w, h, time_ms);
}
private long m_hChat;
private long m_hChat; // must not be renamed as referenced by JNI under the name "m_hChat"
private native static void MrChatUnref (long hChat);
private native static int MrChatGetId (long hChat);
private native static int MrChatGetType (long hChat);
private native static String MrChatGetName (long hChat);
private native static String MrChatGetSubtitle (long hChat);
private native static String MrChatGetDraft (long hChat); // returns null for "no draft"
private native static long MrChatGetDraftTimestamp (long hChat); // returns 0 for "no draft"
private native static int MrChatGetDraftReplyToMsgId (long hChat); // returns 0 for "no draft"
private native static int MrChatSetDraft (long hChat, String draft/*NULL=delete*/, long replyToMsgId);
private native static int MrChatGetUnseenCount (long hChat);
private native static int MrChatGetTotalMsgCount (long hChat);
private native static long MrChatGetSummary (long hChat); // returns hPoortext
private native static int MrChatSendText (long hChat, String text); // returns message id
private native static int MrChatSendMedia (long hChat, int type, String file, String mime, int w, int h, int time_ms);
@@ -128,7 +117,51 @@ public class MrChat {
return ret;
}
public long GetCPtr() {
public long getCPtr() {
return m_hChat;
}
public TLRPC.DraftMessage getDraftMessageObj() {
if( getId() == 0 ) {
return null;
}
TLRPC.DraftMessage ret = new TLRPC.DraftMessage();
ret.message = getDraft();
if( ret.message==null || ret.message.isEmpty() ) {
return null;
}
ret.date = (int)getDraftTimestamp();
ret.reply_to_msg_id = getDraftReplyToMsgId();
return ret;
}
public void saveDraft(CharSequence message, TLRPC.Message replyToMessage) {
if( message == null || TextUtils.isEmpty(message) ) {
setDraft(null, 0);
}
else {
setDraft(message.toString(), 0);
}
}
public void cleanDraft()
{
setDraft(null, 0);
}
public String getNameNAddr()
{
// returns name of group chats or name+e-mail-address for normal chats
String name = "ErrGrpNameNAddr";
if( getType()==MR_CHAT_GROUP ) {
name = getName();
}
else {
int contacts[] = MrMailbox.getChatContacts(getId());
if( contacts.length==1 ) {
name = MrMailbox.getContact(contacts[0]).getNameNAddr();
}
}
return name;
}
}
@@ -1,8 +1,8 @@
/*******************************************************************************
*
* Messenger Android Frontend
* Copyright (C) 2016 Björn Petersen Software Design and Development
* Contact: r10s@b44t.com, http://b44t.com
* (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
@@ -20,7 +20,6 @@
*******************************************************************************
*
* File: MrChatlist.java
* Authors: Björn Petersen
* Purpose: Wrap around mrchatlist_t
*
******************************************************************************/
@@ -48,7 +47,7 @@ public class MrChatlist {
}
public MrPoortext getSummaryByIndex(int index, MrChat chat) {
return new MrPoortext(MrChatlistGetSummaryByIndex(m_hChatlist, index, chat.GetCPtr()));
return new MrPoortext(MrChatlistGetSummaryByIndex(m_hChatlist, index, chat.getCPtr()));
}
private long m_hChatlist;
@@ -1,8 +1,8 @@
/*******************************************************************************
*
* Messenger Android Frontend
* Copyright (C) 2016 Björn Petersen Software Design and Development
* Contact: r10s@b44t.com, http://b44t.com
* (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
@@ -20,7 +20,6 @@
*******************************************************************************
*
* File: MrContact.java
* Authors: Björn Petersen
* Purpose: Wrap around mrcontact_t
*
******************************************************************************/
@@ -32,6 +31,7 @@ package com.b44t.messenger;
public class MrContact {
public final static int MR_CONTACT_ID_SELF = 1;
public final static int MR_CONTACT_ID_LAST_SPECIAL = 9;
public MrContact(long hContact) {
m_hContact = hContact;
@@ -1,8 +1,8 @@
/*******************************************************************************
*
* Messenger Android Frontend
* Copyright (C) 2016 Björn Petersen Software Design and Development
* Contact: r10s@b44t.com, http://b44t.com
* (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
@@ -20,7 +20,6 @@
*******************************************************************************
*
* File: MrMailbox.java
* Authors: Björn Petersen
* Purpose: Wrap around mrmailbox_t
*
******************************************************************************/
@@ -35,13 +34,9 @@ public class MrMailbox {
m_hMailbox = MrMailboxNew();
}
public static int open(String dbfile, String blobdir) {
return MrMailboxOpen(m_hMailbox, dbfile, blobdir);
}
public static void close() {
MrMailboxClose(m_hMailbox);
}
public native static int open(String dbfile);
public native static void close();
public native static String getBlobdir();
public static int configure() {
return MrMailboxConfigure(m_hMailbox);
@@ -63,6 +58,8 @@ public class MrMailbox {
return MrMailboxFetch(m_hMailbox);
}
public native static String getErrorDescr();
public static int setConfig(String key, String value) {
return MrMailboxSetConfig(m_hMailbox, key, value);
}
@@ -75,18 +72,11 @@ public class MrMailbox {
return MrMailboxGetConfigInt(m_hMailbox, key, def);
}
public static String getInfo() {
return MrMailboxGetInfo(m_hMailbox);
}
public native static String getInfo();
public native static String cmdline(String cmd);
public static String execute(String cmd) {
return MrMailboxExecute(m_hMailbox, cmd);
}
private static long m_hMailbox = 0;
private static long m_hMailbox = 0; // do not rename this, is used in C-part
private native static long MrMailboxNew (); // returns hMailbox which must be unref'd after usage (Names as mrmailbox_new don't work due to the additional underscore)
private native static int MrMailboxOpen (long hMailbox, String dbfile, String blobdir);
private native static void MrMailboxClose (long hMailbox);
private native static int MrMailboxConfigure (long hMailbox);
private native static int MrMailboxIsConfigured (long hMailbox);
private native static int MrMailboxConnect (long hMailbox);
@@ -95,18 +85,11 @@ public class MrMailbox {
private native static int MrMailboxSetConfig (long hMailbox, String key, String value); // value may be NULL
private native static String MrMailboxGetConfig (long hMailbox, String key, String def); // def may be NULL, returns empty string as NULL
private native static int MrMailboxGetConfigInt (long hMailbox, String key, int def); // def may be NULL, returns empty string as NULL
private native static String MrMailboxGetInfo (long hMailbox);
private native static String MrMailboxExecute (long hMailbox, String cmd);
// contacts
public static int[] getKnownContacts(String query) {
return MrMailboxGetKnownContacts(m_hMailbox, query);
}
public static int[] getBlockedContacts() {
return MrMailboxGetBlockedContacts(m_hMailbox);
}
public native static int[] getKnownContacts(String query);
public native static int getBlockedCount();
public native static int[] getBlockedContacts();
public static MrContact getContact(int contact_id) {
return new MrContact(MrMailboxGetContact(m_hMailbox, contact_id));
@@ -128,8 +111,6 @@ public class MrMailbox {
return MrMailboxAddAddressBook(m_hMailbox, adrbook);
}
private native static int[] MrMailboxGetKnownContacts (long hMailbox, String query);
private native static int[] MrMailboxGetBlockedContacts(long hMailbox);
private native static long MrMailboxGetContact (long hMailbox, int id);// returns hContact which must be unref'd after usage
private native static int MrMailboxCreateContact (long hMailbox, String name, String addr);
private native static int MrMailboxBlockContact (long hMailbox, int id, int block);
@@ -138,17 +119,16 @@ public class MrMailbox {
// chats
public static MrChatlist getChatlist() {
return new MrChatlist(MrMailboxGetChatlist(m_hMailbox));
public static MrChatlist getChatlist(String query) {
return new MrChatlist(MrMailboxGetChatlist(m_hMailbox, query));
}
public static MrChat getChat(int contact_id) {
return new MrChat(MrMailboxGetChat(m_hMailbox, contact_id));
public static MrChat getChat(int chat_id) {
return new MrChat(MrMailboxGetChat(m_hMailbox, chat_id));
}
public static int markseenChat(int id) {
return MrMailboxMarkseenChat(m_hMailbox, id);
}
public native static int markseenMsg (int msg_id);
public native static int markseenChat (int chat_id);
public static int getChatIdByContactId (int contact_id) {
return MrMailboxGetChatIdByContactId(m_hMailbox, contact_id);
@@ -158,31 +138,30 @@ public class MrMailbox {
return MrMailboxCreateChatByContactId(m_hMailbox, contact_id);
}
public static int[] getChatMsgs(int chat_id) {
return MrMailboxGetChatMsgs(m_hMailbox, chat_id);
}
public native static int createGroupChat (String name);
public native static int addContactToChat (int chat_id, int contact_id);
public native static int removeContactFromChat (int chat_id, int contact_id);
public native static int setChatName (int chat_id, String name);
public final static int MR_GCM_ADDDAYMARKER = 0x01;
public native static int[] getChatMsgs(int chat_id, int flags, int marker1before);
public native static int[] searchMsgs(int chat_id, String query);
public native static int[] getUnseenMsgs();
public static int[] getChatMedia(int chat_id, int msg_type, int or_msg_type) {
return MrMailboxGetChatMedia(m_hMailbox, chat_id, msg_type, or_msg_type);
}
public static int[] getChatContacts(int chat_id) {
return MrMailboxGetChatContacts(m_hMailbox, chat_id);
}
public native static int[] getChatContacts(int chat_id);
public native static int deleteChat(int chat_id);
public static int deleteChat(int chat_id) {
return MrMailboxDeleteChat(m_hMailbox, chat_id);
}
private native static long MrMailboxGetChatlist (long hMailbox); // returns hChatlist which must be unref'd after usage
private native static long MrMailboxGetChatlist (long hMailbox, String query); // returns hChatlist which must be unref'd after usage
private native static long MrMailboxGetChat (long hMailbox, int chat_id); // return hChat which must be unref'd after usage
private native static int MrMailboxMarkseenChat (long hMailbox, int id);
private native static int MrMailboxGetChatIdByContactId (long hMailbox, int contact_id);
private native static int MrMailboxCreateChatByContactId(long hMailbox, int contact_id); // returns chat_id
private native static int[] MrMailboxGetChatMsgs (long hMailbox, int chat_id);
private native static int[] MrMailboxGetChatMedia (long hMailbox, int chat_id, int msg_type, int or_msg_type);
private native static int[] MrMailboxGetChatContacts (long hMailbox, int chat_id);
private native static int MrMailboxDeleteChat (long hMailbox, int chat_id);
// msgs
@@ -194,16 +173,14 @@ public class MrMailbox {
return MrMailboxGetMsgInfo(m_hMailbox, id);
}
public static void deleteMsg(int id) {
MrMailboxDeleteMsg(m_hMailbox, id);
}
public native static void deleteMsgs(int msg_ids[]);
public native static void forwardMsgs(int msg_ids[], int chat_ids);
private native static long MrMailboxGetMsg (long hMailbox, int id); // return hMsg which must be unref'd after usage
private native static String MrMailboxGetMsgInfo (long hMailbox, int id);
private native static void MrMailboxDeleteMsg (long hMailbox, int id);
// static
public native static void MrStockAddStr (int id, String str);
private native static void MrStockAddStr (int id, String str);
public native static String MrGetVersionStr ();
public native static String CPtr2String (long hString); // get strings eg. from data1 from the callback
@@ -211,11 +188,17 @@ public class MrMailbox {
/* receive events
**********************************************************************************************/
public final static int MR_EVENT_MSGS_UPDATED = 2000;
public final static int MR_EVENT_MSGS_CHANGED = 2000;
public final static int MR_EVENT_INCOMING_MSG = 2005;
public final static int MR_EVENT_MSG_DELIVERED = 2010;
public final static int MR_EVENT_MSG_READ = 2015;
public final static int MR_EVENT_CHAT_MODIFIED = 2020;
public final static int MR_EVENT_CONTACTS_CHANGED = 2030;
public final static int MR_EVENT_MSG_DELIVERED = 3000;
public final static int MR_EVENT_MSG_READ = 3010;
public final static int MR_EVENT_CONNECTION_STATE_CHANGED = 3020;
public final static int MR_EVENT_CONNECTION_STATE_CHANGED = 2040;
public final static int MR_EVENT_REPORT = 2050;
public final static int MR_REPORT_ERR_SELF_NOT_IN_GROUP = 1;
public static long MrCallback(final int event, final long data1, final long data2) // this function is called from within the C-wrapper
{
switch(event) {
@@ -228,12 +211,16 @@ public class MrMailbox {
});
return 0;
case MR_EVENT_MSGS_UPDATED:
case MR_EVENT_MSGS_CHANGED:
case MR_EVENT_INCOMING_MSG:
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
reloadMainChatlist();
NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload, event, (int)data1, (int)data2);
if( event == MR_EVENT_INCOMING_MSG ) {
NotificationsController.getInstance().processNewMessages((int)data1, (int)data2);
}
}
});
return 0;
@@ -261,6 +248,29 @@ public class MrMailbox {
}
});
return 0;
case MR_EVENT_CHAT_MODIFIED:
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
reloadMainChatlist();
NotificationCenter.getInstance().postNotificationName(NotificationCenter.updateInterfaces,
MessagesController.UPDATE_MASK_NAME|MessagesController.UPDATE_MASK_CHAT_NAME|
MessagesController.UPDATE_MASK_CHAT_MEMBERS|MessagesController.UPDATE_MASK_AVATAR);
}
});
return 0;
case MR_EVENT_REPORT:
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
if(data1==MR_REPORT_ERR_SELF_NOT_IN_GROUP) {
NotificationCenter.getInstance().postNotificationName(NotificationCenter.errSelfNotInGroup);
}
}
});
return 0;
}
return 0;
}
@@ -273,6 +283,54 @@ public class MrMailbox {
public native static int getCurrentTime ();
public static void reloadMainChatlist()
{
m_currChatlist = getChatlist();
m_currChatlist = getChatlist(null);
}
public final static int MEDIA_PHOTOVIDEO = 0;
public static void getMediaCount(final long uid, final int type, final int classGuid, boolean fromCache) {
Utilities.globalQueue.postRunnable(new Runnable() {
@Override
public void run() {
int[] media = new int[0];
if( type == MEDIA_PHOTOVIDEO ) {
media = MrMailbox.getChatMedia((int)uid, MrMsg.MR_MSG_IMAGE, MrMsg.MR_MSG_VIDEO);
}
NotificationCenter.getInstance().postNotificationName(NotificationCenter.mediaCountDidLoaded,
uid, media.length, false /*not from cache*/, type, media);
}
});
}
public static void initStockStrings()
{
MrStockAddStr(1, LocaleController.getString("NoMessages", R.string.NoMessages));
MrStockAddStr(2, LocaleController.getString("FromSelf", R.string.FromSelf));
MrStockAddStr(3, LocaleController.getString("Draft", R.string.Draft));
MrStockAddStr(4, LocaleController.getString("MemberSg", R.string.MemberSg));
MrStockAddStr(5, LocaleController.getString("MemberPl", R.string.MemberPl));
MrStockAddStr(6, LocaleController.getString("ContactSg", R.string.ContactSg));
MrStockAddStr(7, LocaleController.getString("ContactPl", R.string.ContactPl));
MrStockAddStr(8, LocaleController.getString("Deaddrop", R.string.Deaddrop));
MrStockAddStr(9, LocaleController.getString("AttachPhoto", R.string.AttachPhoto));
MrStockAddStr(10, LocaleController.getString("AttachVideo", R.string.AttachVideo));
MrStockAddStr(11, LocaleController.getString("AttachAudio", R.string.AttachAudio));
MrStockAddStr(12, LocaleController.getString("AttachDocument", R.string.AttachDocument));
MrStockAddStr(13, LocaleController.getString("DefaultStatusText", R.string.DefaultStatusText));
MrStockAddStr(14, LocaleController.getString("MsgNewGroupDraft", R.string.MsgNewGroupDraft));
MrStockAddStr(15, LocaleController.getString("MsgGroupNameChanged", R.string.MsgGroupNameChanged));
MrStockAddStr(16, LocaleController.getString("MsgGroupImageChanged", R.string.MsgGroupImageChanged));
MrStockAddStr(17, LocaleController.getString("MsgMemberAddedToGroup", R.string.MsgMemberAddedToGroup));
MrStockAddStr(18, LocaleController.getString("MsgMemberRemovedFromToGroup", R.string.MsgMemberRemovedFromToGroup));
MrStockAddStr(19, LocaleController.getString("MsgGroupLeft", R.string.MsgGroupLeft));
}
public static String getInviteText() {
String url = "https://getdelta.org";
String email = getConfig("addr", "");
String text = LocaleController.formatString("InviteText", R.string.InviteText, url, email);
return text;
}
}
@@ -1,8 +1,8 @@
/*******************************************************************************
*
* Messenger Android Frontend
* Copyright (C) 2016 Björn Petersen Software Design and Development
* Contact: r10s@b44t.com, http://b44t.com
* (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
@@ -20,7 +20,6 @@
*******************************************************************************
*
* File: MrMsg.java
* Authors: Björn Petersen
* Purpose: Wrap around mrmsg_t
*
******************************************************************************/
@@ -28,8 +27,12 @@
package com.b44t.messenger;
import android.util.Log;
public class MrMsg {
private static final String TAG = "MrMsg";
public final static int MR_MSG_UNDEFINED = 0;
public final static int MR_MSG_TEXT = 10;
public final static int MR_MSG_IMAGE = 20;
@@ -46,6 +49,9 @@ public class MrMsg {
public final static int MR_OUT_DELIVERED = 26;
public final static int MR_OUT_READ = 28;
public final static int MR_MSG_ID_MARKER1 = 1;
public final static int MR_MSG_ID_DAYMARKER = 9;
public MrMsg(long hMsg) {
m_hMsg = hMsg;
}
@@ -91,7 +97,12 @@ public class MrMsg {
return MrMsgGetParamInt(m_hMsg, key, def);
}
private long m_hMsg;
public native int getBytes();
public MrPoortext getSummary(MrChat chat) { return new MrPoortext(getSummaryCPtr(chat.getCPtr())); }
private native long getSummaryCPtr(long hChat);
public native String getSummarytext(int approx_characters);
private long m_hMsg; // must not be renamed as referenced by JNI under the name "m_hMsg"
private native static void MrMsgUnref (long hMsg);
private native static int MrMsgGetId (long hMsg);
private native static String MrMsgGetText (long hMsg);
@@ -147,11 +158,21 @@ public class MrMsg {
TLRPC.TL_photoSize photoSize = new TLRPC.TL_photoSize();
photoSize.w = getParamInt('w', 800);
photoSize.h = getParamInt('h', 800);
photoSize.size = 0;
photoSize.size = 0; // not sure what to use here, maybe `getBytes();`?
photoSize.location = new TLRPC.TL_fileLocation();
photoSize.location.mr_path = path;
photoSize.location.local_id = -ret.id; // this forces the document to be searched in the cache dir
photoSize.type = "x";
if (photoSize.w <= 100 && photoSize.h <= 100) {
photoSize.type = "s";
} else if (photoSize.w <= 320 && photoSize.h <= 320) {
photoSize.type = "m";
} else if (photoSize.w <= 800 && photoSize.h <= 800) {
photoSize.type = "x";
} else if (photoSize.w <= 1280 && photoSize.h <= 1280) {
photoSize.type = "y";
} else {
photoSize.type = "w";
}
photo = new TLRPC.TL_photo();
photo.sizes.add(photoSize);
} catch (Exception e) {
@@ -200,6 +221,15 @@ public class MrMsg {
ret.message = String.format("<unsupported message type #%d for id #%d>", type, ret.id);
}
if( !getParam('a', "").equals("") ) {
ret.flags |= TLRPC.MESSAGE_FLAG_FWD;
ret.fwd_from = new TLRPC.TL_messageFwdHeader();
ret.fwd_from.m_name = getParam('A', "");
if( ret.fwd_from.m_name.isEmpty() ) {
ret.fwd_from.m_name = getParam('a', "");
}
}
return ret;
}
};
@@ -1,8 +1,8 @@
/*******************************************************************************
*
* Messenger Android Frontend
* Copyright (C) 2016 Björn Petersen Software Design and Development
* Contact: r10s@b44t.com, http://b44t.com
* (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
@@ -20,7 +20,6 @@
*******************************************************************************
*
* File: MrPoortext.java
* Authors: Björn Petersen
* Purpose: Wrap around mrpoortext_t
*
******************************************************************************/
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 1.3.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -113,7 +128,7 @@ public class NativeLoader {
return;
}
String crashDir = context.getCacheDir().getAbsolutePath();
//String crashDir = context.getCacheDir().getAbsolutePath();
try {
String folder;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -23,47 +38,28 @@ public class NotificationCenter {
public static final int closeChats = totalEvents++;
public static final int messagesDeleted = totalEvents++;
public static final int messagesSentOrRead = totalEvents++;
public static final int messagesDidLoaded = totalEvents++;
public static final int messageReceivedByAck = totalEvents++;
public static final int messageReceivedByServer = totalEvents++;
public static final int messageSendError = totalEvents++;
public static final int contactsDidLoaded = totalEvents++;
public static final int chatDidCreated = totalEvents++;
public static final int chatDidFailCreate = totalEvents++;
public static final int mediaDidLoaded = totalEvents++;
public static final int mediaCountDidLoaded = totalEvents++;
public static final int dialogPhotosLoaded = totalEvents++;
public static final int removeAllMessagesFromDialog = totalEvents++;
public static final int notificationsSettingsUpdated = totalEvents++;
public static final int pushMessagesUpdated = totalEvents++;
//public static final int pushMessagesUpdated = totalEvents++;
public static final int blockedUsersDidLoaded = totalEvents++;
public static final int openedChatChanged = totalEvents++;
public static final int stopEncodingService = totalEvents++;
public static final int didCreatedNewDeleteTask = totalEvents++;
public static final int mainUserInfoChanged = totalEvents++;
public static final int updateMessageMedia = totalEvents++;
public static final int recentImagesDidLoaded = totalEvents++;
public static final int replaceMessagesObjects = totalEvents++;
public static final int didSetPasscode = totalEvents++;
//public static final int screenStateChanged = totalEvents++; -- currently not used, but this may get handy
public static final int didLoadedReplyMessages = totalEvents++;
public static final int didReceivedWebpages = totalEvents++;
public static final int didReceivedWebpagesInUpdates = totalEvents++;
public static final int stickersDidLoaded = totalEvents++;
public static final int didReplacedPhotoInMemCache = totalEvents++;
public static final int messagesReadContent = totalEvents++;
public static final int userInfoDidLoaded = totalEvents++;
public static final int chatSearchResultsAvailable = totalEvents++;
public static final int musicDidLoaded = totalEvents++;
public static final int needShowAlert = totalEvents++;
public static final int didUpdatedMessagesViews = totalEvents++;
public static final int needReloadRecentDialogsSearch = totalEvents++;
public static final int locationPermissionGranted = totalEvents++;
public static final int peerSettingsDidLoaded = totalEvents++;
public static final int wasUnableToFindCurrentLocation = totalEvents++;
public static final int reloadHints = totalEvents++;
public static final int reloadInlineHints = totalEvents++;
public static final int newDraftReceived = totalEvents++;
public static final int httpFileDidLoaded = totalEvents++;
public static final int httpFileDidFailedLoad = totalEvents++;
@@ -73,10 +69,7 @@ public class NotificationCenter {
public static final int wallpapersDidLoaded = totalEvents++;
public static final int closeOtherAppActivities = totalEvents++;
public static final int didUpdatedConnectionState = totalEvents++;
public static final int didReceiveSmsCode = totalEvents++;
public static final int didReceiveCall = totalEvents++;
public static final int emojiDidLoaded = totalEvents++;
public static final int appDidLogout = totalEvents++;
public static final int FileDidUpload = totalEvents++;
public static final int FileDidFailUpload = totalEvents++;
@@ -101,6 +94,8 @@ public class NotificationCenter {
public static final int audioDidStarted = totalEvents++;
public static final int audioRouteChanged = totalEvents++;
public static final int errSelfNotInGroup = totalEvents++;
private SparseArray<ArrayList<Object>> observers = new SparseArray<>();
private SparseArray<ArrayList<Object>> removeAfterBroadcast = new SparseArray<>();
private SparseArray<ArrayList<Object>> addAfterBroadcast = new SparseArray<>();
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
File diff suppressed because it is too large Load Diff
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 1.3.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 1.3.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -19,7 +34,6 @@ import android.webkit.MimeTypeMap;
import android.widget.Toast;
import com.b44t.messenger.audioinfo.AudioInfo;
import com.b44t.messenger.query.DraftQuery;
import java.io.File;
import java.io.RandomAccessFile;
@@ -544,63 +558,23 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
if (document == null) {
return;
}
if ((int) peer == 0) {
int high_id = (int) (peer >> 32);
TLRPC.EncryptedChat encryptedChat = MessagesController.getInstance().getEncryptedChat(high_id);
if (encryptedChat == null) {
return;
}
if (document.thumb instanceof TLRPC.TL_photoSize) {
File file = FileLoader.getPathToAttach(document.thumb, true);
if (file.exists()) {
try {
int len = (int) file.length();
byte[] arr = new byte[(int) file.length()];
RandomAccessFile reader = new RandomAccessFile(file, "r");
reader.readFully(arr);
TLRPC.TL_document newDocument = new TLRPC.TL_document();
newDocument.thumb = new TLRPC.TL_photoCachedSize();
newDocument.thumb.location = document.thumb.location;
newDocument.thumb.size = document.thumb.size;
newDocument.thumb.w = document.thumb.w;
newDocument.thumb.h = document.thumb.h;
newDocument.thumb.type = document.thumb.type;
newDocument.thumb.bytes = arr;
newDocument.id = document.id;
newDocument.access_hash = document.access_hash;
newDocument.date = document.date;
newDocument.mime_type = document.mime_type;
newDocument.size = document.size;
newDocument.dc_id = document.dc_id;
newDocument.attributes = document.attributes;
if (newDocument.mime_type == null) {
newDocument.mime_type = "";
}
document = newDocument;
} catch (Exception e) {
FileLog.e("messenger", e);
}
}
}
}
SendMessagesHelper.getInstance().sendMessageDocument((TLRPC.TL_document) document, null, null, peer, replyingMessageObject, null);
}
public void sendMessageContact(TLRPC.User user, long peer, MessageObject reply_to_msg, HashMap<String, String> params) {
sendMessage__(null, null, null, null, user, null, peer, null, reply_to_msg, null, null, params);
sendMessage__(null, null, null, null, user, null, peer, null, reply_to_msg, params);
}
public void sendMessageDocument(TLRPC.TL_document document, VideoEditedInfo videoEditedInfo, String path, long peer, MessageObject reply_to_msg, HashMap<String, String> params) {
sendMessage__(null, null, null, videoEditedInfo, null, document, peer, path, reply_to_msg, null, null, params);
sendMessage__(null, null, null, videoEditedInfo, null, document, peer, path, reply_to_msg, params);
}
public void sendMessageText(String message, long peer, MessageObject reply_to_msg, TLRPC.WebPage webPage, boolean searchLinks, ArrayList<TLRPC.MessageEntity> entities, HashMap<String, String> params) {
sendMessage__(message, null, null, null, null, null, peer, null, reply_to_msg, webPage, entities, params);
public void sendMessageText(String message, long peer, MessageObject reply_to_msg, HashMap<String, String> params) {
sendMessage__(message, null, null, null, null, null, peer, null, reply_to_msg, params);
}
public void sendMessagePhoto(TLRPC.TL_photo photo, String path, long peer, MessageObject reply_to_msg, HashMap<String, String> params) {
sendMessage__(null, null, photo, null, null, null, peer, path, reply_to_msg, null, null, params);
sendMessage__(null, null, photo, null, null, null, peer, path, reply_to_msg, params);
}
private void sendMessage__(String message,
@@ -612,8 +586,6 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
long peer,
String path,
MessageObject reply_to_msg,
TLRPC.WebPage webPage,
ArrayList<TLRPC.MessageEntity> entities,
HashMap<String, String> params) {
if (peer == 0) { // peer == dialog id
return;
@@ -653,15 +625,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
{
if (message != null) {
newMsg = new TLRPC.TL_message();
if (entities != null && !entities.isEmpty()) {
newMsg.entities = entities;
}
if (webPage == null) {
newMsg.media = new TLRPC.TL_messageMediaEmpty();
} else {
newMsg.media = new TLRPC.TL_messageMediaWebPage();
newMsg.media.webpage = webPage;
}
newMsg.media = new TLRPC.TL_messageMediaEmpty();
if (params != null && params.containsKey("query_id")) {
type = 9;
} else {
@@ -799,7 +763,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
if (type == 0 /*|| type == 9 && message != null && encryptedChat != null*/ )
{
newMsg.id = mrChat.sendText(newMsg.message);
DraftQuery.cleanDraft(peer, false);
mrChat.cleanDraft();
MrMailbox.reloadMainChatlist();
}
@@ -1072,6 +1036,9 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
*/
}
if( newMsg.id!=0 ) {
NotificationsController.getInstance().playOutChatSound();
}
// finally update the interface, this results u.a. in an didReceivedNewMessages event which requires newMsg.id to be set
MessagesController.getInstance().updateInterfaceWithMessages(peer, objArr);
@@ -1646,7 +1613,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
//int count = (int) Math.ceil(textFinal.length() / 4096.0f);
//for (int a = 0; a < count; a++) {
// String mess = textFinal.substring(a * 4096, Math.min((a + 1) * 4096, textFinal.length()));
SendMessagesHelper.getInstance().sendMessageText(textFinal, dialog_id, null, null, true, null, null);
SendMessagesHelper.getInstance().sendMessageText(textFinal, dialog_id, null, null);
//}
}
}
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -17,14 +32,11 @@ public class TLRPC {
public static final int MESSAGE_FLAG_REPLY = 0x00000008;
public static final int MESSAGE_FLAG_HAS_FROM_ID = 0x00000100;
public static final int MESSAGE_FLAG_HAS_MEDIA = 0x00000200;
public static final int MESSAGE_FLAG_EDITED = 0x00008000;
public static class DraftMessage extends TLObject {
public int flags;
public boolean no_webpage;
public int reply_to_msg_id;
public String message;
public ArrayList<MessageEntity> entities = new ArrayList<>();
public int date;
}
@@ -80,15 +92,12 @@ public class TLRPC {
public static class Peer extends TLObject {
public final int channel_id = 0;
public int user_id;
public int chat_id;
public final int chat_id = 0;
}
public static class TL_peerUser extends Peer {
}
public static class TL_peerChat extends Peer {
}
public static class GeoPoint extends TLObject {
public double _long;
public double lat;
@@ -97,15 +106,6 @@ public class TLRPC {
public static class TL_geoPoint extends GeoPoint {
}
public static class SendMessageAction extends TLObject {
public int progress;
}
public static class PrivacyRule extends TLObject {
public ArrayList<Integer> users = new ArrayList<>();
}
public static class TL_messageMediaEmpty extends MessageMedia {
}
@@ -124,27 +124,6 @@ public class TLRPC {
public static class TL_messageMediaGeo extends MessageMedia {
}
public static class TL_messageMediaWebPage extends MessageMedia {
}
public static class BotInlineResult extends TLObject {
public int flags;
public String id;
public String type;
public String title;
public String description;
public String url;
public String thumb_url;
public String content_url;
public String content_type;
public int w;
public int h;
public int duration;
public Photo photo;
public Document document;
}
public static class PeerNotifySettings extends TLObject {
public int flags;
public boolean silent;
@@ -157,7 +136,6 @@ public class TLRPC {
public static class TL_messages_stickerSet extends TLObject {
public StickerSet set;
public ArrayList<TL_stickerPack> packs = new ArrayList<>();
public ArrayList<Document> documents = new ArrayList<>();
}
@@ -185,54 +163,22 @@ public class TLRPC {
public int flags;
public int id;
public String about;
public int pinned_msg_id;
public ChatParticipants participants;
}
public static class TL_topPeerCategoryPeers extends TLObject {
public TopPeerCategory category;
public int count;
}
public static class InputUser extends TLObject {
public int user_id;
public long access_hash;
}
public static class TL_inputUserEmpty extends InputUser {
}
public static class TL_inputUserSelf extends InputUser {
}
public static class TL_inputUser extends InputUser {
}
public static class WebPage extends TLObject {
public int flags;
public long id;
public String url;
public String display_url;
public String type;
public String site_name;
public String title;
public String description;
public Photo photo;
public String embed_url;
public int embed_width;
public int embed_height;
public int duration;
public String author;
public int date;
public Document document;
}
public static class TL_webPageEmpty extends WebPage {
}
public static class TL_webPage extends WebPage {
}
public static class InputFileLocation extends TLObject {
public long id;
public long access_hash;
@@ -252,62 +198,17 @@ public class TLRPC {
public String first_name;
public String last_name;
public String username;
public long access_hash;
public String phone;
public UserProfilePhoto photo;
public UserStatus status;
public int flags;
public boolean self;
public boolean contact;
public boolean mutual_contact;
public boolean deleted;
public final boolean bot = false;
public boolean verified;
public boolean min;
public String restriction_reason;
}
public static class TL_userContact_old2 extends User {
}
public static class MessageAction extends TLObject {
public String title;
public String address;
public ArrayList<Integer> users = new ArrayList<>();
public final int channel_id = 0;
public Photo photo;
public int chat_id;
public int user_id;
public UserProfilePhoto newUserPhoto;
}
public static class TL_messageActionChatCreate extends MessageAction {
}
public static class TL_messageActionHistoryClear extends MessageAction {
}
public static class TL_messageActionChatEditPhoto extends MessageAction {
}
public static class TL_messageActionChatAddUser extends MessageAction {
}
public static class TL_messageActionChatDeleteUser extends MessageAction {
}
public static class TL_messageActionUserUpdatedPhoto extends MessageAction {
}
public static class TL_messageActionChatDeletePhoto extends MessageAction {
}
public static class TL_messageActionChatEditTitle extends MessageAction {
}
public static class TL_messageActionEmpty extends MessageAction {
}
public static class Video extends TLObject {
public long id;
public int user_id;
@@ -324,9 +225,6 @@ public class TLRPC {
public byte[] iv;
}
public static class TopPeerCategory extends TLObject {
}
public static class InputDocument extends TLObject {
public long id;
public long access_hash;
@@ -404,65 +302,12 @@ public class TLRPC {
public static class InputStickerSet extends TLObject {
public long id;
public long access_hash;
public String short_name;
}
public static class TL_inputStickerSetEmpty extends InputStickerSet {
}
public static class TL_inputStickerSetID extends InputStickerSet {
}
public static class TL_inputStickerSetShortName extends InputStickerSet {
}
public static class UserStatus extends TLObject {
public int expires;
}
public static class TL_userStatusLastWeek extends UserStatus {
}
public static class TL_userStatusLastMonth extends UserStatus {
}
public static class TL_userStatusRecently extends UserStatus {
}
public static class Update extends TLObject {
public int chat_id;
public int user_id;
public int date;
public int version;
public DraftMessage draft;
public int pts;
public byte[] data;
public int flags;
public String query;
public String offset;
public int channel_id;
public SendMessageAction action;
public boolean blocked;
public String location;
public boolean enabled;
public ArrayList<PrivacyRule> rules = new ArrayList<>();
public UserStatus status;
public int views;
public String type;
public MessageMedia media;
public String first_name;
public String last_name;
public String username;
public ArrayList<Integer> messages = new ArrayList<>();
public String phone;
public WebPage webpage;
public EncryptedChat chat;
public ArrayList<Long> order = new ArrayList<>();
public UserProfilePhoto photo;
public boolean previous;
}
public static class InputEncryptedFile extends TLObject {
public long id;
public int parts;
@@ -473,48 +318,6 @@ public class TLRPC {
public FileLocation photo_big;
}
public static class MessageEntity extends TLObject {
public int offset;
public int length;
public String url;
public String language;
}
public static class TL_messageEntityTextUrl extends MessageEntity {
}
public static class TL_messageEntityEmail extends MessageEntity {
}
public static class TL_messageEntityPre extends MessageEntity {
}
public static class TL_messageEntityUrl extends MessageEntity {
}
public static class TL_messageEntityItalic extends MessageEntity {
}
public static class TL_messageEntityMention extends MessageEntity {
}
public static class TL_messageEntityMentionName extends MessageEntity {
public int user_id;
}
public static class TL_inputMessageEntityMentionName extends MessageEntity {
public InputUser user_id;
}
public static class TL_messageEntityBold extends MessageEntity {
}
public static class TL_messageEntityHashtag extends MessageEntity {
}
public static class TL_messageEntityCode extends MessageEntity {
}
public static class Photo extends TLObject {
public long id;
public long access_hash;
@@ -530,49 +333,23 @@ public class TLRPC {
public static class TL_photoEmpty extends Photo {
}
public static class TL_contact extends TLObject {
public int user_id;
public boolean mutual;
}
public static class ChatParticipants extends TLObject {
public int flags;
public int chat_id;
public ArrayList<ChatParticipant> participants = new ArrayList<>();
public int version;
}
public static class ChatParticipant extends TLObject {
public int user_id;
public int date;
}
public static class Chat extends TLObject {
public int flags;
public boolean creator;
public boolean kicked;
public boolean deactivated;
public int id;
public String title;
public final ChatPhoto photo = null;
public int date;
public int version;
public boolean editor;
public final boolean broadcast = false;
public boolean verified;
public final boolean megagroup = false;
public boolean left;
public String username;
public boolean restricted;
public boolean signatures;
public String restriction_reason;
public boolean min;
public String address;
}
public static class StickerSet extends TLObject {
public long id;
public long access_hash;
public String title;
public int flags;
public boolean installed;
@@ -582,33 +359,8 @@ public class TLRPC {
public int hash;
}
public static class MessagesFilter extends TLObject {
}
public static class TL_inputMessagesFilterDocument extends MessagesFilter {
}
public static class TL_inputMessagesFilterMusic extends MessagesFilter {
}
public static class TL_inputMessagesFilterUrl extends MessagesFilter {
}
public static class TL_inputMessagesFilterVoice extends MessagesFilter {
}
public static class TL_inputMessagesFilterEmpty extends MessagesFilter {
}
public static class TL_inputMessagesFilterPhotoVideo extends MessagesFilter {
}
public static class TL_messageFwdHeader extends TLObject {
public int flags;
public int from_id;
public int date;
public int channel_id;
public int channel_post;
public String m_name;
}
public static class FileLocation extends TLObject {
@@ -627,7 +379,7 @@ public class TLRPC {
}
public static class PhotoSize extends TLObject {
public String type;
public String type; // s, m, x, y, w for small, medium, ... widest
public FileLocation location;
public int w;
public int h;
@@ -651,26 +403,6 @@ public class TLRPC {
public String name;
}
public static class Updates extends TLObject {
public ArrayList<Update> updates = new ArrayList<>();
public ArrayList<User> users = new ArrayList<>();
public ArrayList<Chat> chats = new ArrayList<>();
public int date;
public int seq;
public int flags;
public boolean out;
public boolean mentioned;
public boolean silent;
public int id;
public int user_id;
public String message;
public int pts;
public MessageMedia media;
public Update update;
public int from_id;
public int chat_id;
}
public static class WallPaper extends TLObject {
public int id;
public String title;
@@ -685,10 +417,6 @@ public class TLRPC {
public static class TL_wallPaperSolid extends WallPaper {
}
public static class TL_stickerPack extends TLObject {
public ArrayList<Long> documents = new ArrayList<>();
}
public static class InputPhoto extends TLObject {
public long id;
public long access_hash;
@@ -699,7 +427,6 @@ public class TLRPC {
public static class InputPeer extends TLObject {
public int user_id;
public long access_hash;
public int chat_id;
public int channel_id;
}
@@ -707,31 +434,6 @@ public class TLRPC {
public static class TL_inputPeerUser extends InputPeer {
}
public static class TL_inputPeerEmpty extends InputPeer {
}
public static class TL_topPeer extends TLObject {
public Peer peer;
}
public static class TL_messages_search extends TLObject {
public int flags;
public InputPeer peer;
public String q;
public MessagesFilter filter;
public int offset;
public int max_id;
public int limit;
}
public static class TL_messages_searchGlobal extends TLObject {
public String q;
public int offset_date;
public InputPeer offset_peer;
public int offset_id;
public int limit;
}
public static class MessageMedia extends TLObject {
public byte[] bytes;
public Photo photo;
@@ -749,47 +451,28 @@ public class TLRPC {
public WebPage webpage;
}
public static class EncryptedChat extends TLObject {
public int id;
public int date;
public byte[] nonce;
public byte[] auth_key; //custom
public int user_id; //custom
public int ttl; //custom
public int layer; //custom
public byte[] key_hash; //custom
}
public static class Message extends TLObject {
public int id;
public int from_id;
public Peer to_id;
public int date;
public MessageAction action;
public int reply_to_msg_id;
public long reply_to_random_id;
public String message;
public MessageMedia media;
public int flags;
public boolean mentioned;
public boolean media_unread;
public boolean out;
public boolean unread;
public ArrayList<MessageEntity> entities = new ArrayList<>();
public String via_bot_name;
public int views;
public int edit_date;
public boolean silent;
public boolean post;
public TL_messageFwdHeader fwd_from;
public int via_bot_id;
public int send_state = 0; //custom
public String attachPath = ""; //custom
public HashMap<String, String> params; //custom
public long random_id; //custom
public long dialog_id; //custom
public int ttl; //custom
public int destroyTime; //custom
public int layer; //custom
public TLRPC.Message replyMessage; //custom
public boolean created_by_mr;
@@ -801,9 +484,6 @@ public class TLRPC {
public static class TL_message extends Message {
}
public static class TL_messageService extends Message {
}
public static class TL_dialog extends TLObject {
final public int flags = 0;
public Peer peer;
@@ -816,8 +496,6 @@ public class TLRPC {
public long id; //custom
}
public static class TL_chatEmpty extends Chat {
}
public static class Vector extends TLObject {
public ArrayList<Object> objects = new ArrayList<>();
}
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -1,39 +1,35 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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 UserObject {
public static boolean isDeleted(TLRPC.User user) {
return user == null || user.deleted;
}
public static boolean isUserSelf(TLRPC.User user) {
return user.self;
}
public static String getUserName(TLRPC.User user) {
if (user == null || isDeleted(user)) {
return "ErrName";
}
String name = ContactsController.formatName(user.first_name, user.last_name);
return name.length() != 0 || user.phone == null || user.phone.length() == 0 ? name : ""/*PhoneFormat.getInstance().format("+" + user.phone)*/;
}
public static String getFirstName(TLRPC.User user) {
if (user == null || isDeleted(user)) {
return "DELETED";
}
String name = user.first_name;
if (name == null || name.length() == 0) {
name = user.last_name;
}
return name != null && name.length() > 0 ? name : "ErrFirstName";
return "ErrName"; // use MrContact.getName() instead
}
}
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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;
@@ -32,7 +47,8 @@ public class WearReplyReceiver extends BroadcastReceiver {
if (dialog_id == 0 || max_id == 0) {
return;
}
SendMessagesHelper.getInstance().sendMessageText(text.toString(), dialog_id, null, null, true, null, null);
MessagesController.getInstance().markDialogAsRead(dialog_id, max_id, max_id, 0, true, false);
SendMessagesHelper.getInstance().sendMessageText(text.toString(), dialog_id, null, null);
MrMailbox.markseenChat((int)dialog_id);
NotificationsController.getInstance().removeSeenMessages();
}
}
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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.browser;
@@ -1,208 +0,0 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
package com.b44t.messenger.query;
import android.text.TextUtils;
import com.b44t.messenger.MrChat;
import com.b44t.messenger.MrMailbox;
import com.b44t.messenger.TLRPC;
import java.util.ArrayList;
public class DraftQuery {
/* EDIT BY MR
private static HashMap<Long, TLRPC.DraftMessage> drafts = new HashMap<>();
private static HashMap<Long, TLRPC.Message> draftMessages = new HashMap<>();
private static boolean inTransaction;
private static SharedPreferences preferences;
private static boolean loadingDrafts;
static {
preferences = ApplicationLoader.applicationContext.getSharedPreferences("drafts", Activity.MODE_PRIVATE);
Map<String, ?> values = preferences.getAll();
for (Map.Entry<String, ?> entry : values.entrySet()) {
try {
String key = entry.getKey();
long did = Utilities.parseLong(key);
byte[] bytes = Utilities.hexToBytes((String) entry.getValue());
SerializedData serializedData = new SerializedData(bytes);
if (key.startsWith("r_")) {
TLRPC.Message message = TLRPC.Message.TLdeserialize(serializedData, serializedData.readInt32(true), true);
if (message != null) {
draftMessages.put(did, message);
}
} else {
TLRPC.DraftMessage draftMessage = TLRPC.DraftMessage.TLdeserialize(serializedData, serializedData.readInt32(true), true);
if (draftMessage != null) {
drafts.put(did, draftMessage);
}
}
} catch (Exception e) {
//igonre
}
}
}
*/
public static void cleanup() {
/* EDIT BY MR
drafts.clear();
draftMessages.clear();
preferences.edit().clear().commit();
*/
}
public static TLRPC.DraftMessage getDraft(long did) { // returns null for "no draft"
MrChat mrChat = MrMailbox.getChat((int)did);
if( mrChat.getId() == 0 ) {
return null;
}
TLRPC.DraftMessage ret = new TLRPC.DraftMessage();
ret.message = mrChat.getDraft();
ret.date = (int)mrChat.getDraftTimestamp();
ret.reply_to_msg_id = mrChat.getDraftReplyToMsgId();
return ret;
}
public static TLRPC.Message getDraftMessage(long did) { // returns null for "no draft"
MrChat mrChat = MrMailbox.getChat((int)did);
if( mrChat.getId() == 0 ) {
return null;
}
TLRPC.Message ret = new TLRPC.Message();
ret.message = mrChat.getDraft();
ret.date = (int)mrChat.getDraftTimestamp();
ret.reply_to_msg_id = mrChat.getDraftReplyToMsgId();
return ret;
}
private static void saveDraft__(long did, String message, long replyToMessageId) // message may be null
{
MrChat mrChat = MrMailbox.getChat((int)did);
mrChat.setDraft(message, replyToMessageId);
}
public static void saveDraft(long did, CharSequence message, ArrayList<TLRPC.MessageEntity> entities, TLRPC.Message replyToMessage, boolean noWebpage) {
saveDraft(did, message, entities, replyToMessage, noWebpage, false);
}
public static void saveDraft(long did, CharSequence message, ArrayList<TLRPC.MessageEntity> entities, TLRPC.Message replyToMessage, boolean noWebpage, boolean clean) {
if( message == null || TextUtils.isEmpty(message) ) {
saveDraft__(did, null, 0);
}
else {
saveDraft__(did, message.toString(), 0);
}
/* EDIT BY MR
TLRPC.DraftMessage draftMessage;
if (!TextUtils.isEmpty(message) || replyToMessage != null) {
draftMessage = new TLRPC.TL_draftMessage();
} else {
draftMessage = new TLRPC.TL_draftMessageEmpty();
}
draftMessage.date = (int) (System.currentTimeMillis() / 1000);
draftMessage.message = message == null ? "" : message.toString();
draftMessage.no_webpage = noWebpage;
if (replyToMessage != null) {
draftMessage.reply_to_msg_id = replyToMessage.id;
draftMessage.flags |= 1;
}
if (entities != null && !entities.isEmpty()) {
draftMessage.entities = entities;
draftMessage.flags |= 8;
}
TLRPC.DraftMessage currentDraft = drafts.get(did);
if (!clean) {
if (currentDraft != null && currentDraft.message.equals(draftMessage.message) && currentDraft.reply_to_msg_id == draftMessage.reply_to_msg_id && currentDraft.no_webpage == draftMessage.no_webpage ||
currentDraft == null && TextUtils.isEmpty(draftMessage.message) && draftMessage.reply_to_msg_id == 0) {
return;
}
}
saveDraft(did, draftMessage, replyToMessage, false);
int lower_id = (int) did;
if (lower_id != 0) {
TLRPC.TL_messages_saveDraft req = new TLRPC.TL_messages_saveDraft();
req.peer = MessagesController.getInputPeer(lower_id);
if (req.peer == null) {
return;
}
req.message = draftMessage.message;
req.no_webpage = draftMessage.no_webpage;
req.reply_to_msg_id = draftMessage.reply_to_msg_id;
req.entities = draftMessage.entities;
req.flags = draftMessage.flags;
ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
}
});
}
MessagesController.getInstance().sortDialogs(null);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload);
*/
}
/* EDIT BY MR
private static void saveDraftReplyMessage(final long did, final TLRPC.Message message) {
if (message == null) {
return;
}
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
TLRPC.DraftMessage draftMessage = drafts.get(did);
if (draftMessage != null && draftMessage.reply_to_msg_id == message.id) {
draftMessages.put(did, message);
SerializedData serializedData = new SerializedData(message.getObjectSize());
message.serializeToStream(serializedData);
preferences.edit().putString("r_" + did, Utilities.bytesToHex(serializedData.toByteArray())).commit();
NotificationCenter.getInstance().postNotificationName(NotificationCenter.newDraftReceived, did);
}
}
});
}
*/
public static void cleanDraft(long did, boolean replyOnly) {
saveDraft__(did, null, 0);
/* EDIT BY MR
TLRPC.DraftMessage draftMessage = drafts.get(did);
if (draftMessage == null) {
return;
}
if (!replyOnly) {
drafts.remove(did);
draftMessages.remove(did);
preferences.edit().remove("" + did).remove("r_" + did).commit();
MessagesController.getInstance().sortDialogs(null);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload);
} else if (draftMessage.reply_to_msg_id != 0) {
draftMessage.reply_to_msg_id = 0;
draftMessage.flags &= ~1;
saveDraft(did, draftMessage.message, draftMessage.entities, null, draftMessage.no_webpage, true);
}
*/
}
/* EDIT BY MR
public static void beginTransaction() {
inTransaction = true;
}
public static void endTransaction() {
inTransaction = false;
}
*/
}
@@ -1,445 +0,0 @@
/*
* This is the source code of Telegram for Android v. 3.x.x
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
package com.b44t.messenger.query;
import android.text.Spannable;
import com.b44t.messenger.MessageObject;
import com.b44t.messenger.MessagesController;
import com.b44t.messenger.Utilities;
import com.b44t.messenger.TLRPC;
import com.b44t.ui.Components.URLSpanUserMention;
import java.util.ArrayList;
import java.util.HashMap;
public class MessagesQuery {
public static MessageObject loadPinnedMessage(final int channelId, final int mid, boolean useQueue) {
if (useQueue) {
/*
MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() {
@Override
public void run() {
loadPinnedMessageInternal(channelId, mid, false);
}
});
*/
} else {
return loadPinnedMessageInternal(channelId, mid, true);
}
return null;
}
private static MessageObject loadPinnedMessageInternal(final int channelId, final int mid, boolean returnValue) {
/*
try {
long messageId = ((long) mid) | ((long) channelId) << 32;
TLRPC.Message result = null;
final ArrayList<TLRPC.User> users = new ArrayList<>();
final ArrayList<TLRPC.Chat> chats = new ArrayList<>();
ArrayList<Integer> usersToLoad = new ArrayList<>();
ArrayList<Integer> chatsToLoad = new ArrayList<>();
SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, mid, date FROM messages WHERE mid = %d", messageId));
if (cursor.next()) {
NativeByteBuffer data = cursor.byteBufferValue(0);
if (data != null) {
result = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false);
data.reuse();
result.id = cursor.intValue(1);
result.date = cursor.intValue(2);
result.dialog_id = -channelId;
MessagesStorage.addUsersAndChatsFromMessage(result, usersToLoad, chatsToLoad);
}
}
cursor.dispose();
if (result == null) {
cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT data FROM chat_pinned WHERE uid = %d", channelId));
if (cursor.next()) {
NativeByteBuffer data = cursor.byteBufferValue(0);
if (data != null) {
result = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false);
data.reuse();
if (result.id != mid) {
result = null;
} else {
result.dialog_id = -channelId;
MessagesStorage.addUsersAndChatsFromMessage(result, usersToLoad, chatsToLoad);
}
}
}
cursor.dispose();
}
if (result == null) {
final TLRPC.TL_channels_getMessages req = new TLRPC.TL_channels_getMessages();
req.channel = MessagesController.getInputChannel(channelId);
req.id.add(mid);
ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
boolean ok = false;
if (error == null) {
TLRPC.messages_Messages messagesRes = (TLRPC.messages_Messages) response;
if (!messagesRes.messages.isEmpty()) {
ImageLoader.saveMessagesThumbs(messagesRes.messages);
broadcastPinnedMessage(messagesRes.messages.get(0), messagesRes.users, messagesRes.chats, false, false);
//MessagesStorage.getInstance().putUsersAndChats(messagesRes.users, messagesRes.chats, true, true);
savePinnedMessage(messagesRes.messages.get(0));
ok = true;
}
}
if (!ok) {
MessagesStorage.getInstance().updateChannelPinnedMessage(channelId, 0);
}
}
});
} else {
if (returnValue) {
return broadcastPinnedMessage(result, users, chats, true, returnValue);
} else {
if (!usersToLoad.isEmpty()) {
//MessagesStorage.getInstance().getUsersInternal(TextUtils.join(",", usersToLoad), users);
}
if (!chatsToLoad.isEmpty()) {
//MessagesStorage.getInstance().getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
}
broadcastPinnedMessage(result, users, chats, true, false);
}
}
} catch (Exception e) {
FileLog.e("messenger", e);
}
*/
return null;
}
/*
private static MessageObject broadcastPinnedMessage(final TLRPC.Message result, final ArrayList<TLRPC.User> users, final ArrayList<TLRPC.Chat> chats, final boolean isCache, boolean returnValue) {
final HashMap<Integer, TLRPC.User> usersDict = new HashMap<>();
for (int a = 0; a < users.size(); a++) {
TLRPC.User user = users.get(a);
usersDict.put(user.id, user);
}
final HashMap<Integer, TLRPC.Chat> chatsDict = new HashMap<>();
for (int a = 0; a < chats.size(); a++) {
TLRPC.Chat chat = chats.get(a);
chatsDict.put(chat.id, chat);
}
if (returnValue) {
return new MessageObject(result, usersDict, chatsDict, false);
} else {
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
MessagesController.getInstance().putUsers(users, isCache);
MessagesController.getInstance().putChats(chats, isCache);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.didLoadedPinnedMessage, new MessageObject(result, usersDict, chatsDict, false));
}
});
}
return null;
}
*/
public static void loadReplyMessagesForMessages(final ArrayList<MessageObject> messages, final long dialogId) {
if ((int) dialogId == 0) {
final ArrayList<Long> replyMessages = new ArrayList<>();
final HashMap<Long, ArrayList<MessageObject>> replyMessageRandomOwners = new HashMap<>();
final StringBuilder stringBuilder = new StringBuilder();
for (int a = 0; a < messages.size(); a++) {
MessageObject messageObject = messages.get(a);
if (messageObject.isReply() && messageObject.replyMessageObject == null) {
Long id = messageObject.messageOwner.reply_to_random_id;
if (stringBuilder.length() > 0) {
stringBuilder.append(',');
}
stringBuilder.append(id);
ArrayList<MessageObject> messageObjects = replyMessageRandomOwners.get(id);
if (messageObjects == null) {
messageObjects = new ArrayList<>();
replyMessageRandomOwners.put(id, messageObjects);
}
messageObjects.add(messageObject);
if (!replyMessages.contains(id)) {
replyMessages.add(id);
}
}
}
if (replyMessages.isEmpty()) {
return;
}
/*
MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() {
@Override
public void run() {
try {
SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid, m.date, r.random_id FROM randoms as r INNER JOIN messages as m ON r.mid = m.mid WHERE r.random_id IN(%s)", TextUtils.join(",", replyMessages)));
while (cursor.next()) {
NativeByteBuffer data = cursor.byteBufferValue(0);
if (data != null) {
TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false);
data.reuse();
message.id = cursor.intValue(1);
message.date = cursor.intValue(2);
message.dialog_id = dialogId;
ArrayList<MessageObject> arrayList = replyMessageRandomOwners.remove(cursor.longValue(3));
if (arrayList != null) {
MessageObject messageObject = new MessageObject(message, null, null, false);
for (int b = 0; b < arrayList.size(); b++) {
MessageObject object = arrayList.get(b);
object.replyMessageObject = messageObject;
object.messageOwner.reply_to_msg_id = messageObject.getId();
}
}
}
}
cursor.dispose();
if (!replyMessageRandomOwners.isEmpty()) {
for (HashMap.Entry<Long, ArrayList<MessageObject>> entry : replyMessageRandomOwners.entrySet()) {
ArrayList<MessageObject> arrayList = entry.getValue();
for (int a = 0; a < arrayList.size(); a++) {
arrayList.get(a).messageOwner.reply_to_random_id = 0;
}
}
}
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
NotificationCenter.getInstance().postNotificationName(NotificationCenter.didLoadedReplyMessages, dialogId);
}
});
} catch (Exception e) {
FileLog.e("messenger", e);
}
}
});
*/
} else {
final ArrayList<Integer> replyMessages = new ArrayList<>();
final HashMap<Integer, ArrayList<MessageObject>> replyMessageOwners = new HashMap<>();
final StringBuilder stringBuilder = new StringBuilder();
int channelId = 0;
for (int a = 0; a < messages.size(); a++) {
MessageObject messageObject = messages.get(a);
if (messageObject.getId() > 0 && messageObject.isReply() && messageObject.replyMessageObject == null) {
Integer id = messageObject.messageOwner.reply_to_msg_id;
long messageId = id;
if (messageObject.messageOwner.to_id.channel_id != 0) {
messageId |= ((long) messageObject.messageOwner.to_id.channel_id) << 32;
channelId = messageObject.messageOwner.to_id.channel_id;
}
if (stringBuilder.length() > 0) {
stringBuilder.append(',');
}
stringBuilder.append(messageId);
ArrayList<MessageObject> messageObjects = replyMessageOwners.get(id);
if (messageObjects == null) {
messageObjects = new ArrayList<>();
replyMessageOwners.put(id, messageObjects);
}
messageObjects.add(messageObject);
if (!replyMessages.contains(id)) {
replyMessages.add(id);
}
}
}
if (replyMessages.isEmpty()) {
return;
}
/*
final int channelIdFinal = channelId;
MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() {
@Override
public void run() {
try {
final ArrayList<TLRPC.Message> result = new ArrayList<>();
final ArrayList<TLRPC.User> users = new ArrayList<>();
final ArrayList<TLRPC.Chat> chats = new ArrayList<>();
ArrayList<Integer> usersToLoad = new ArrayList<>();
ArrayList<Integer> chatsToLoad = new ArrayList<>();
SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, mid, date FROM messages WHERE mid IN(%s)", stringBuilder.toString()));
while (cursor.next()) {
NativeByteBuffer data = cursor.byteBufferValue(0);
if (data != null) {
TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false);
data.reuse();
message.id = cursor.intValue(1);
message.date = cursor.intValue(2);
message.dialog_id = dialogId;
MessagesStorage.addUsersAndChatsFromMessage(message, usersToLoad, chatsToLoad);
result.add(message);
replyMessages.remove((Integer) message.id);
}
}
cursor.dispose();
if (!usersToLoad.isEmpty()) {
//MessagesStorage.getInstance().getUsersInternal(TextUtils.join(",", usersToLoad), users);
}
if (!chatsToLoad.isEmpty()) {
//MessagesStorage.getInstance().getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
}
broadcastReplyMessages(result, replyMessageOwners, users, chats, dialogId, true);
if (!replyMessages.isEmpty()) {
if (channelIdFinal != 0) {
final TLRPC.TL_channels_getMessages req = new TLRPC.TL_channels_getMessages();
req.channel = MessagesController.getInputChannel(channelIdFinal);
req.id = replyMessages;
ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error == null) {
TLRPC.messages_Messages messagesRes = (TLRPC.messages_Messages) response;
ImageLoader.saveMessagesThumbs(messagesRes.messages);
broadcastReplyMessages(messagesRes.messages, replyMessageOwners, messagesRes.users, messagesRes.chats, dialogId, false);
//MessagesStorage.getInstance().putUsersAndChats(messagesRes.users, messagesRes.chats, true, true);
saveReplyMessages(replyMessageOwners, messagesRes.messages);
}
}
});
} else {
TLRPC.TL_messages_getMessages req = new TLRPC.TL_messages_getMessages();
req.id = replyMessages;
ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error == null) {
TLRPC.messages_Messages messagesRes = (TLRPC.messages_Messages) response;
ImageLoader.saveMessagesThumbs(messagesRes.messages);
broadcastReplyMessages(messagesRes.messages, replyMessageOwners, messagesRes.users, messagesRes.chats, dialogId, false);
//MessagesStorage.getInstance().putUsersAndChats(messagesRes.users, messagesRes.chats, true, true);
saveReplyMessages(replyMessageOwners, messagesRes.messages);
}
}
});
}
}
} catch (Exception e) {
FileLog.e("messenger", e);
}
}
});
*/
}
}
/*
private static void saveReplyMessages(final HashMap<Integer, ArrayList<MessageObject>> replyMessageOwners, final ArrayList<TLRPC.Message> result) {
MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() {
@Override
public void run() {
try {
MessagesStorage.getInstance().getDatabase().beginTransaction();
SQLitePreparedStatement state = MessagesStorage.getInstance().getDatabase().executeFast("UPDATE messages SET replydata = ? WHERE mid = ?");
for (int a = 0; a < result.size(); a++) {
TLRPC.Message message = result.get(a);
ArrayList<MessageObject> messageObjects = replyMessageOwners.get(message.id);
if (messageObjects != null) {
NativeByteBuffer data = new NativeByteBuffer(message.getObjectSize());
message.serializeToStream(data);
for (int b = 0; b < messageObjects.size(); b++) {
MessageObject messageObject = messageObjects.get(b);
state.requery();
long messageId = messageObject.getId();
if (messageObject.messageOwner.to_id.channel_id != 0) {
messageId |= ((long) messageObject.messageOwner.to_id.channel_id) << 32;
}
state.bindByteBuffer(1, data);
state.bindLong(2, messageId);
state.step();
}
data.reuse();
}
}
state.dispose();
MessagesStorage.getInstance().getDatabase().commitTransaction();
} catch (Exception e) {
FileLog.e("messenger", e);
}
}
});
}
*/
/*
private static void broadcastReplyMessages(final ArrayList<TLRPC.Message> result, final HashMap<Integer, ArrayList<MessageObject>> replyMessageOwners, final ArrayList<TLRPC.User> users, final ArrayList<TLRPC.Chat> chats, final long dialog_id, final boolean isCache) {
final HashMap<Integer, TLRPC.User> usersDict = new HashMap<>();
for (int a = 0; a < users.size(); a++) {
TLRPC.User user = users.get(a);
usersDict.put(user.id, user);
}
final HashMap<Integer, TLRPC.Chat> chatsDict = new HashMap<>();
for (int a = 0; a < chats.size(); a++) {
TLRPC.Chat chat = chats.get(a);
chatsDict.put(chat.id, chat);
}
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
MessagesController.getInstance().putUsers(users, isCache);
MessagesController.getInstance().putChats(chats, isCache);
boolean changed = false;
for (int a = 0; a < result.size(); a++) {
TLRPC.Message message = result.get(a);
ArrayList<MessageObject> arrayList = replyMessageOwners.get(message.id);
if (arrayList != null) {
MessageObject messageObject = new MessageObject(message, usersDict, chatsDict, false);
for (int b = 0; b < arrayList.size(); b++) {
MessageObject m = arrayList.get(b);
m.replyMessageObject = messageObject;
//if (m.messageOwner.action instanceof TLRPC.TL_messageActionPinMessage) {
// m.generatePinMessageText(null, null);
//}
}
changed = true;
}
}
if (changed) {
NotificationCenter.getInstance().postNotificationName(NotificationCenter.didLoadedReplyMessages, dialog_id);
}
}
});
}
*/
public static ArrayList<TLRPC.MessageEntity> getEntities(CharSequence message) {
if (message == null) {
return null;
}
ArrayList<TLRPC.MessageEntity> entities = null;
if (message instanceof Spannable) {
Spannable spannable = (Spannable) message;
URLSpanUserMention spans[] = spannable.getSpans(0, message.length(), URLSpanUserMention.class);
if (spans != null && spans.length > 0) {
entities = new ArrayList<>();
for (int b = 0; b < spans.length; b++) {
TLRPC.TL_inputMessageEntityMentionName entity = new TLRPC.TL_inputMessageEntityMentionName();
entity.user_id = MessagesController.getInputUser(Utilities.parseInt(spans[b].getURL()));
if (entity.user_id != null) {
entity.offset = spannable.getSpanStart(spans[b]);
entity.length = Math.min(spannable.getSpanEnd(spans[b]), message.length()) - entity.offset;
if (message.charAt(entity.offset + entity.length - 1) == ' ') {
entity.length--;
}
entities.add(entity);
}
}
}
}
return entities;
}
}
@@ -1,208 +0,0 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
package com.b44t.messenger.query;
import com.b44t.messenger.MessageObject;
import com.b44t.messenger.MessagesController;
import com.b44t.messenger.NotificationCenter;
import com.b44t.messenger.ConnectionsManager;
import com.b44t.messenger.TLRPC;
import java.util.ArrayList;
@SuppressWarnings("unchecked")
public class MessagesSearchQuery {
private static int reqId;
private static int mergeReqId;
private static long lastMergeDialogId;
private static int lastReqId;
private static int messagesSearchCount[] = new int[] {0, 0};
private static boolean messagesSearchEndReached[] = new boolean[] {false, false};
private static ArrayList<MessageObject> searchResultMessages = new ArrayList<>();
private static String lastSearchQuery;
private static int lastReturnedNum;
private static int getMask() {
int mask = 0;
if (lastReturnedNum < searchResultMessages.size() - 1 || !messagesSearchEndReached[0] || !messagesSearchEndReached[1]) {
mask |= 1;
}
if (lastReturnedNum > 0) {
mask |= 2;
}
return mask;
}
public static void searchMessagesInChat(String query, final long dialog_id, final long mergeDialogId, final int guid, final int direction) {
searchMessagesInChat(query, dialog_id, mergeDialogId, guid, direction, false);
}
private static void searchMessagesInChat(String query, final long dialog_id, final long mergeDialogId, final int guid, final int direction, final boolean internal) {
int max_id = 0;
long queryWithDialog = dialog_id;
boolean firstQuery = !internal;
if (reqId != 0) {
ConnectionsManager.getInstance().cancelRequest(reqId, true);
reqId = 0;
}
if (mergeReqId != 0) {
ConnectionsManager.getInstance().cancelRequest(mergeReqId, true);
mergeReqId = 0;
}
if (query == null || query.length() == 0) {
if (searchResultMessages.isEmpty()) {
return;
}
if (direction == 1) {
lastReturnedNum++;
if (lastReturnedNum < searchResultMessages.size()) {
MessageObject messageObject = searchResultMessages.get(lastReturnedNum);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, messageObject.getId(), getMask(), messageObject.getDialogId(), lastReturnedNum, messagesSearchCount[0] + messagesSearchCount[1]);
return;
} else {
if (messagesSearchEndReached[0] && mergeDialogId == 0 || messagesSearchEndReached[1]) {
lastReturnedNum--;
return;
}
firstQuery = false;
query = lastSearchQuery;
MessageObject messageObject = searchResultMessages.get(searchResultMessages.size() - 1);
if (messageObject.getDialogId() == dialog_id && !messagesSearchEndReached[0]) {
max_id = messageObject.getId();
queryWithDialog = dialog_id;
} else {
if (messageObject.getDialogId() == mergeDialogId) {
max_id = messageObject.getId();
}
queryWithDialog = mergeDialogId;
messagesSearchEndReached[1] = false;
}
}
} else if (direction == 2) {
lastReturnedNum--;
if (lastReturnedNum < 0) {
lastReturnedNum = 0;
return;
}
if (lastReturnedNum >= searchResultMessages.size()) {
lastReturnedNum = searchResultMessages.size() - 1;
}
MessageObject messageObject = searchResultMessages.get(lastReturnedNum);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, messageObject.getId(), getMask(), messageObject.getDialogId(), lastReturnedNum, messagesSearchCount[0] + messagesSearchCount[1]);
return;
} else {
return;
}
}
if (messagesSearchEndReached[0] && !messagesSearchEndReached[1] && mergeDialogId != 0) {
queryWithDialog = mergeDialogId;
}
if (queryWithDialog == dialog_id && firstQuery) {
if (mergeDialogId != 0) {
TLRPC.InputPeer inputPeer = MessagesController.getInputPeer((int) mergeDialogId);
if (inputPeer == null) {
return;
}
final TLRPC.TL_messages_search req = new TLRPC.TL_messages_search();
req.peer = inputPeer;
lastMergeDialogId = mergeDialogId;
req.limit = 1;
req.q = query;
req.filter = new TLRPC.TL_inputMessagesFilterEmpty();
mergeReqId = 0;/*ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
@Override
public void run(final TLObject response, final TLRPC.TL_error error) {
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
if (lastMergeDialogId == mergeDialogId) {
mergeReqId = 0;
if (response != null) {
TLRPC.messages_Messages res = (TLRPC.messages_Messages) response;
messagesSearchEndReached[1] = res.messages.isEmpty();
messagesSearchCount[1] = res instanceof TLRPC.TL_messages_messagesSlice ? res.count : res.messages.size();
searchMessagesInChat(req.q, dialog_id, mergeDialogId, guid, direction, true);
}
}
}
});
}
}, ConnectionsManager.RequestFlagFailOnServerErrors);*/
return;
} else {
lastMergeDialogId = 0;
messagesSearchEndReached[1] = true;
messagesSearchCount[1] = 0;
}
}
final TLRPC.TL_messages_search req = new TLRPC.TL_messages_search();
req.peer = MessagesController.getInputPeer((int) queryWithDialog);
if (req.peer == null) {
return;
}
req.limit = 21;
req.q = query;
req.max_id = max_id;
req.filter = new TLRPC.TL_inputMessagesFilterEmpty();
final int currentReqId = ++lastReqId;
lastSearchQuery = query;
final long queryWithDialogFinal = queryWithDialog;
reqId = 0; /* ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
@Override
public void run(final TLObject response, final TLRPC.TL_error error) {
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
if (currentReqId == lastReqId) {
reqId = 0;
if (response != null) {
TLRPC.messages_Messages res = (TLRPC.messages_Messages) response;
//MessagesStorage.getInstance().putUsersAndChats(res.users, res.chats, true, true);
MessagesController.getInstance().putUsers(res.users, false);
MessagesController.getInstance().putChats(res.chats, false);
if (req.max_id == 0 && queryWithDialogFinal == dialog_id) {
lastReturnedNum = 0;
searchResultMessages.clear();
messagesSearchCount[0] = 0;
}
boolean added = false;
for (int a = 0; a < Math.min(res.messages.size(), 20); a++) {
TLRPC.Message message = res.messages.get(a);
added = true;
searchResultMessages.add(new MessageObject(message, null, false));
}
messagesSearchEndReached[queryWithDialogFinal == dialog_id ? 0 : 1] = res.messages.size() != 21;
messagesSearchCount[queryWithDialogFinal == dialog_id ? 0 : 1] = res instanceof TLRPC.TL_messages_messagesSlice ? res.count : res.messages.size();
if (searchResultMessages.isEmpty()) {
NotificationCenter.getInstance().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, 0, getMask(), (long) 0, 0, 0);
} else {
if (added) {
if (lastReturnedNum >= searchResultMessages.size()) {
lastReturnedNum = searchResultMessages.size() - 1;
}
MessageObject messageObject = searchResultMessages.get(lastReturnedNum);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, messageObject.getId(), getMask(), messageObject.getDialogId(), lastReturnedNum, messagesSearchCount[0] + messagesSearchCount[1]);
}
}
if (queryWithDialogFinal == dialog_id && messagesSearchEndReached[0] && mergeDialogId != 0 && !messagesSearchEndReached[1]) {
searchMessagesInChat(lastSearchQuery, dialog_id, mergeDialogId, guid, 0, true);
}
}
}
}
});
}
}, ConnectionsManager.RequestFlagFailOnServerErrors);*/
}
public static String getLastSearchQuery() {
return lastSearchQuery;
}
}
@@ -1,327 +0,0 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
package com.b44t.messenger.query;
import com.b44t.messenger.MessagesController;
import com.b44t.messenger.NotificationCenter;
import com.b44t.messenger.TLRPC;
import java.util.ArrayList;
import java.util.HashMap;
public class SearchQuery {
public static ArrayList<TLRPC.TL_topPeer> hints = new ArrayList<>();
public static ArrayList<TLRPC.TL_topPeer> inlineBots = new ArrayList<>();
private static HashMap<Integer, Integer> inlineDates = new HashMap<>();
private static boolean loaded;
private static boolean loading;
public static void cleanup() {
loading = false;
loaded = false;
hints.clear();
inlineBots.clear();
inlineDates.clear();
NotificationCenter.getInstance().postNotificationName(NotificationCenter.reloadHints);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.reloadInlineHints);
}
public static void loadHints(boolean cache) {
if (loading) {
return;
}
if (cache) {
if (loaded) {
return;
}
loading = true;
/*
MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() {
@Override
public void run() {
final ArrayList<TLRPC.TL_topPeer> hintsNew = new ArrayList<>();
final ArrayList<TLRPC.TL_topPeer> inlineBotsNew = new ArrayList<>();
final HashMap<Integer, Integer> inlineDatesNew = new HashMap<>();
final ArrayList<TLRPC.User> users = new ArrayList<>();
final ArrayList<TLRPC.Chat> chats = new ArrayList<>();
try {
ArrayList<Integer> usersToLoad = new ArrayList<>();
ArrayList<Integer> chatsToLoad = new ArrayList<>();
SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized("SELECT did, type, rating, date FROM chat_hints WHERE 1 ORDER BY rating DESC");
while (cursor.next()) {
int did = cursor.intValue(0);
int type = cursor.intValue(1);
TLRPC.TL_topPeer peer = new TLRPC.TL_topPeer();
peer.rating = cursor.doubleValue(2);
if (did > 0) {
peer.peer = new TLRPC.TL_peerUser();
peer.peer.user_id = did;
usersToLoad.add(did);
} else {
peer.peer = new TLRPC.TL_peerChat();
peer.peer.chat_id = -did;
chatsToLoad.add(-did);
}
if (type == 0) {
hintsNew.add(peer);
} else if (type == 1) {
inlineBotsNew.add(peer);
inlineDatesNew.put(did, cursor.intValue(3));
}
}
cursor.dispose();
if (!usersToLoad.isEmpty()) {
//MessagesStorage.getInstance().getUsersInternal(TextUtils.join(",", usersToLoad), users);
}
if (!chatsToLoad.isEmpty()) {
//MessagesStorage.getInstance().getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
}
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
MessagesController.getInstance().putUsers(users, true);
MessagesController.getInstance().putChats(chats, true);
loading = false;
loaded = true;
hints = hintsNew;
inlineBots = inlineBotsNew;
inlineDates = inlineDatesNew;
NotificationCenter.getInstance().postNotificationName(NotificationCenter.reloadHints);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.reloadInlineHints);
if (Math.abs(UserConfig.lastHintsSyncTime - (int) (System.currentTimeMillis() / 1000)) >= 24 * 60 * 60) {
loadHints(false);
}
}
});
} catch (Exception e) {
FileLog.e("messenger", e);
}
}
});
*/
loaded = true;
} else {
loading = true;
/*
TLRPC.TL_contacts_getTopPeers req = new TLRPC.TL_contacts_getTopPeers();
req.hash = 0;
req.bots_pm = false;
req.correspondents = true;
req.groups = false;
req.channels = false;
req.bots_inline = true;
req.offset = 0;
req.limit = 20;
ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
@Override
public void run(final TLObject response, TLRPC.TL_error error) {
if (response instanceof TLRPC.TL_contacts_topPeers) {
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
final TLRPC.TL_contacts_topPeers topPeers = (TLRPC.TL_contacts_topPeers) response;
MessagesController.getInstance().putUsers(topPeers.users, false);
MessagesController.getInstance().putChats(topPeers.chats, false);
for (int a = 0; a < topPeers.categories.size(); a++) {
TLRPC.TL_topPeerCategoryPeers category = topPeers.categories.get(a);
if (category.category instanceof TLRPC.TL_topPeerCategoryBotsInline) {
inlineBots = category.peers;
} else {
hints = category.peers;
}
}
NotificationCenter.getInstance().postNotificationName(NotificationCenter.reloadHints);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.reloadInlineHints);
final HashMap<Integer, Integer> inlineDatesCopy = new HashMap<>(inlineDates);
MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() {
@Override
public void run() {
try {
MessagesStorage.getInstance().getDatabase().executeFast("DELETE FROM chat_hints WHERE 1").stepThis().dispose();
MessagesStorage.getInstance().getDatabase().beginTransaction();
MessagesStorage.getInstance().putUsersAndChats(topPeers.users, topPeers.chats, false, false);
SQLitePreparedStatement state = MessagesStorage.getInstance().getDatabase().executeFast("REPLACE INTO chat_hints VALUES(?, ?, ?, ?)");
for (int a = 0; a < topPeers.categories.size(); a++) {
int type;
TLRPC.TL_topPeerCategoryPeers category = topPeers.categories.get(a);
if (category.category instanceof TLRPC.TL_topPeerCategoryBotsInline) {
type = 1;
} else {
type = 0;
}
for (int b = 0; b < category.peers.size(); b++) {
TLRPC.TL_topPeer peer = category.peers.get(b);
int did;
if (peer.peer instanceof TLRPC.TL_peerUser) {
did = peer.peer.user_id;
} else if (peer.peer instanceof TLRPC.TL_peerChat) {
did = -peer.peer.chat_id;
} else {
did = -peer.peer.channel_id;
}
Integer date = inlineDatesCopy.get(did);
state.requery();
state.bindInteger(1, did);
state.bindInteger(2, type);
state.bindDouble(3, peer.rating);
state.bindInteger(4, date != null ? date : 0);
state.step();
}
}
state.dispose();
MessagesStorage.getInstance().getDatabase().commitTransaction();
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
UserConfig.lastHintsSyncTime = (int) (System.currentTimeMillis() / 1000);
UserConfig.saveConfig(false);
}
});
} catch (Exception e) {
FileLog.e("messenger", e);
}
}
});
}
});
}
}
});*/
}
}
public static void removeInline(final int uid) {
TLRPC.TL_topPeerCategoryPeers category = null;
for (int a = 0; a < inlineBots.size(); a++) {
if (inlineBots.get(a).peer.user_id == uid) {
inlineBots.remove(a);
/*TLRPC.TL_contacts_resetTopPeerRating req = new TLRPC.TL_contacts_resetTopPeerRating();
req.category = new TLRPC.TL_topPeerCategoryBotsInline();
req.peer = MessagesController.getInputPeer(uid);
ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
}
});
deletePeer(uid, 1);
*/
NotificationCenter.getInstance().postNotificationName(NotificationCenter.reloadInlineHints);
return;
}
}
}
public static void removePeer(final int uid) {
TLRPC.TL_topPeerCategoryPeers category = null;
for (int a = 0; a < hints.size(); a++) {
if (hints.get(a).peer.user_id == uid) {
hints.remove(a);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.reloadHints);
/*TLRPC.TL_contacts_resetTopPeerRating req = new TLRPC.TL_contacts_resetTopPeerRating();
req.category = new TLRPC.TL_topPeerCategoryCorrespondents();
req.peer = MessagesController.getInputPeer(uid);
deletePeer(uid, 0);
ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
}
});*/
return;
}
}
}
public static void increasePeerRaiting(final long did) {
final int lower_id = (int) did;
if (lower_id <= 0) {
return;
}
//remove chats and bots for now
final TLRPC.User user = lower_id > 0 ? MessagesController.getInstance().getUser(lower_id) : null;
//final TLRPC.Chat chat = lower_id < 0 ? MessagesController.getInstance().getChat(-lower_id) : null;
if (user == null || user.bot/*&& chat == null || ChatObject.isChannel(chat) && !chat.megagroup*/) {
return;
}
/*
MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() {
@Override
public void run() {
double dt = 0;
try {
int lastTime = 0;
int lastMid = 0;
SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT MAX(mid), MAX(date) FROM messages WHERE uid = %d AND out = 1", did));
if (cursor.next()) {
lastMid = cursor.intValue(0);
lastTime = cursor.intValue(1);
}
cursor.dispose();
if (lastMid > 0) {
cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT date FROM messages WHERE uid = %d AND mid < %d AND out = 1 ORDER BY date DESC", did, lastMid));
if (cursor.next()) {
dt = (lastTime - cursor.intValue(0));
}
cursor.dispose();
}
} catch (Exception e) {
FileLog.e("messenger", e);
}
final double dtFinal = dt;
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
TLRPC.TL_topPeer peer = null;
for (int a = 0; a < hints.size(); a++) {
TLRPC.TL_topPeer p = hints.get(a);
if (lower_id < 0 && (p.peer.chat_id == -lower_id || p.peer.channel_id == -lower_id) || lower_id > 0 && p.peer.user_id == lower_id) {
peer = p;
break;
}
}
if (peer == null) {
peer = new TLRPC.TL_topPeer();
if (lower_id > 0) {
peer.peer = new TLRPC.TL_peerUser();
peer.peer.user_id = lower_id;
} else {
peer.peer = new TLRPC.TL_peerChat();
peer.peer.chat_id = -lower_id;
}
hints.add(peer);
}
peer.rating += Math.exp(dtFinal / MessagesController.getInstance().ratingDecay);
Collections.sort(hints, new Comparator<TLRPC.TL_topPeer>() {
@Override
public int compare(TLRPC.TL_topPeer lhs, TLRPC.TL_topPeer rhs) {
if (lhs.rating > rhs.rating) {
return -1;
} else if (lhs.rating < rhs.rating) {
return 1;
}
return 0;
}
});
savePeer((int) did, 0, peer.rating);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.reloadHints);
}
});
}
});
*/
}
}
@@ -1,439 +0,0 @@
/*
* This is the source code of Telegram for Android v. 2.0.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
package com.b44t.messenger.query;
import com.b44t.messenger.ChatObject;
import com.b44t.messenger.MessagesController;
import com.b44t.messenger.MrMailbox;
import com.b44t.messenger.MrMsg;
import com.b44t.messenger.NotificationCenter;
import com.b44t.messenger.Utilities;
import com.b44t.messenger.TLRPC;
public class SharedMediaQuery {
public final static int MEDIA_PHOTOVIDEO = 0;
public final static int MEDIA_FILE = 1;
public final static int MEDIA_AUDIO = 2;
public final static int MEDIA_URL = 3;
public final static int MEDIA_MUSIC = 4;
public final static int MEDIA_TYPES_COUNT = 5;
public static void loadMedia(final long uid, final int offset, final int count, final int max_id, final int type, final boolean fromCache, final int classGuid) {
final boolean isChannel = false;//(int) uid < 0 && ChatObject.isChannel(-(int) uid);
int lower_part = (int)uid;
if (fromCache || lower_part == 0) {
loadMediaDatabase(uid, offset, count, max_id, type, classGuid, isChannel);
} else {
TLRPC.TL_messages_search req = new TLRPC.TL_messages_search();
req.offset = offset;
req.limit = count + 1;
req.max_id = max_id;
if (type == MEDIA_PHOTOVIDEO) {
req.filter = new TLRPC.TL_inputMessagesFilterPhotoVideo();
} else if (type == MEDIA_FILE) {
req.filter = new TLRPC.TL_inputMessagesFilterDocument();
} else if (type == MEDIA_AUDIO) {
req.filter = new TLRPC.TL_inputMessagesFilterVoice();
} else if (type == MEDIA_URL) {
req.filter = new TLRPC.TL_inputMessagesFilterUrl();
} else if (type == MEDIA_MUSIC) {
req.filter = new TLRPC.TL_inputMessagesFilterMusic();
}
req.q = "";
req.peer = MessagesController.getInputPeer(lower_part);
if (req.peer == null) {
return;
}
/*int reqId = ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error == null) {
final TLRPC.messages_Messages res = (TLRPC.messages_Messages) response;
boolean topReached;
if (res.messages.size() > count) {
topReached = false;
res.messages.remove(res.messages.size() - 1);
} else {
topReached = true;
}
processLoadedMedia(res, uid, offset, count, max_id, type, false, classGuid, isChannel, topReached);
}
}
});
ConnectionsManager.getInstance().bindRequestToGuid(reqId, classGuid);*/
}
}
public static void getMediaCount(final long uid, final int type, final int classGuid, boolean fromCache) {
Utilities.globalQueue.postRunnable(new Runnable() {
@Override
public void run() {
int[] media = new int[0];
if( type == SharedMediaQuery.MEDIA_PHOTOVIDEO ) {
media = MrMailbox.getChatMedia((int)uid, MrMsg.MR_MSG_IMAGE, MrMsg.MR_MSG_VIDEO);
}
NotificationCenter.getInstance().postNotificationName(NotificationCenter.mediaCountDidLoaded,
uid, media.length, false /*not from cache*/, type, media);
}
});
/*
int lower_part = (int)uid;
if (fromCache || lower_part == 0) {
getMediaCountDatabase(uid, type, classGuid);
} else {
TLRPC.TL_messages_search req = new TLRPC.TL_messages_search();
req.offset = 0;
req.limit = 1;
req.max_id = 0;
if (type == MEDIA_PHOTOVIDEO) {
req.filter = new TLRPC.TL_inputMessagesFilterPhotoVideo();
} else if (type == MEDIA_FILE) {
req.filter = new TLRPC.TL_inputMessagesFilterDocument();
} else if (type == MEDIA_AUDIO) {
req.filter = new TLRPC.TL_inputMessagesFilterVoice();
} else if (type == MEDIA_URL) {
req.filter = new TLRPC.TL_inputMessagesFilterUrl();
} else if (type == MEDIA_MUSIC) {
req.filter = new TLRPC.TL_inputMessagesFilterMusic();
}
req.q = "";
req.peer = MessagesController.getInputPeer(lower_part);
if (req.peer == null) {
return;
}
int reqId = ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error == null) {
final TLRPC.messages_Messages res = (TLRPC.messages_Messages) response;
//MessagesStorage.getInstance().putUsersAndChats(res.users, res.chats, true, true);
int count;
if (res instanceof TLRPC.TL_messages_messages) {
count = res.messages.size();
} else {
count = res.count;
}
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
MessagesController.getInstance().putUsers(res.users, false);
MessagesController.getInstance().putChats(res.chats, false);
}
});
processLoadedMediaCount(count, uid, type, classGuid, false);
}
}
});
ConnectionsManager.getInstance().bindRequestToGuid(reqId, classGuid);
}
*/
}
/*
public static int getMediaType(TLRPC.Message message) {
if (message == null) {
return -1;
}
if (message.media instanceof TLRPC.TL_messageMediaPhoto) {
return MEDIA_PHOTOVIDEO;
} else if (message.media instanceof TLRPC.TL_messageMediaDocument) {
if (MessageObject.isVoiceMessage(message)) {
return MEDIA_AUDIO;
} else if (MessageObject.isVideoMessage(message)) {
return MEDIA_PHOTOVIDEO;
} else if (MessageObject.isStickerMessage(message)) {
return -1;
} else if (MessageObject.isMusicMessage(message)) {
return MEDIA_MUSIC;
} else {
return MEDIA_FILE;
}
} else if (!message.entities.isEmpty()) {
for (int a = 0; a < message.entities.size(); a++) {
TLRPC.MessageEntity entity = message.entities.get(a);
if (entity instanceof TLRPC.TL_messageEntityUrl || entity instanceof TLRPC.TL_messageEntityTextUrl || entity instanceof TLRPC.TL_messageEntityEmail) {
return MEDIA_URL;
}
}
}
return -1;
}
*/
/*
private static void processLoadedMedia(final TLRPC.messages_Messages res, final long uid, int offset, int count, int max_id, final int type, final boolean fromCache, final int classGuid, final boolean isChannel, final boolean topReached) {
int lower_part = (int)uid;
if (fromCache && res.messages.isEmpty() && lower_part != 0) {
loadMedia(uid, offset, count, max_id, type, false, classGuid);
} else {
if (!fromCache) {
ImageLoader.saveMessagesThumbs(res.messages);
//MessagesStorage.getInstance().putUsersAndChats(res.users, res.chats, true, true);
putMediaDatabase(uid, type, res.messages, max_id, topReached);
}
final HashMap<Integer, TLRPC.User> usersDict = new HashMap<>();
for (int a = 0; a < res.users.size(); a++) {
TLRPC.User u = res.users.get(a);
usersDict.put(u.id, u);
}
final ArrayList<MessageObject> objects = new ArrayList<>();
for (int a = 0; a < res.messages.size(); a++) {
TLRPC.Message message = res.messages.get(a);
objects.add(new MessageObject(message, usersDict, true));
}
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
int totalCount = res.count;
MessagesController.getInstance().putUsers(res.users, fromCache);
MessagesController.getInstance().putChats(res.chats, fromCache);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.mediaDidLoaded, uid, totalCount, objects, classGuid, type, topReached);
}
});
}
}
*/
private static void loadMediaDatabase(final long uid, final int offset, final int count, final int max_id, final int type, final int classGuid, final boolean isChannel) {
/*
MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() {
@Override
public void run() {
boolean topReached = false;
TLRPC.TL_messages_messages res = new TLRPC.TL_messages_messages();
try {
ArrayList<Integer> usersToLoad = new ArrayList<>();
ArrayList<Integer> chatsToLoad = new ArrayList<>();
int countToLoad = count + 1;
SQLiteCursor cursor;
SQLiteDatabase database = MessagesStorage.getInstance().getDatabase();
boolean isEnd = false;
if ((int) uid != 0) {
int channelId = 0;
long messageMaxId = max_id;
if (isChannel) {
channelId = -(int) uid;
}
if (messageMaxId != 0 && channelId != 0) {
messageMaxId |= ((long) channelId) << 32;
}
cursor = database.queryFinalized(String.format(Locale.US, "SELECT start FROM media_holes_v2 WHERE uid = %d AND type = %d AND start IN (0, 1)", uid, type));
if (cursor.next()) {
isEnd = cursor.intValue(0) == 1;
cursor.dispose();
} else {
cursor.dispose();
cursor = database.queryFinalized(String.format(Locale.US, "SELECT min(mid) FROM media_v2 WHERE uid = %d AND type = %d AND mid > 0", uid, type));
if (cursor.next()) {
int mid = cursor.intValue(0);
if (mid != 0) {
SQLitePreparedStatement state = database.executeFast("REPLACE INTO media_holes_v2 VALUES(?, ?, ?, ?)");
state.requery();
state.bindLong(1, uid);
state.bindInteger(2, type);
state.bindInteger(3, 0);
state.bindInteger(4, mid);
state.step();
state.dispose();
}
}
cursor.dispose();
}
if (messageMaxId != 0) {
long holeMessageId = 0;
cursor = database.queryFinalized(String.format(Locale.US, "SELECT end FROM media_holes_v2 WHERE uid = %d AND type = %d AND end <= %d ORDER BY end DESC LIMIT 1", uid, type, max_id));
if (cursor.next()) {
holeMessageId = cursor.intValue(0);
if (channelId != 0) {
holeMessageId |= ((long) channelId) << 32;
}
}
cursor.dispose();
if (holeMessageId > 1) {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v2 WHERE uid = %d AND mid > 0 AND mid < %d AND mid >= %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, messageMaxId, holeMessageId, type, countToLoad));
} else {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v2 WHERE uid = %d AND mid > 0 AND mid < %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, messageMaxId, type, countToLoad));
}
} else {
long holeMessageId = 0;
cursor = database.queryFinalized(String.format(Locale.US, "SELECT max(end) FROM media_holes_v2 WHERE uid = %d AND type = %d", uid, type));
if (cursor.next()) {
holeMessageId = cursor.intValue(0);
if (channelId != 0) {
holeMessageId |= ((long) channelId) << 32;
}
}
cursor.dispose();
if (holeMessageId > 1) {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v2 WHERE uid = %d AND mid >= %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d,%d", uid, holeMessageId, type, offset, countToLoad));
} else {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v2 WHERE uid = %d AND mid > 0 AND type = %d ORDER BY date DESC, mid DESC LIMIT %d,%d", uid, type, offset, countToLoad));
}
}
} else {
isEnd = true;
if (max_id != 0) {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid, r.random_id FROM media_v2 as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid > %d AND type = %d ORDER BY m.mid ASC LIMIT %d", uid, max_id, type, countToLoad));
} else {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid, r.random_id FROM media_v2 as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND type = %d ORDER BY m.mid ASC LIMIT %d,%d", uid, type, offset, countToLoad));
}
}
while (cursor.next()) {
NativeByteBuffer data = cursor.byteBufferValue(0);
if (data != null) {
TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false);
data.reuse();
message.id = cursor.intValue(1);
message.dialog_id = uid;
if ((int) uid == 0) {
message.random_id = cursor.longValue(2);
}
res.messages.add(message);
if (message.from_id > 0) {
if (!usersToLoad.contains(message.from_id)) {
usersToLoad.add(message.from_id);
}
} else {
if (!chatsToLoad.contains(-message.from_id)) {
chatsToLoad.add(-message.from_id);
}
}
}
}
cursor.dispose();
if (!usersToLoad.isEmpty()) {
//MessagesStorage.getInstance().getUsersInternal(TextUtils.join(",", usersToLoad), res.users);
}
if (!chatsToLoad.isEmpty()) {
//MessagesStorage.getInstance().getChatsInternal(TextUtils.join(",", chatsToLoad), res.chats);
}
if (res.messages.size() > count) {
topReached = false;
res.messages.remove(res.messages.size() - 1);
} else {
topReached = isEnd;
}
} catch (Exception e) {
res.messages.clear();
res.chats.clear();
res.users.clear();
FileLog.e("messenger", e);
} finally {
processLoadedMedia(res, uid, offset, count, max_id, type, true, classGuid, isChannel, topReached);
}
}
});
*/
}
/*
private static void putMediaDatabase(final long uid, final int type, final ArrayList<TLRPC.Message> messages, final int max_id, final boolean topReached) {
MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() {
@Override
public void run() {
try {
if (messages.isEmpty() || topReached) {
MessagesStorage.getInstance().doneHolesInMedia(uid, max_id, type);
if (messages.isEmpty()) {
return;
}
}
MessagesStorage.getInstance().getDatabase().beginTransaction();
SQLitePreparedStatement state2 = MessagesStorage.getInstance().getDatabase().executeFast("REPLACE INTO media_v2 VALUES(?, ?, ?, ?, ?)");
for (TLRPC.Message message : messages) {
if (canAddMessageToMedia(message)) {
long messageId = message.id;
if (message.to_id.channel_id != 0) {
messageId |= ((long) message.to_id.channel_id) << 32;
}
state2.requery();
NativeByteBuffer data = new NativeByteBuffer(message.getObjectSize());
message.serializeToStream(data);
state2.bindLong(1, messageId);
state2.bindLong(2, uid);
state2.bindInteger(3, message.date);
state2.bindInteger(4, type);
state2.bindByteBuffer(5, data);
state2.step();
data.reuse();
}
}
state2.dispose();
if (!topReached || max_id != 0) {
int minId = topReached ? 1 : messages.get(messages.size() - 1).id;
if (max_id != 0) {
MessagesStorage.getInstance().closeHolesInMedia(uid, minId, max_id, type);
} else {
MessagesStorage.getInstance().closeHolesInMedia(uid, minId, Integer.MAX_VALUE, type);
}
}
MessagesStorage.getInstance().getDatabase().commitTransaction();
} catch (Exception e) {
FileLog.e("messenger", e);
}
}
});
}
*/
public static void loadMusic(final long uid, final int max_id) {
/*
MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() {
@Override
public void run() {
final ArrayList<MessageObject> arrayList = new ArrayList<>();
try {
SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v2 WHERE uid = %d AND mid < %d AND type = %d ORDER BY date DESC, mid DESC LIMIT 1000", uid, max_id, MEDIA_MUSIC));
while (cursor.next()) {
NativeByteBuffer data = cursor.byteBufferValue(0);
if (data != null) {
TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false);
data.reuse();
if (MessageObject.isMusicMessage(message)) {
message.id = cursor.intValue(1);
message.dialog_id = uid;
arrayList.add(0, new MessageObject(mess age, null, false));
}
}
}
cursor.dispose();
} catch (Exception e) {
FileLog.e("messenger", e);
}
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
NotificationCenter.getInstance().postNotificationName(NotificationCenter.musicDidLoaded, uid, arrayList);
}
});
}
});
*/
}
}
@@ -1,519 +0,0 @@
/*
* This is the source code of Telegram for Android v. 3.x.x
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
package com.b44t.messenger.query;
import android.content.Context;
import com.b44t.messenger.NotificationCenter;
import com.b44t.messenger.TLRPC;
import java.util.ArrayList;
import java.util.HashMap;
public class StickersQuery {
private static int loadHash;
private static int loadDate;
private static ArrayList<TLRPC.TL_messages_stickerSet> stickerSets = new ArrayList<>();
private static HashMap<Long, TLRPC.TL_messages_stickerSet> stickerSetsById = new HashMap<>();
private static HashMap<String, TLRPC.TL_messages_stickerSet> stickerSetsByName = new HashMap<>();
private static HashMap<Long, String> stickersByEmoji = new HashMap<>();
private static HashMap<Long, TLRPC.Document> stickersById = new HashMap<>();
private static HashMap<String, ArrayList<TLRPC.Document>> allStickers = new HashMap<>();
private static boolean loadingStickers;
private static boolean stickersLoaded;
public static void cleanup() {
loadHash = 0;
loadDate = 0;
allStickers.clear();
stickerSets.clear();
stickersByEmoji.clear();
stickerSetsById.clear();
stickerSetsByName.clear();
loadingStickers = false;
stickersLoaded = false;
}
public static void checkStickers() {
if (!loadingStickers && (!stickersLoaded || Math.abs(System.currentTimeMillis() / 1000 - loadDate) >= 60 * 60)) {
loadStickers(true, false);
}
}
/*
public static boolean isLoadingStickers() {
return loadingStickers;
}
*/
public static TLRPC.Document getStickerById(long id) {
TLRPC.Document document = stickersById.get(id);
if (document != null) {
long setId = getStickerSetId(document);
TLRPC.TL_messages_stickerSet stickerSet = stickerSetsById.get(setId);
if (stickerSet != null && stickerSet.set.disabled) {
return null;
}
}
return document;
}
public static TLRPC.TL_messages_stickerSet getStickerSetByName(String name) {
return stickerSetsByName.get(name);
}
public static TLRPC.TL_messages_stickerSet getStickerSetById(Long id) {
return stickerSetsById.get(id);
}
public static HashMap<String, ArrayList<TLRPC.Document>> getAllStickers() {
return allStickers;
}
public static ArrayList<TLRPC.TL_messages_stickerSet> getStickerSets() {
return stickerSets;
}
public static boolean isStickerPackInstalled(long id) {
return stickerSetsById.containsKey(id);
}
public static boolean isStickerPackInstalled(String name) {
return stickerSetsByName.containsKey(name);
}
public static String getEmojiForSticker(long id) {
String value = stickersByEmoji.get(id);
return value != null ? value : "";
}
/*
public static void reorderStickers(final ArrayList<Long> order) {
Collections.sort(stickerSets, new Comparator<TLRPC.TL_messages_stickerSet>() {
@Override
public int compare(TLRPC.TL_messages_stickerSet lhs, TLRPC.TL_messages_stickerSet rhs) {
int index1 = order.indexOf(lhs.set.id);
int index2 = order.indexOf(rhs.set.id);
if (index1 > index2) {
return 1;
} else if (index1 < index2) {
return -1;
}
return 0;
}
});
loadHash = calcStickersHash(stickerSets);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.stickersDidLoaded);
StickersQuery.loadStickers(false, true);
}
*/
/*
public static void calcNewHash() {
loadHash = calcStickersHash(stickerSets);
}
*/
/*
public static void addNewStickerSet(final TLRPC.TL_messages_stickerSet set) {
if (stickerSetsById.containsKey(set.set.id) || stickerSetsByName.containsKey(set.set.short_name)) {
return;
}
stickerSets.add(0, set);
stickerSetsById.put(set.set.id, set);
stickerSetsByName.put(set.set.short_name, set);
for (int a = 0; a < set.documents.size(); a++) {
TLRPC.Document document = set.documents.get(a);
stickersById.put(document.id, document);
}
for (int a = 0; a < set.packs.size(); a++) {
TLRPC.TL_stickerPack stickerPack = set.packs.get(a);
stickerPack.emoticon = stickerPack.emoticon.replace("\uFE0F", "");
ArrayList<TLRPC.Document> arrayList = allStickers.get(stickerPack.emoticon);
if (arrayList == null) {
arrayList = new ArrayList<>();
allStickers.put(stickerPack.emoticon, arrayList);
}
for (int c = 0; c < stickerPack.documents.size(); c++) {
Long id = stickerPack.documents.get(c);
if (!stickersByEmoji.containsKey(id)) {
stickersByEmoji.put(id, stickerPack.emoticon);
}
TLRPC.Document sticker = stickersById.get(id);
if (sticker != null) {
arrayList.add(sticker);
}
}
}
loadHash = calcStickersHash(stickerSets);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.stickersDidLoaded);
StickersQuery.loadStickers(false, true);
}
*/
public static void loadStickers(boolean cache, boolean force) {
if (loadingStickers) {
return;
}
loadingStickers = true;
if (cache) {
/*
MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() {
@Override
public void run() {
ArrayList<TLRPC.TL_messages_stickerSet> newStickerArray = null;
int date = 0;
int hash = 0;
SQLiteCursor cursor = null;
try {
cursor = MessagesStorage.getInstance().getDatabase().queryFinalized("SELECT data, date, hash FROM stickers_v2 WHERE 1");
if (cursor.next()) {
NativeByteBuffer data = cursor.byteBufferValue(0);
if (data != null) {
newStickerArray = new ArrayList<>();
int count = data.readInt32(false);
for (int a = 0; a < count; a++) {
TLRPC.TL_messages_stickerSet stickerSet = TLRPC.TL_messages_stickerSet.TLdeserialize(data, data.readInt32(false), false);
newStickerArray.add(stickerSet);
}
data.reuse();
}
date = cursor.intValue(1);
hash = calcStickersHash(newStickerArray);
}
} catch (Throwable e) {
FileLog.e("messenger", e);
} finally {
if (cursor != null) {
cursor.dispose();
}
}
processLoadedStickers(newStickerArray, true, date, hash);
}
});
*/
} else {
/*final TLRPC.TL_messages_getAllStickers req = new TLRPC.TL_messages_getAllStickers();
req.hash = force ? 0 : loadHash;
ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
@Override
public void run(final TLObject response, final TLRPC.TL_error error) {
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
if (response instanceof TLRPC.TL_messages_allStickers) {
final HashMap<Long, TLRPC.TL_messages_stickerSet> newStickerSets = new HashMap<>();
final ArrayList<TLRPC.TL_messages_stickerSet> newStickerArray = new ArrayList<>();
final TLRPC.TL_messages_allStickers res = (TLRPC.TL_messages_allStickers) response;
for (int a = 0; a < res.sets.size(); a++) {
final TLRPC.StickerSet stickerSet = res.sets.get(a);
TLRPC.TL_messages_stickerSet oldSet = stickerSetsById.get(stickerSet.id);
if (oldSet != null && oldSet.set.hash == stickerSet.hash) {
oldSet.set.disabled = stickerSet.disabled;
oldSet.set.installed = stickerSet.installed;
oldSet.set.official = stickerSet.official;
newStickerSets.put(oldSet.set.id, oldSet);
newStickerArray.add(oldSet);
if (newStickerSets.size() == res.sets.size()) {
processLoadedStickers(newStickerArray, false, (int) (System.currentTimeMillis() / 1000), res.hash);
}
continue;
}
newStickerArray.add(null);
final int index = a;
TLRPC.TL_messages_getStickerSet req = new TLRPC.TL_messages_getStickerSet();
req.stickerset = new TLRPC.TL_inputStickerSetID();
req.stickerset.id = stickerSet.id;
req.stickerset.access_hash = stickerSet.access_hash;
ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
@Override
public void run(final TLObject response, final TLRPC.TL_error error) {
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
TLRPC.TL_messages_stickerSet res1 = (TLRPC.TL_messages_stickerSet) response;
newStickerArray.set(index, res1);
newStickerSets.put(stickerSet.id, res1);
if (newStickerSets.size() == res.sets.size()) {
processLoadedStickers(newStickerArray, false, (int) (System.currentTimeMillis() / 1000), res.hash);
}
}
});
}
});
}
} else {
processLoadedStickers(null, false, (int) (System.currentTimeMillis() / 1000), req.hash);
}
}
});
}
});*/
}
}
private static void putStickersToCache(ArrayList<TLRPC.TL_messages_stickerSet> stickers, final int date, final int hash) {
final ArrayList<TLRPC.TL_messages_stickerSet> stickersFinal = stickers != null ? new ArrayList<>(stickers) : null;
/*
MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() {
@Override
public void run() {
try {
if (stickersFinal != null) {
SQLitePreparedStatement state = MessagesStorage.getInstance().getDatabase().executeFast("REPLACE INTO stickers_v2 VALUES(?, ?, ?, ?)");
state.requery();
int size = 4;
for (int a = 0; a < stickersFinal.size(); a++) {
size += stickersFinal.get(a).getObjectSize();
}
NativeByteBuffer data = new NativeByteBuffer(size);
data.writeInt32(stickersFinal.size());
for (int a = 0; a < stickersFinal.size(); a++) {
stickersFinal.get(a).serializeToStream(data);
}
state.bindInteger(1, 1);
state.bindByteBuffer(2, data);
state.bindInteger(3, date);
state.bindInteger(4, hash);
state.step();
data.reuse();
state.dispose();
} else {
SQLitePreparedStatement state = MessagesStorage.getInstance().getDatabase().executeFast("UPDATE stickers_v2 SET date = ?");
state.requery();
state.bindInteger(1, date);
state.step();
state.dispose();
}
} catch (Exception e) {
FileLog.e("messenger", e);
}
}
});
*/
}
/*
public static String getStickerSetName(long setId) {
TLRPC.TL_messages_stickerSet stickerSet = stickerSetsById.get(setId);
return stickerSet != null ? stickerSet.set.short_name : null;
}
*/
public static long getStickerSetId(TLRPC.Document document) {
for (int a = 0; a < document.attributes.size(); a++) {
TLRPC.DocumentAttribute attribute = document.attributes.get(a);
if (attribute instanceof TLRPC.TL_documentAttributeSticker) {
if (attribute.stickerset instanceof TLRPC.TL_inputStickerSetID) {
return attribute.stickerset.id;
}
break;
}
}
return -1;
}
private static int calcStickersHash(ArrayList<TLRPC.TL_messages_stickerSet> sets) {
long acc = 0;
for (int a = 0; a < sets.size(); a++) {
TLRPC.StickerSet set = sets.get(a).set;
if (set.disabled) {
continue;
}
acc = ((acc * 20261) + 0x80000000L + set.hash) % 0x80000000L;
}
return (int) acc;
}
/*
private static void processLoadedStickers(final ArrayList<TLRPC.TL_messages_stickerSet> res, final boolean cache, final int date, final int hash) {
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
loadingStickers = false;
stickersLoaded = true;
}
});
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
if (cache && (res == null || Math.abs(System.currentTimeMillis() / 1000 - date) >= 60 * 60) || !cache && res == null && hash == 0) {
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
if (res != null && hash != 0) {
loadHash = hash;
}
loadStickers(false, false);
}
}, res == null && !cache ? 1000 : 0);
if (res == null) {
return;
}
}
if (res != null) {
try {
final ArrayList<TLRPC.TL_messages_stickerSet> stickerSetsNew = new ArrayList<>();
final HashMap<Long, TLRPC.TL_messages_stickerSet> stickerSetsByIdNew = new HashMap<>();
final HashMap<String, TLRPC.TL_messages_stickerSet> stickerSetsByNameNew = new HashMap<>();
final HashMap<Long, String> stickersByEmojiNew = new HashMap<>();
final HashMap<Long, TLRPC.Document> stickersByIdNew = new HashMap<>();
final HashMap<String, ArrayList<TLRPC.Document>> allStickersNew = new HashMap<>();
for (int a = 0; a < res.size(); a++) {
TLRPC.TL_messages_stickerSet stickerSet = res.get(a);
if (stickerSet == null) {
continue;
}
stickerSetsNew.add(stickerSet);
stickerSetsByIdNew.put(stickerSet.set.id, stickerSet);
stickerSetsByNameNew.put(stickerSet.set.short_name, stickerSet);
for (int b = 0; b < stickerSet.documents.size(); b++) {
TLRPC.Document document = stickerSet.documents.get(b);
if (document == null || document instanceof TLRPC.TL_documentEmpty) {
continue;
}
stickersByIdNew.put(document.id, document);
}
if (!stickerSet.set.disabled) {
for (int b = 0; b < stickerSet.packs.size(); b++) {
TLRPC.TL_stickerPack stickerPack = stickerSet.packs.get(b);
if (stickerPack == null || stickerPack.emoticon == null) {
continue;
}
stickerPack.emoticon = stickerPack.emoticon.replace("\uFE0F", "");
ArrayList<TLRPC.Document> arrayList = allStickersNew.get(stickerPack.emoticon);
if (arrayList == null) {
arrayList = new ArrayList<>();
allStickersNew.put(stickerPack.emoticon, arrayList);
}
for (int c = 0; c < stickerPack.documents.size(); c++) {
Long id = stickerPack.documents.get(c);
if (!stickersByEmojiNew.containsKey(id)) {
stickersByEmojiNew.put(id, stickerPack.emoticon);
}
TLRPC.Document sticker = stickersByIdNew.get(id);
if (sticker != null) {
arrayList.add(sticker);
}
}
}
}
}
if (!cache) {
putStickersToCache(stickerSetsNew, date, hash);
}
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
stickersById = stickersByIdNew;
stickerSetsById = stickerSetsByIdNew;
stickerSetsByName = stickerSetsByNameNew;
stickerSets = stickerSetsNew;
allStickers = allStickersNew;
stickersByEmoji = stickersByEmojiNew;
loadHash = hash;
loadDate = date;
NotificationCenter.getInstance().postNotificationName(NotificationCenter.stickersDidLoaded);
}
});
} catch (Throwable e) {
FileLog.e("messenger", e);
}
} else if (!cache) {
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
loadDate = date;
}
});
putStickersToCache(null, date, 0);
}
}
});
}
*/
public static void removeStickersSet(final Context context, TLRPC.StickerSet stickerSet, int hide) {
TLRPC.TL_inputStickerSetID stickerSetID = new TLRPC.TL_inputStickerSetID();
stickerSetID.access_hash = stickerSet.access_hash;
stickerSetID.id = stickerSet.id;
if (hide != 0) {
stickerSet.disabled = hide == 1;
for (int a = 0; a < stickerSets.size(); a++) {
TLRPC.TL_messages_stickerSet set = stickerSets.get(a);
if (set.set.id == stickerSet.id) {
stickerSets.remove(a);
if (hide == 2) {
stickerSets.add(0, set);
} else {
for (int b = stickerSets.size() - 1; b >= 0; b--) {
if (stickerSets.get(b).set.disabled) {
continue;
}
stickerSets.add(b + 1, set);
break;
}
}
break;
}
}
loadHash = calcStickersHash(stickerSets);
putStickersToCache(stickerSets, loadDate, loadHash);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.stickersDidLoaded);
/*TLRPC.TL_messages_installStickerSet req = new TLRPC.TL_messages_installStickerSet();
req.stickerset = stickerSetID;
req.disabled = hide == 1;
ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
@Override
public void run(TLObject response, final TLRPC.TL_error error) {
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
loadStickers(false, false);
}
}, 1000);
}
});*/
} else {
/*TLRPC.TL_messages_uninstallStickerSet req = new TLRPC.TL_messages_uninstallStickerSet();
req.stickerset = stickerSetID;
ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
@Override
public void run(TLObject response, final TLRPC.TL_error error) {
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
try {
if (error == null) {
Toast.makeText(context, LocaleController.getString("StickersRemoved", R.string.StickersRemoved), Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, LocaleController.getString("ErrorOccurred", R.string.ErrorOccurred), Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
FileLog.e("messenger", e);
}
loadStickers(false, true);
}
});
}
});*/
}
}
}
@@ -1,592 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.b44t.messenger.support.util;
import android.support.annotation.UiThread;
import android.support.annotation.WorkerThread;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
/**
* A utility class that supports asynchronous content loading.
* <p>
* It can be used to load Cursor data in chunks without querying the Cursor on the UI Thread while
* keeping UI and cache synchronous for better user experience.
* <p>
* It loads the data on a background thread and keeps only a limited number of fixed sized
* chunks in memory at all times.
* <p>
* {@link AsyncListUtil} queries the currently visible range through {@link ViewCallback},
* loads the required data items in the background through {@link DataCallback}, and notifies a
* {@link ViewCallback} when the data is loaded. It may load some extra items for smoother
* scrolling.
* <p>
* Note that this class uses a single thread to load the data, so it suitable to load data from
* secondary storage such as disk, but not from network.
* <p>
* This class is designed to work with {@link android.support.v7.widget.RecyclerView}, but it does
* not depend on it and can be used with other list views.
*
*/
public class AsyncListUtil<T> {
private static final String TAG = "AsyncListUtil";
private static final boolean DEBUG = false;
final Class<T> mTClass;
final int mTileSize;
final DataCallback<T> mDataCallback;
final ViewCallback mViewCallback;
final TileList<T> mTileList;
final ThreadUtil.MainThreadCallback<T> mMainThreadProxy;
final ThreadUtil.BackgroundCallback<T> mBackgroundProxy;
final int[] mTmpRange = new int[2];
final int[] mPrevRange = new int[2];
final int[] mTmpRangeExtended = new int[2];
private boolean mAllowScrollHints;
private int mScrollHint = ViewCallback.HINT_SCROLL_NONE;
private int mItemCount = 0;
int mDisplayedGeneration = 0;
int mRequestedGeneration = mDisplayedGeneration;
final private SparseIntArray mMissingPositions = new SparseIntArray();
private void log(String s, Object... args) {
Log.d(TAG, "[MAIN] " + String.format(s, args));
}
/**
* Creates an AsyncListUtil.
*
* @param klass Class of the data item.
* @param tileSize Number of item per chunk loaded at once.
* @param dataCallback Data access callback.
* @param viewCallback Callback for querying visible item range and update notifications.
*/
public AsyncListUtil(Class<T> klass, int tileSize, DataCallback<T> dataCallback,
ViewCallback viewCallback) {
mTClass = klass;
mTileSize = tileSize;
mDataCallback = dataCallback;
mViewCallback = viewCallback;
mTileList = new TileList<T>(mTileSize);
ThreadUtil<T> threadUtil = new MessageThreadUtil<T>();
mMainThreadProxy = threadUtil.getMainThreadProxy(mMainThreadCallback);
mBackgroundProxy = threadUtil.getBackgroundProxy(mBackgroundCallback);
refresh();
}
private boolean isRefreshPending() {
return mRequestedGeneration != mDisplayedGeneration;
}
/**
* Updates the currently visible item range.
*
* <p>
* Identifies the data items that have not been loaded yet and initiates loading them in the
* background. Should be called from the view's scroll listener (such as
* {@link android.support.v7.widget.RecyclerView.OnScrollListener#onScrolled}).
*/
public void onRangeChanged() {
if (isRefreshPending()) {
return; // Will update range will the refresh result arrives.
}
updateRange();
mAllowScrollHints = true;
}
/**
* Forces reloading the data.
* <p>
* Discards all the cached data and reloads all required data items for the currently visible
* range. To be called when the data item count and/or contents has changed.
*/
public void refresh() {
mMissingPositions.clear();
mBackgroundProxy.refresh(++mRequestedGeneration);
}
/**
* Returns the data item at the given position or <code>null</code> if it has not been loaded
* yet.
*
* <p>
* If this method has been called for a specific position and returned <code>null</code>, then
* {@link ViewCallback#onItemLoaded(int)} will be called when it finally loads. Note that if
* this position stays outside of the cached item range (as defined by
* {@link ViewCallback#extendRangeInto} method), then the callback will never be called for
* this position.
*
* @param position Item position.
*
* @return The data item at the given position or <code>null</code> if it has not been loaded
* yet.
*/
public T getItem(int position) {
if (position < 0 || position >= mItemCount) {
throw new IndexOutOfBoundsException(position + " is not within 0 and " + mItemCount);
}
T item = mTileList.getItemAt(position);
if (item == null && !isRefreshPending()) {
mMissingPositions.put(position, 0);
}
return item;
}
/**
* Returns the number of items in the data set.
*
* <p>
* This is the number returned by a recent call to
* {@link DataCallback#refreshData()}.
*
* @return Number of items.
*/
public int getItemCount() {
return mItemCount;
}
private void updateRange() {
mViewCallback.getItemRangeInto(mTmpRange);
if (mTmpRange[0] > mTmpRange[1] || mTmpRange[0] < 0) {
return;
}
if (mTmpRange[1] >= mItemCount) {
// Invalid range may arrive soon after the refresh.
return;
}
if (!mAllowScrollHints) {
mScrollHint = ViewCallback.HINT_SCROLL_NONE;
} else if (mTmpRange[0] > mPrevRange[1] || mPrevRange[0] > mTmpRange[1]) {
// Ranges do not intersect, long leap not a scroll.
mScrollHint = ViewCallback.HINT_SCROLL_NONE;
} else if (mTmpRange[0] < mPrevRange[0]) {
mScrollHint = ViewCallback.HINT_SCROLL_DESC;
} else if (mTmpRange[0] > mPrevRange[0]) {
mScrollHint = ViewCallback.HINT_SCROLL_ASC;
}
mPrevRange[0] = mTmpRange[0];
mPrevRange[1] = mTmpRange[1];
mViewCallback.extendRangeInto(mTmpRange, mTmpRangeExtended, mScrollHint);
mTmpRangeExtended[0] = Math.min(mTmpRange[0], Math.max(mTmpRangeExtended[0], 0));
mTmpRangeExtended[1] =
Math.max(mTmpRange[1], Math.min(mTmpRangeExtended[1], mItemCount - 1));
mBackgroundProxy.updateRange(mTmpRange[0], mTmpRange[1],
mTmpRangeExtended[0], mTmpRangeExtended[1], mScrollHint);
}
private final ThreadUtil.MainThreadCallback<T>
mMainThreadCallback = new ThreadUtil.MainThreadCallback<T>() {
@Override
public void updateItemCount(int generation, int itemCount) {
if (DEBUG) {
log("updateItemCount: size=%d, gen #%d", itemCount, generation);
}
if (!isRequestedGeneration(generation)) {
return;
}
mItemCount = itemCount;
mViewCallback.onDataRefresh();
mDisplayedGeneration = mRequestedGeneration;
recycleAllTiles();
mAllowScrollHints = false; // Will be set to true after a first real scroll.
// There will be no scroll event if the size change does not affect the current range.
updateRange();
}
@Override
public void addTile(int generation, TileList.Tile<T> tile) {
if (!isRequestedGeneration(generation)) {
if (DEBUG) {
log("recycling an older generation tile @%d", tile.mStartPosition);
}
mBackgroundProxy.recycleTile(tile);
return;
}
TileList.Tile<T> duplicate = mTileList.addOrReplace(tile);
if (duplicate != null) {
Log.e(TAG, "duplicate tile @" + duplicate.mStartPosition);
mBackgroundProxy.recycleTile(duplicate);
}
if (DEBUG) {
log("gen #%d, added tile @%d, total tiles: %d",
generation, tile.mStartPosition, mTileList.size());
}
int endPosition = tile.mStartPosition + tile.mItemCount;
int index = 0;
while (index < mMissingPositions.size()) {
final int position = mMissingPositions.keyAt(index);
if (tile.mStartPosition <= position && position < endPosition) {
mMissingPositions.removeAt(index);
mViewCallback.onItemLoaded(position);
} else {
index++;
}
}
}
@Override
public void removeTile(int generation, int position) {
if (!isRequestedGeneration(generation)) {
return;
}
TileList.Tile<T> tile = mTileList.removeAtPos(position);
if (tile == null) {
Log.e(TAG, "tile not found @" + position);
return;
}
if (DEBUG) {
log("recycling tile @%d, total tiles: %d", tile.mStartPosition, mTileList.size());
}
mBackgroundProxy.recycleTile(tile);
}
private void recycleAllTiles() {
if (DEBUG) {
log("recycling all %d tiles", mTileList.size());
}
for (int i = 0; i < mTileList.size(); i++) {
mBackgroundProxy.recycleTile(mTileList.getAtIndex(i));
}
mTileList.clear();
}
private boolean isRequestedGeneration(int generation) {
return generation == mRequestedGeneration;
}
};
private final ThreadUtil.BackgroundCallback<T>
mBackgroundCallback = new ThreadUtil.BackgroundCallback<T>() {
private TileList.Tile<T> mRecycledRoot;
final SparseBooleanArray mLoadedTiles = new SparseBooleanArray();
private int mGeneration;
private int mItemCount;
private int mFirstRequiredTileStart;
private int mLastRequiredTileStart;
@Override
public void refresh(int generation) {
mGeneration = generation;
mLoadedTiles.clear();
mItemCount = mDataCallback.refreshData();
mMainThreadProxy.updateItemCount(mGeneration, mItemCount);
}
@Override
public void updateRange(int rangeStart, int rangeEnd, int extRangeStart, int extRangeEnd,
int scrollHint) {
if (DEBUG) {
log("updateRange: %d..%d extended to %d..%d, scroll hint: %d",
rangeStart, rangeEnd, extRangeStart, extRangeEnd, scrollHint);
}
if (rangeStart > rangeEnd) {
return;
}
final int firstVisibleTileStart = getTileStart(rangeStart);
final int lastVisibleTileStart = getTileStart(rangeEnd);
mFirstRequiredTileStart = getTileStart(extRangeStart);
mLastRequiredTileStart = getTileStart(extRangeEnd);
if (DEBUG) {
log("requesting tile range: %d..%d",
mFirstRequiredTileStart, mLastRequiredTileStart);
}
// All pending tile requests are removed by ThreadUtil at this point.
// Re-request all required tiles in the most optimal order.
if (scrollHint == ViewCallback.HINT_SCROLL_DESC) {
requestTiles(mFirstRequiredTileStart, lastVisibleTileStart, scrollHint, true);
requestTiles(lastVisibleTileStart + mTileSize, mLastRequiredTileStart, scrollHint,
false);
} else {
requestTiles(firstVisibleTileStart, mLastRequiredTileStart, scrollHint, false);
requestTiles(mFirstRequiredTileStart, firstVisibleTileStart - mTileSize, scrollHint,
true);
}
}
private int getTileStart(int position) {
return position - position % mTileSize;
}
private void requestTiles(int firstTileStart, int lastTileStart, int scrollHint,
boolean backwards) {
for (int i = firstTileStart; i <= lastTileStart; i += mTileSize) {
int tileStart = backwards ? (lastTileStart + firstTileStart - i) : i;
if (DEBUG) {
log("requesting tile @%d", tileStart);
}
mBackgroundProxy.loadTile(tileStart, scrollHint);
}
}
@Override
public void loadTile(int position, int scrollHint) {
if (isTileLoaded(position)) {
if (DEBUG) {
log("already loaded tile @%d", position);
}
return;
}
TileList.Tile<T> tile = acquireTile();
tile.mStartPosition = position;
tile.mItemCount = Math.min(mTileSize, mItemCount - tile.mStartPosition);
mDataCallback.fillData(tile.mItems, tile.mStartPosition, tile.mItemCount);
flushTileCache(scrollHint);
addTile(tile);
}
@Override
public void recycleTile(TileList.Tile<T> tile) {
if (DEBUG) {
log("recycling tile @%d", tile.mStartPosition);
}
mDataCallback.recycleData(tile.mItems, tile.mItemCount);
tile.mNext = mRecycledRoot;
mRecycledRoot = tile;
}
private TileList.Tile<T> acquireTile() {
if (mRecycledRoot != null) {
TileList.Tile<T> result = mRecycledRoot;
mRecycledRoot = mRecycledRoot.mNext;
return result;
}
return new TileList.Tile<T>(mTClass, mTileSize);
}
private boolean isTileLoaded(int position) {
return mLoadedTiles.get(position);
}
private void addTile(TileList.Tile<T> tile) {
mLoadedTiles.put(tile.mStartPosition, true);
mMainThreadProxy.addTile(mGeneration, tile);
if (DEBUG) {
log("loaded tile @%d, total tiles: %d", tile.mStartPosition, mLoadedTiles.size());
}
}
private void removeTile(int position) {
mLoadedTiles.delete(position);
mMainThreadProxy.removeTile(mGeneration, position);
if (DEBUG) {
log("flushed tile @%d, total tiles: %s", position, mLoadedTiles.size());
}
}
private void flushTileCache(int scrollHint) {
final int cacheSizeLimit = mDataCallback.getMaxCachedTiles();
while (mLoadedTiles.size() >= cacheSizeLimit) {
int firstLoadedTileStart = mLoadedTiles.keyAt(0);
int lastLoadedTileStart = mLoadedTiles.keyAt(mLoadedTiles.size() - 1);
int startMargin = mFirstRequiredTileStart - firstLoadedTileStart;
int endMargin = lastLoadedTileStart - mLastRequiredTileStart;
if (startMargin > 0 && (startMargin >= endMargin ||
(scrollHint == ViewCallback.HINT_SCROLL_ASC))) {
removeTile(firstLoadedTileStart);
} else if (endMargin > 0 && (startMargin < endMargin ||
(scrollHint == ViewCallback.HINT_SCROLL_DESC))){
removeTile(lastLoadedTileStart);
} else {
// Could not flush on either side, bail out.
return;
}
}
}
private void log(String s, Object... args) {
Log.d(TAG, "[BKGR] " + String.format(s, args));
}
};
/**
* The callback that provides data access for {@link AsyncListUtil}.
*
* <p>
* All methods are called on the background thread.
*/
public static abstract class DataCallback<T> {
/**
* Refresh the data set and return the new data item count.
*
* <p>
* If the data is being accessed through {@link android.database.Cursor} this is where
* the new cursor should be created.
*
* @return Data item count.
*/
@WorkerThread
public abstract int refreshData();
/**
* Fill the given tile.
*
* <p>
* The provided tile might be a recycled tile, in which case it will already have objects.
* It is suggested to re-use these objects if possible in your use case.
*
* @param startPosition The start position in the list.
* @param itemCount The data item count.
* @param data The data item array to fill into. Should not be accessed beyond
* <code>itemCount</code>.
*/
@WorkerThread
public abstract void fillData(T[] data, int startPosition, int itemCount);
/**
* Recycle the objects created in {@link #fillData} if necessary.
*
*
* @param data Array of data items. Should not be accessed beyond <code>itemCount</code>.
* @param itemCount The data item count.
*/
@WorkerThread
public void recycleData(T[] data, int itemCount) {
}
/**
* Returns tile cache size limit (in tiles).
*
* <p>
* The actual number of cached tiles will be the maximum of this value and the number of
* tiles that is required to cover the range returned by
* {@link ViewCallback#extendRangeInto(int[], int[], int)}.
* <p>
* For example, if this method returns 10, and the most
* recent call to {@link ViewCallback#extendRangeInto(int[], int[], int)} returned
* {100, 179}, and the tile size is 5, then the maximum number of cached tiles will be 16.
* <p>
* However, if the tile size is 20, then the maximum number of cached tiles will be 10.
* <p>
* The default implementation returns 10.
*
* @return Maximum cache size.
*/
@WorkerThread
public int getMaxCachedTiles() {
return 10;
}
}
/**
* The callback that links {@link AsyncListUtil} with the list view.
*
* <p>
* All methods are called on the main thread.
*/
public static abstract class ViewCallback {
/**
* No scroll direction hint available.
*/
public static final int HINT_SCROLL_NONE = 0;
/**
* Scrolling in descending order (from higher to lower positions in the order of the backing
* storage).
*/
public static final int HINT_SCROLL_DESC = 1;
/**
* Scrolling in ascending order (from lower to higher positions in the order of the backing
* storage).
*/
public static final int HINT_SCROLL_ASC = 2;
/**
* Compute the range of visible item positions.
* <p>
* outRange[0] is the position of the first visible item (in the order of the backing
* storage).
* <p>
* outRange[1] is the position of the last visible item (in the order of the backing
* storage).
* <p>
* Negative positions and positions greater or equal to {@link #getItemCount} are invalid.
* If the returned range contains invalid positions it is ignored (no item will be loaded).
*
* @param outRange The visible item range.
*/
@UiThread
public abstract void getItemRangeInto(int[] outRange);
/**
* Compute a wider range of items that will be loaded for smoother scrolling.
*
* <p>
* If there is no scroll hint, the default implementation extends the visible range by half
* its length in both directions. If there is a scroll hint, the range is extended by
* its full length in the scroll direction, and by half in the other direction.
* <p>
* For example, if <code>range</code> is <code>{100, 200}</code> and <code>scrollHint</code>
* is {@link #HINT_SCROLL_ASC}, then <code>outRange</code> will be <code>{50, 300}</code>.
* <p>
* However, if <code>scrollHint</code> is {@link #HINT_SCROLL_NONE}, then
* <code>outRange</code> will be <code>{50, 250}</code>
*
* @param range Visible item range.
* @param outRange Extended range.
* @param scrollHint The scroll direction hint.
*/
@UiThread
public void extendRangeInto(int[] range, int[] outRange, int scrollHint) {
final int fullRange = range[1] - range[0] + 1;
final int halfRange = fullRange / 2;
outRange[0] = range[0] - (scrollHint == HINT_SCROLL_DESC ? fullRange : halfRange);
outRange[1] = range[1] + (scrollHint == HINT_SCROLL_ASC ? fullRange : halfRange);
}
/**
* Called when the entire data set has changed.
*/
@UiThread
public abstract void onDataRefresh();
/**
* Called when an item at the given position is loaded.
* @param position Item position.
*/
@UiThread
public abstract void onItemLoaded(int position);
}
}
@@ -1,281 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.b44t.messenger.support.util;
import android.os.Handler;
import android.os.Looper;
import android.support.v4.content.ParallelExecutorCompat;
import android.util.Log;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
class MessageThreadUtil<T> implements ThreadUtil<T> {
public MainThreadCallback<T> getMainThreadProxy(final MainThreadCallback<T> callback) {
return new MainThreadCallback<T>() {
final private MessageQueue mQueue = new MessageQueue();
final private Handler mMainThreadHandler = new Handler(Looper.getMainLooper());
private static final int UPDATE_ITEM_COUNT = 1;
private static final int ADD_TILE = 2;
private static final int REMOVE_TILE = 3;
@Override
public void updateItemCount(int generation, int itemCount) {
sendMessage(SyncQueueItem.obtainMessage(UPDATE_ITEM_COUNT, generation, itemCount));
}
@Override
public void addTile(int generation, TileList.Tile<T> tile) {
sendMessage(SyncQueueItem.obtainMessage(ADD_TILE, generation, tile));
}
@Override
public void removeTile(int generation, int position) {
sendMessage(SyncQueueItem.obtainMessage(REMOVE_TILE, generation, position));
}
private void sendMessage(SyncQueueItem msg) {
mQueue.sendMessage(msg);
mMainThreadHandler.post(mMainThreadRunnable);
}
private Runnable mMainThreadRunnable = new Runnable() {
@Override
public void run() {
SyncQueueItem msg = mQueue.next();
while (msg != null) {
switch (msg.what) {
case UPDATE_ITEM_COUNT:
callback.updateItemCount(msg.arg1, msg.arg2);
break;
case ADD_TILE:
//noinspection unchecked
callback.addTile(msg.arg1, (TileList.Tile<T>) msg.data);
break;
case REMOVE_TILE:
callback.removeTile(msg.arg1, msg.arg2);
break;
default:
Log.e("ThreadUtil", "Unsupported message, what=" + msg.what);
}
msg = mQueue.next();
}
}
};
};
}
public BackgroundCallback<T> getBackgroundProxy(final BackgroundCallback<T> callback) {
return new BackgroundCallback<T>() {
final private MessageQueue mQueue = new MessageQueue();
final private Executor mExecutor = ParallelExecutorCompat.getParallelExecutor();
AtomicBoolean mBackgroundRunning = new AtomicBoolean(false);
private static final int REFRESH = 1;
private static final int UPDATE_RANGE = 2;
private static final int LOAD_TILE = 3;
private static final int RECYCLE_TILE = 4;
@Override
public void refresh(int generation) {
sendMessageAtFrontOfQueue(SyncQueueItem.obtainMessage(REFRESH, generation, null));
}
@Override
public void updateRange(int rangeStart, int rangeEnd,
int extRangeStart, int extRangeEnd, int scrollHint) {
sendMessageAtFrontOfQueue(SyncQueueItem.obtainMessage(UPDATE_RANGE,
rangeStart, rangeEnd, extRangeStart, extRangeEnd, scrollHint, null));
}
@Override
public void loadTile(int position, int scrollHint) {
sendMessage(SyncQueueItem.obtainMessage(LOAD_TILE, position, scrollHint));
}
@Override
public void recycleTile(TileList.Tile<T> tile) {
sendMessage(SyncQueueItem.obtainMessage(RECYCLE_TILE, 0, tile));
}
private void sendMessage(SyncQueueItem msg) {
mQueue.sendMessage(msg);
maybeExecuteBackgroundRunnable();
}
private void sendMessageAtFrontOfQueue(SyncQueueItem msg) {
mQueue.sendMessageAtFrontOfQueue(msg);
maybeExecuteBackgroundRunnable();
}
private void maybeExecuteBackgroundRunnable() {
if (mBackgroundRunning.compareAndSet(false, true)) {
mExecutor.execute(mBackgroundRunnable);
}
}
private Runnable mBackgroundRunnable = new Runnable() {
@Override
public void run() {
while (true) {
SyncQueueItem msg = mQueue.next();
if (msg == null) {
break;
}
switch (msg.what) {
case REFRESH:
mQueue.removeMessages(REFRESH);
callback.refresh(msg.arg1);
break;
case UPDATE_RANGE:
mQueue.removeMessages(UPDATE_RANGE);
mQueue.removeMessages(LOAD_TILE);
callback.updateRange(
msg.arg1, msg.arg2, msg.arg3, msg.arg4, msg.arg5);
break;
case LOAD_TILE:
callback.loadTile(msg.arg1, msg.arg2);
break;
case RECYCLE_TILE:
//noinspection unchecked
callback.recycleTile((TileList.Tile<T>) msg.data);
break;
default:
Log.e("ThreadUtil", "Unsupported message, what=" + msg.what);
}
}
mBackgroundRunning.set(false);
}
};
};
}
/**
* Replica of android.os.Message. Unfortunately, cannot use it without a Handler and don't want
* to create a thread just for this component.
*/
static class SyncQueueItem {
private static SyncQueueItem sPool;
private static final Object sPoolLock = new Object();
private SyncQueueItem next;
public int what;
public int arg1;
public int arg2;
public int arg3;
public int arg4;
public int arg5;
public Object data;
void recycle() {
next = null;
what = arg1 = arg2 = arg3 = arg4 = arg5 = 0;
data = null;
synchronized (sPoolLock) {
if (sPool != null) {
next = sPool;
}
sPool = this;
}
}
static SyncQueueItem obtainMessage(int what, int arg1, int arg2, int arg3, int arg4,
int arg5, Object data) {
synchronized (sPoolLock) {
final SyncQueueItem item;
if (sPool == null) {
item = new SyncQueueItem();
} else {
item = sPool;
sPool = sPool.next;
item.next = null;
}
item.what = what;
item.arg1 = arg1;
item.arg2 = arg2;
item.arg3 = arg3;
item.arg4 = arg4;
item.arg5 = arg5;
item.data = data;
return item;
}
}
static SyncQueueItem obtainMessage(int what, int arg1, int arg2) {
return obtainMessage(what, arg1, arg2, 0, 0, 0, null);
}
static SyncQueueItem obtainMessage(int what, int arg1, Object data) {
return obtainMessage(what, arg1, 0, 0, 0, 0, data);
}
}
static class MessageQueue {
private SyncQueueItem mRoot;
synchronized SyncQueueItem next() {
if (mRoot == null) {
return null;
}
final SyncQueueItem next = mRoot;
mRoot = mRoot.next;
return next;
}
synchronized void sendMessageAtFrontOfQueue(SyncQueueItem item) {
item.next = mRoot;
mRoot = item;
}
synchronized void sendMessage(SyncQueueItem item) {
if (mRoot == null) {
mRoot = item;
return;
}
SyncQueueItem last = mRoot;
while (last.next != null) {
last = last.next;
}
last.next = item;
}
synchronized void removeMessages(int what) {
while (mRoot != null && mRoot.what == what) {
SyncQueueItem item = mRoot;
mRoot = mRoot.next;
item.recycle();
}
if (mRoot != null) {
SyncQueueItem prev = mRoot;
SyncQueueItem item = prev.next;
while (item != null) {
SyncQueueItem next = item.next;
if (item.what == what) {
prev.next = next;
item.recycle();
} else {
prev = item;
}
item = next;
}
}
}
}
}
@@ -1,891 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.b44t.messenger.support.util;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
/**
* A Sorted list implementation that can keep items in order and also notify for changes in the
* list
* such that it can be bound to a {@link android.support.v7.widget.RecyclerView.Adapter
* RecyclerView.Adapter}.
* <p>
* It keeps items ordered using the {@link Callback#compare(Object, Object)} method and uses
* binary search to retrieve items. If the sorting criteria of your items may change, make sure you
* call appropriate methods while editing them to avoid data inconsistencies.
* <p>
* You can control the order of items and change notifications via the {@link Callback} parameter.
*/
@SuppressWarnings("unchecked")
public class SortedList<T> {
/**
* Used by {@link #indexOf(Object)} when he item cannot be found in the list.
*/
public static final int INVALID_POSITION = -1;
private static final int MIN_CAPACITY = 10;
private static final int CAPACITY_GROWTH = MIN_CAPACITY;
private static final int INSERTION = 1;
private static final int DELETION = 1 << 1;
private static final int LOOKUP = 1 << 2;
T[] mData;
/**
* A copy of the previous list contents used during the merge phase of addAll.
*/
private T[] mOldData;
private int mOldDataStart;
private int mOldDataSize;
/**
* The size of the valid portion of mData during the merge phase of addAll.
*/
private int mMergedSize;
/**
* The callback instance that controls the behavior of the SortedList and get notified when
* changes happen.
*/
private Callback mCallback;
private BatchedCallback mBatchedCallback;
private int mSize;
private final Class<T> mTClass;
/**
* Creates a new SortedList of type T.
*
* @param klass The class of the contents of the SortedList.
* @param callback The callback that controls the behavior of SortedList.
*/
public SortedList(Class<T> klass, Callback<T> callback) {
this(klass, callback, MIN_CAPACITY);
}
/**
* Creates a new SortedList of type T.
*
* @param klass The class of the contents of the SortedList.
* @param callback The callback that controls the behavior of SortedList.
* @param initialCapacity The initial capacity to hold items.
*/
public SortedList(Class<T> klass, Callback<T> callback, int initialCapacity) {
mTClass = klass;
mData = (T[]) Array.newInstance(klass, initialCapacity);
mCallback = callback;
mSize = 0;
}
/**
* The number of items in the list.
*
* @return The number of items in the list.
*/
public int size() {
return mSize;
}
/**
* Adds the given item to the list. If this is a new item, SortedList calls
* {@link Callback#onInserted(int, int)}.
* <p>
* If the item already exists in the list and its sorting criteria is not changed, it is
* replaced with the existing Item. SortedList uses
* {@link Callback#areItemsTheSame(Object, Object)} to check if two items are the same item
* and uses {@link Callback#areContentsTheSame(Object, Object)} to decide whether it should
* call {@link Callback#onChanged(int, int)} or not. In both cases, it always removes the
* reference to the old item and puts the new item into the backing array even if
* {@link Callback#areContentsTheSame(Object, Object)} returns false.
* <p>
* If the sorting criteria of the item is changed, SortedList won't be able to find
* its duplicate in the list which will result in having a duplicate of the Item in the list.
* If you need to update sorting criteria of an item that already exists in the list,
* use {@link #updateItemAt(int, Object)}. You can find the index of the item using
* {@link #indexOf(Object)} before you update the object.
*
* @param item The item to be added into the list.
*
* @return The index of the newly added item.
* @see {@link Callback#compare(Object, Object)}
* @see {@link Callback#areItemsTheSame(Object, Object)}
* @see {@link Callback#areContentsTheSame(Object, Object)}}
*/
public int add(T item) {
throwIfMerging();
return add(item, true);
}
/**
* Adds the given items to the list. Equivalent to calling {@link SortedList#add} in a loop,
* except the callback events may be in a different order/granularity since addAll can batch
* them for better performance.
* <p>
* If allowed, may modify the input array and even take the ownership over it in order
* to avoid extra memory allocation during sorting and deduplication.
* </p>
* @param items Array of items to be added into the list.
* @param mayModifyInput If true, SortedList is allowed to modify the input.
* @see {@link SortedList#addAll(T[] items)}.
*/
public void addAll(T[] items, boolean mayModifyInput) {
throwIfMerging();
if (items.length == 0) {
return;
}
if (mayModifyInput) {
addAllInternal(items);
} else {
T[] copy = (T[]) Array.newInstance(mTClass, items.length);
System.arraycopy(items, 0, copy, 0, items.length);
addAllInternal(copy);
}
}
/**
* Adds the given items to the list. Does not modify the input.
*
* @see {@link SortedList#addAll(T[] items, boolean mayModifyInput)}
*
* @param items Array of items to be added into the list.
*/
public void addAll(T... items) {
addAll(items, false);
}
/**
* Adds the given items to the list. Does not modify the input.
*
* @see {@link SortedList#addAll(T[] items, boolean mayModifyInput)}
*
* @param items Collection of items to be added into the list.
*/
public void addAll(Collection<T> items) {
T[] copy = (T[]) Array.newInstance(mTClass, items.size());
addAll(items.toArray(copy), true);
}
private void addAllInternal(T[] newItems) {
final boolean forceBatchedUpdates = !(mCallback instanceof BatchedCallback);
if (forceBatchedUpdates) {
beginBatchedUpdates();
}
mOldData = mData;
mOldDataStart = 0;
mOldDataSize = mSize;
Arrays.sort(newItems, mCallback); // Arrays.sort is stable.
final int newSize = deduplicate(newItems);
if (mSize == 0) {
mData = newItems;
mSize = newSize;
mMergedSize = newSize;
mCallback.onInserted(0, newSize);
} else {
merge(newItems, newSize);
}
mOldData = null;
if (forceBatchedUpdates) {
endBatchedUpdates();
}
}
/**
* Remove duplicate items, leaving only the last item from each group of "same" items.
* Move the remaining items to the beginning of the array.
*
* @return Number of deduplicated items at the beginning of the array.
*/
private int deduplicate(T[] items) {
if (items.length == 0) {
throw new IllegalArgumentException("Input array must be non-empty");
}
// Keep track of the range of equal items at the end of the output.
// Start with the range containing just the first item.
int rangeStart = 0;
int rangeEnd = 1;
for (int i = 1; i < items.length; ++i) {
T currentItem = items[i];
int compare = mCallback.compare(items[rangeStart], currentItem);
if (compare > 0) {
throw new IllegalArgumentException("Input must be sorted in ascending order.");
}
if (compare == 0) {
// The range of equal items continues, update it.
final int sameItemPos = findSameItem(currentItem, items, rangeStart, rangeEnd);
if (sameItemPos != INVALID_POSITION) {
// Replace the duplicate item.
items[sameItemPos] = currentItem;
} else {
// Expand the range.
if (rangeEnd != i) { // Avoid redundant copy.
items[rangeEnd] = currentItem;
}
rangeEnd++;
}
} else {
// The range has ended. Reset it to contain just the current item.
if (rangeEnd != i) { // Avoid redundant copy.
items[rangeEnd] = currentItem;
}
rangeStart = rangeEnd++;
}
}
return rangeEnd;
}
private int findSameItem(T item, T[] items, int from, int to) {
for (int pos = from; pos < to; pos++) {
if (mCallback.areItemsTheSame(items[pos], item)) {
return pos;
}
}
return INVALID_POSITION;
}
/**
* This method assumes that newItems are sorted and deduplicated.
*/
private void merge(T[] newData, int newDataSize) {
final int mergedCapacity = mSize + newDataSize + CAPACITY_GROWTH;
mData = (T[]) Array.newInstance(mTClass, mergedCapacity);
mMergedSize = 0;
int newDataStart = 0;
while (mOldDataStart < mOldDataSize || newDataStart < newDataSize) {
if (mOldDataStart == mOldDataSize) {
// No more old items, copy the remaining new items.
int itemCount = newDataSize - newDataStart;
System.arraycopy(newData, newDataStart, mData, mMergedSize, itemCount);
mMergedSize += itemCount;
mSize += itemCount;
mCallback.onInserted(mMergedSize - itemCount, itemCount);
break;
}
if (newDataStart == newDataSize) {
// No more new items, copy the remaining old items.
int itemCount = mOldDataSize - mOldDataStart;
System.arraycopy(mOldData, mOldDataStart, mData, mMergedSize, itemCount);
mMergedSize += itemCount;
break;
}
T oldItem = mOldData[mOldDataStart];
T newItem = newData[newDataStart];
int compare = mCallback.compare(oldItem, newItem);
if (compare > 0) {
// New item is lower, output it.
mData[mMergedSize++] = newItem;
mSize++;
newDataStart++;
mCallback.onInserted(mMergedSize - 1, 1);
} else if (compare == 0 && mCallback.areItemsTheSame(oldItem, newItem)) {
// Items are the same. Output the new item, but consume both.
mData[mMergedSize++] = newItem;
newDataStart++;
mOldDataStart++;
if (!mCallback.areContentsTheSame(oldItem, newItem)) {
mCallback.onChanged(mMergedSize - 1, 1);
}
} else {
// Old item is lower than or equal to (but not the same as the new). Output it.
// New item with the same sort order will be inserted later.
mData[mMergedSize++] = oldItem;
mOldDataStart++;
}
}
}
private void throwIfMerging() {
if (mOldData != null) {
throw new IllegalStateException("Cannot call this method from within addAll");
}
}
/**
* Batches adapter updates that happen between calling this method until calling
* {@link #endBatchedUpdates()}. For example, if you add multiple items in a loop
* and they are placed into consecutive indices, SortedList calls
* {@link Callback#onInserted(int, int)} only once with the proper item count. If an event
* cannot be merged with the previous event, the previous event is dispatched
* to the callback instantly.
* <p>
* After running your data updates, you <b>must</b> call {@link #endBatchedUpdates()}
* which will dispatch any deferred data change event to the current callback.
* <p>
* A sample implementation may look like this:
* <pre>
* mSortedList.beginBatchedUpdates();
* try {
* mSortedList.add(item1)
* mSortedList.add(item2)
* mSortedList.remove(item3)
* ...
* } finally {
* mSortedList.endBatchedUpdates();
* }
* </pre>
* <p>
* Instead of using this method to batch calls, you can use a Callback that extends
* {@link BatchedCallback}. In that case, you must make sure that you are manually calling
* {@link BatchedCallback#dispatchLastEvent()} right after you complete your data changes.
* Failing to do so may create data inconsistencies with the Callback.
* <p>
* If the current Callback in an instance of {@link BatchedCallback}, calling this method
* has no effect.
*/
public void beginBatchedUpdates() {
throwIfMerging();
if (mCallback instanceof BatchedCallback) {
return;
}
if (mBatchedCallback == null) {
mBatchedCallback = new BatchedCallback(mCallback);
}
mCallback = mBatchedCallback;
}
/**
* Ends the update transaction and dispatches any remaining event to the callback.
*/
public void endBatchedUpdates() {
throwIfMerging();
if (mCallback instanceof BatchedCallback) {
((BatchedCallback) mCallback).dispatchLastEvent();
}
if (mCallback == mBatchedCallback) {
mCallback = mBatchedCallback.mWrappedCallback;
}
}
private int add(T item, boolean notify) {
int index = findIndexOf(item, mData, 0, mSize, INSERTION);
if (index == INVALID_POSITION) {
index = 0;
} else if (index < mSize) {
T existing = mData[index];
if (mCallback.areItemsTheSame(existing, item)) {
if (mCallback.areContentsTheSame(existing, item)) {
//no change but still replace the item
mData[index] = item;
return index;
} else {
mData[index] = item;
mCallback.onChanged(index, 1);
return index;
}
}
}
addToData(index, item);
if (notify) {
mCallback.onInserted(index, 1);
}
return index;
}
/**
* Removes the provided item from the list and calls {@link Callback#onRemoved(int, int)}.
*
* @param item The item to be removed from the list.
*
* @return True if item is removed, false if item cannot be found in the list.
*/
public boolean remove(T item) {
throwIfMerging();
return remove(item, true);
}
/**
* Removes the item at the given index and calls {@link Callback#onRemoved(int, int)}.
*
* @param index The index of the item to be removed.
*
* @return The removed item.
*/
public T removeItemAt(int index) {
throwIfMerging();
T item = get(index);
removeItemAtIndex(index, true);
return item;
}
private boolean remove(T item, boolean notify) {
int index = findIndexOf(item, mData, 0, mSize, DELETION);
if (index == INVALID_POSITION) {
return false;
}
removeItemAtIndex(index, notify);
return true;
}
private void removeItemAtIndex(int index, boolean notify) {
System.arraycopy(mData, index + 1, mData, index, mSize - index - 1);
mSize--;
mData[mSize] = null;
if (notify) {
mCallback.onRemoved(index, 1);
}
}
/**
* Updates the item at the given index and calls {@link Callback#onChanged(int, int)} and/or
* {@link Callback#onMoved(int, int)} if necessary.
* <p>
* You can use this method if you need to change an existing Item such that its position in the
* list may change.
* <p>
* If the new object is a different object (<code>get(index) != item</code>) and
* {@link Callback#areContentsTheSame(Object, Object)} returns <code>true</code>, SortedList
* avoids calling {@link Callback#onChanged(int, int)} otherwise it calls
* {@link Callback#onChanged(int, int)}.
* <p>
* If the new position of the item is different than the provided <code>index</code>,
* SortedList
* calls {@link Callback#onMoved(int, int)}.
*
* @param index The index of the item to replace
* @param item The item to replace the item at the given Index.
* @see #add(Object)
*/
public void updateItemAt(int index, T item) {
throwIfMerging();
final T existing = get(index);
// assume changed if the same object is given back
boolean contentsChanged = existing == item || !mCallback.areContentsTheSame(existing, item);
if (existing != item) {
// different items, we can use comparison and may avoid lookup
final int cmp = mCallback.compare(existing, item);
if (cmp == 0) {
mData[index] = item;
if (contentsChanged) {
mCallback.onChanged(index, 1);
}
return;
}
}
if (contentsChanged) {
mCallback.onChanged(index, 1);
}
// TODO this done in 1 pass to avoid shifting twice.
removeItemAtIndex(index, false);
int newIndex = add(item, false);
if (index != newIndex) {
mCallback.onMoved(index, newIndex);
}
}
/**
* This method can be used to recalculate the position of the item at the given index, without
* triggering an {@link Callback#onChanged(int, int)} callback.
* <p>
* If you are editing objects in the list such that their position in the list may change but
* you don't want to trigger an onChange animation, you can use this method to re-position it.
* If the item changes position, SortedList will call {@link Callback#onMoved(int, int)}
* without
* calling {@link Callback#onChanged(int, int)}.
* <p>
* A sample usage may look like:
*
* <pre>
* final int position = mSortedList.indexOf(item);
* item.incrementPriority(); // assume items are sorted by priority
* mSortedList.recalculatePositionOfItemAt(position);
* </pre>
* In the example above, because the sorting criteria of the item has been changed,
* mSortedList.indexOf(item) will not be able to find the item. This is why the code above
* first
* gets the position before editing the item, edits it and informs the SortedList that item
* should be repositioned.
*
* @param index The current index of the Item whose position should be re-calculated.
* @see #updateItemAt(int, Object)
* @see #add(Object)
*/
public void recalculatePositionOfItemAt(int index) {
throwIfMerging();
// TODO can be improved
final T item = get(index);
removeItemAtIndex(index, false);
int newIndex = add(item, false);
if (index != newIndex) {
mCallback.onMoved(index, newIndex);
}
}
/**
* Returns the item at the given index.
*
* @param index The index of the item to retrieve.
*
* @return The item at the given index.
* @throws java.lang.IndexOutOfBoundsException if provided index is negative or larger than the
* size of the list.
*/
public T get(int index) throws IndexOutOfBoundsException {
if (index >= mSize || index < 0) {
throw new IndexOutOfBoundsException("Asked to get item at " + index + " but size is "
+ mSize);
}
if (mOldData != null) {
// The call is made from a callback during addAll execution. The data is split
// between mData and mOldData.
if (index >= mMergedSize) {
return mOldData[index - mMergedSize + mOldDataStart];
}
}
return mData[index];
}
/**
* Returns the position of the provided item.
*
* @param item The item to query for position.
*
* @return The position of the provided item or {@link #INVALID_POSITION} if item is not in the
* list.
*/
public int indexOf(T item) {
if (mOldData != null) {
int index = findIndexOf(item, mData, 0, mMergedSize, LOOKUP);
if (index != INVALID_POSITION) {
return index;
}
index = findIndexOf(item, mOldData, mOldDataStart, mOldDataSize, LOOKUP);
if (index != INVALID_POSITION) {
return index - mOldDataStart + mMergedSize;
}
return INVALID_POSITION;
}
return findIndexOf(item, mData, 0, mSize, LOOKUP);
}
private int findIndexOf(T item, T[] mData, int left, int right, int reason) {
while (left < right) {
final int middle = (left + right) / 2;
T myItem = mData[middle];
final int cmp = mCallback.compare(myItem, item);
if (cmp < 0) {
left = middle + 1;
} else if (cmp == 0) {
if (mCallback.areItemsTheSame(myItem, item)) {
return middle;
} else {
int exact = linearEqualitySearch(item, middle, left, right);
if (reason == INSERTION) {
return exact == INVALID_POSITION ? middle : exact;
} else {
return exact;
}
}
} else {
right = middle;
}
}
return reason == INSERTION ? left : INVALID_POSITION;
}
private int linearEqualitySearch(T item, int middle, int left, int right) {
// go left
for (int next = middle - 1; next >= left; next--) {
T nextItem = mData[next];
int cmp = mCallback.compare(nextItem, item);
if (cmp != 0) {
break;
}
if (mCallback.areItemsTheSame(nextItem, item)) {
return next;
}
}
for (int next = middle + 1; next < right; next++) {
T nextItem = mData[next];
int cmp = mCallback.compare(nextItem, item);
if (cmp != 0) {
break;
}
if (mCallback.areItemsTheSame(nextItem, item)) {
return next;
}
}
return INVALID_POSITION;
}
private void addToData(int index, T item) {
if (index > mSize) {
throw new IndexOutOfBoundsException(
"cannot add item to " + index + " because size is " + mSize);
}
if (mSize == mData.length) {
// we are at the limit enlarge
T[] newData = (T[]) Array.newInstance(mTClass, mData.length + CAPACITY_GROWTH);
System.arraycopy(mData, 0, newData, 0, index);
newData[index] = item;
System.arraycopy(mData, index, newData, index + 1, mSize - index);
mData = newData;
} else {
// just shift, we fit
System.arraycopy(mData, index, mData, index + 1, mSize - index);
mData[index] = item;
}
mSize++;
}
/**
* Removes all items from the SortedList.
*/
public void clear() {
throwIfMerging();
if (mSize == 0) {
return;
}
final int prevSize = mSize;
Arrays.fill(mData, 0, prevSize, null);
mSize = 0;
mCallback.onRemoved(0, prevSize);
}
/**
* The class that controls the behavior of the {@link SortedList}.
* <p>
* It defines how items should be sorted and how duplicates should be handled.
* <p>
* SortedList calls the callback methods on this class to notify changes about the underlying
* data.
*/
public static abstract class Callback<T2> implements Comparator<T2> {
/**
* Similar to {@link java.util.Comparator#compare(Object, Object)}, should compare two and
* return how they should be ordered.
*
* @param o1 The first object to compare.
* @param o2 The second object to compare.
*
* @return a negative integer, zero, or a positive integer as the
* first argument is less than, equal to, or greater than the
* second.
*/
abstract public int compare(T2 o1, T2 o2);
/**
* Called by the SortedList when an item is inserted at the given position.
*
* @param position The position of the new item.
* @param count The number of items that have been added.
*/
abstract public void onInserted(int position, int count);
/**
* Called by the SortedList when an item is removed from the given position.
*
* @param position The position of the item which has been removed.
* @param count The number of items which have been removed.
*/
abstract public void onRemoved(int position, int count);
/**
* Called by the SortedList when an item changes its position in the list.
*
* @param fromPosition The previous position of the item before the move.
* @param toPosition The new position of the item.
*/
abstract public void onMoved(int fromPosition, int toPosition);
/**
* Called by the SortedList when the item at the given position is updated.
*
* @param position The position of the item which has been updated.
* @param count The number of items which has changed.
*/
abstract public void onChanged(int position, int count);
/**
* Called by the SortedList when it wants to check whether two items have the same data
* or not. SortedList uses this information to decide whether it should call
* {@link #onChanged(int, int)} or not.
* <p>
* SortedList uses this method to check equality instead of {@link Object#equals(Object)}
* so
* that you can change its behavior depending on your UI.
* <p>
* For example, if you are using SortedList with a {@link android.support.v7.widget.RecyclerView.Adapter
* RecyclerView.Adapter}, you should
* return whether the items' visual representations are the same or not.
*
* @param oldItem The previous representation of the object.
* @param newItem The new object that replaces the previous one.
*
* @return True if the contents of the items are the same or false if they are different.
*/
abstract public boolean areContentsTheSame(T2 oldItem, T2 newItem);
/**
* Called by the SortedList to decide whether two object represent the same Item or not.
* <p>
* For example, if your items have unique ids, this method should check their equality.
*
* @param item1 The first item to check.
* @param item2 The second item to check.
*
* @return True if the two items represent the same object or false if they are different.
*/
abstract public boolean areItemsTheSame(T2 item1, T2 item2);
}
/**
* A callback implementation that can batch notify events dispatched by the SortedList.
* <p>
* This class can be useful if you want to do multiple operations on a SortedList but don't
* want to dispatch each event one by one, which may result in a performance issue.
* <p>
* For example, if you are going to add multiple items to a SortedList, BatchedCallback call
* convert individual <code>onInserted(index, 1)</code> calls into one
* <code>onInserted(index, N)</code> if items are added into consecutive indices. This change
* can help RecyclerView resolve changes much more easily.
* <p>
* If consecutive changes in the SortedList are not suitable for batching, BatchingCallback
* dispatches them as soon as such case is detected. After your edits on the SortedList is
* complete, you <b>must</b> always call {@link BatchedCallback#dispatchLastEvent()} to flush
* all changes to the Callback.
*/
public static class BatchedCallback<T2> extends Callback<T2> {
private final Callback<T2> mWrappedCallback;
static final int TYPE_NONE = 0;
static final int TYPE_ADD = 1;
static final int TYPE_REMOVE = 2;
static final int TYPE_CHANGE = 3;
static final int TYPE_MOVE = 4;
int mLastEventType = TYPE_NONE;
int mLastEventPosition = -1;
int mLastEventCount = -1;
/**
* Creates a new BatchedCallback that wraps the provided Callback.
*
* @param wrappedCallback The Callback which should received the data change callbacks.
* Other method calls (e.g. {@link #compare(Object, Object)} from
* the SortedList are directly forwarded to this Callback.
*/
public BatchedCallback(Callback<T2> wrappedCallback) {
mWrappedCallback = wrappedCallback;
}
@Override
public int compare(T2 o1, T2 o2) {
return mWrappedCallback.compare(o1, o2);
}
@Override
public void onInserted(int position, int count) {
if (mLastEventType == TYPE_ADD && position >= mLastEventPosition
&& position <= mLastEventPosition + mLastEventCount) {
mLastEventCount += count;
mLastEventPosition = Math.min(position, mLastEventPosition);
return;
}
dispatchLastEvent();
mLastEventPosition = position;
mLastEventCount = count;
mLastEventType = TYPE_ADD;
}
@Override
public void onRemoved(int position, int count) {
if (mLastEventType == TYPE_REMOVE && mLastEventPosition == position) {
mLastEventCount += count;
return;
}
dispatchLastEvent();
mLastEventPosition = position;
mLastEventCount = count;
mLastEventType = TYPE_REMOVE;
}
@Override
public void onMoved(int fromPosition, int toPosition) {
dispatchLastEvent();//moves are not merged
mWrappedCallback.onMoved(fromPosition, toPosition);
}
@Override
public void onChanged(int position, int count) {
if (mLastEventType == TYPE_CHANGE &&
!(position > mLastEventPosition + mLastEventCount
|| position + count < mLastEventPosition)) {
// take potential overlap into account
int previousEnd = mLastEventPosition + mLastEventCount;
mLastEventPosition = Math.min(position, mLastEventPosition);
mLastEventCount = Math.max(previousEnd, position + count) - mLastEventPosition;
return;
}
dispatchLastEvent();
mLastEventPosition = position;
mLastEventCount = count;
mLastEventType = TYPE_CHANGE;
}
@Override
public boolean areContentsTheSame(T2 oldItem, T2 newItem) {
return mWrappedCallback.areContentsTheSame(oldItem, newItem);
}
@Override
public boolean areItemsTheSame(T2 item1, T2 item2) {
return mWrappedCallback.areItemsTheSame(item1, item2);
}
/**
* This method dispatches any pending event notifications to the wrapped Callback.
* You <b>must</b> always call this method after you are done with editing the SortedList.
*/
public void dispatchLastEvent() {
if (mLastEventType == TYPE_NONE) {
return;
}
switch (mLastEventType) {
case TYPE_ADD:
mWrappedCallback.onInserted(mLastEventPosition, mLastEventCount);
break;
case TYPE_REMOVE:
mWrappedCallback.onRemoved(mLastEventPosition, mLastEventCount);
break;
case TYPE_CHANGE:
mWrappedCallback.onChanged(mLastEventPosition, mLastEventCount);
break;
}
mLastEventType = TYPE_NONE;
}
}
}
@@ -1,45 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.b44t.messenger.support.util;
interface ThreadUtil<T> {
interface MainThreadCallback<T> {
void updateItemCount(int generation, int itemCount);
void addTile(int generation, TileList.Tile<T> tile);
void removeTile(int generation, int position);
}
interface BackgroundCallback<T> {
void refresh(int generation);
void updateRange(int rangeStart, int rangeEnd, int extRangeStart, int extRangeEnd,
int scrollHint);
void loadTile(int position, int scrollHint);
void recycleTile(TileList.Tile<T> tile);
}
MainThreadCallback<T> getMainThreadProxy(MainThreadCallback<T> callback);
BackgroundCallback<T> getBackgroundProxy(BackgroundCallback<T> callback);
}
@@ -1,105 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.b44t.messenger.support.util;
import android.util.SparseArray;
import java.lang.reflect.Array;
/**
* A sparse collection of tiles sorted for efficient access.
*/
class TileList<T> {
final int mTileSize;
// Keyed by start position.
private final SparseArray<Tile<T>> mTiles = new SparseArray<Tile<T>>(10);
Tile<T> mLastAccessedTile;
public TileList(int tileSize) {
mTileSize = tileSize;
}
public T getItemAt(int pos) {
if (mLastAccessedTile == null || !mLastAccessedTile.containsPosition(pos)) {
final int startPosition = pos - (pos % mTileSize);
final int index = mTiles.indexOfKey(startPosition);
if (index < 0) {
return null;
}
mLastAccessedTile = mTiles.valueAt(index);
}
return mLastAccessedTile.getByPosition(pos);
}
public int size() {
return mTiles.size();
}
public void clear() {
mTiles.clear();
}
public Tile<T> getAtIndex(int index) {
return mTiles.valueAt(index);
}
public Tile<T> addOrReplace(Tile<T> newTile) {
final int index = mTiles.indexOfKey(newTile.mStartPosition);
if (index < 0) {
mTiles.put(newTile.mStartPosition, newTile);
return null;
}
Tile<T> oldTile = mTiles.valueAt(index);
mTiles.setValueAt(index, newTile);
if (mLastAccessedTile == oldTile) {
mLastAccessedTile = newTile;
}
return oldTile;
}
public Tile<T> removeAtPos(int startPosition) {
Tile<T> tile = mTiles.get(startPosition);
if (mLastAccessedTile == tile) {
mLastAccessedTile = null;
}
mTiles.delete(startPosition);
return tile;
}
public static class Tile<T> {
public final T[] mItems;
public int mStartPosition;
public int mItemCount;
Tile<T> mNext; // Used only for pooling recycled tiles.
public Tile(Class<T> klass, int size) {
//noinspection unchecked
mItems = (T[]) Array.newInstance(klass, size);
}
boolean containsPosition(int pos) {
return mStartPosition <= pos && pos < mStartPosition + mItemCount;
}
T getByPosition(int pos) {
return mItems[pos - mStartPosition];
}
}
}
@@ -1890,7 +1890,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements
*/
static class LayoutState {
final static String TAG = "LinearLayoutManager#LayoutState";
final static String TAG = "LinLayMngr#LayoutState";
final static int LAYOUT_START = -1;
@@ -1,460 +0,0 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.b44t.messenger.support.widget;
import java.util.ArrayList;
/**
* Like a SparseArray, but with the ability to offset key ranges for bulk insertions/deletions.
*/
class PositionMap<E> implements Cloneable {
private static final Object DELETED = new Object();
private boolean mGarbage = false;
private int[] mKeys;
private Object[] mValues;
private int mSize;
/**
* Creates a new SparseArray containing no mappings.
*/
public PositionMap() {
this(10);
}
/**
* Creates a new PositionMap containing no mappings that will not
* require any additional memory allocation to store the specified
* number of mappings. If you supply an initial capacity of 0, the
* sparse array will be initialized with a light-weight representation
* not requiring any additional array allocations.
*/
public PositionMap(int initialCapacity) {
if (initialCapacity == 0) {
mKeys = ContainerHelpers.EMPTY_INTS;
mValues = ContainerHelpers.EMPTY_OBJECTS;
} else {
initialCapacity = idealIntArraySize(initialCapacity);
mKeys = new int[initialCapacity];
mValues = new Object[initialCapacity];
}
mSize = 0;
}
@Override
@SuppressWarnings("unchecked")
public PositionMap<E> clone() {
PositionMap<E> clone = null;
try {
clone = (PositionMap<E>) super.clone();
clone.mKeys = mKeys.clone();
clone.mValues = mValues.clone();
} catch (CloneNotSupportedException cnse) {
/* ignore */
}
return clone;
}
/**
* Gets the Object mapped from the specified key, or <code>null</code>
* if no such mapping has been made.
*/
public E get(int key) {
return get(key, null);
}
/**
* Gets the Object mapped from the specified key, or the specified Object
* if no such mapping has been made.
*/
@SuppressWarnings("unchecked")
public E get(int key, E valueIfKeyNotFound) {
int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
if (i < 0 || mValues[i] == DELETED) {
return valueIfKeyNotFound;
} else {
return (E) mValues[i];
}
}
/**
* Removes the mapping from the specified key, if there was any.
*/
public void delete(int key) {
int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
if (i >= 0) {
if (mValues[i] != DELETED) {
mValues[i] = DELETED;
mGarbage = true;
}
}
}
/**
* Alias for {@link #delete(int)}.
*/
public void remove(int key) {
delete(key);
}
/**
* Removes the mapping at the specified index.
*/
public void removeAt(int index) {
if (mValues[index] != DELETED) {
mValues[index] = DELETED;
mGarbage = true;
}
}
/**
* Remove a range of mappings as a batch.
*
* @param index Index to begin at
* @param size Number of mappings to remove
*/
public void removeAtRange(int index, int size) {
final int end = Math.min(mSize, index + size);
for (int i = index; i < end; i++) {
removeAt(i);
}
}
public void insertKeyRange(int keyStart, int count) {
}
public void removeKeyRange(ArrayList<E> removedItems, int keyStart, int count) {
}
private void gc() {
// Log.e("SparseArray", "gc start with " + mSize);
int n = mSize;
int o = 0;
int[] keys = mKeys;
Object[] values = mValues;
for (int i = 0; i < n; i++) {
Object val = values[i];
if (val != DELETED) {
if (i != o) {
keys[o] = keys[i];
values[o] = val;
values[i] = null;
}
o++;
}
}
mGarbage = false;
mSize = o;
// Log.e("SparseArray", "gc end with " + mSize);
}
/**
* Adds a mapping from the specified key to the specified value,
* replacing the previous mapping from the specified key if there
* was one.
*/
public void put(int key, E value) {
int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
if (i >= 0) {
mValues[i] = value;
} else {
i = ~i;
if (i < mSize && mValues[i] == DELETED) {
mKeys[i] = key;
mValues[i] = value;
return;
}
if (mGarbage && mSize >= mKeys.length) {
gc();
// Search again because indices may have changed.
i = ~ContainerHelpers.binarySearch(mKeys, mSize, key);
}
if (mSize >= mKeys.length) {
int n = idealIntArraySize(mSize + 1);
int[] nkeys = new int[n];
Object[] nvalues = new Object[n];
// Log.e("SparseArray", "grow " + mKeys.length + " to " + n);
System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
mKeys = nkeys;
mValues = nvalues;
}
if (mSize - i != 0) {
// Log.e("SparseArray", "move " + (mSize - i));
System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
}
mKeys[i] = key;
mValues[i] = value;
mSize++;
}
}
/**
* Returns the number of key-value mappings that this SparseArray
* currently stores.
*/
public int size() {
if (mGarbage) {
gc();
}
return mSize;
}
/**
* Given an index in the range <code>0...size()-1</code>, returns
* the key from the <code>index</code>th key-value mapping that this
* SparseArray stores.
*/
public int keyAt(int index) {
if (mGarbage) {
gc();
}
return mKeys[index];
}
/**
* Given an index in the range <code>0...size()-1</code>, returns
* the value from the <code>index</code>th key-value mapping that this
* SparseArray stores.
*/
@SuppressWarnings("unchecked")
public E valueAt(int index) {
if (mGarbage) {
gc();
}
return (E) mValues[index];
}
/**
* Given an index in the range <code>0...size()-1</code>, sets a new
* value for the <code>index</code>th key-value mapping that this
* SparseArray stores.
*/
public void setValueAt(int index, E value) {
if (mGarbage) {
gc();
}
mValues[index] = value;
}
/**
* Returns the index for which {@link #keyAt} would return the
* specified key, or a negative number if the specified
* key is not mapped.
*/
public int indexOfKey(int key) {
if (mGarbage) {
gc();
}
return ContainerHelpers.binarySearch(mKeys, mSize, key);
}
/**
* Returns an index for which {@link #valueAt} would return the
* specified key, or a negative number if no keys map to the
* specified value.
* <p>Beware that this is a linear search, unlike lookups by key,
* and that multiple keys can map to the same value and this will
* find only one of them.
* <p>Note also that unlike most collections' {@code indexOf} methods,
* this method compares values using {@code ==} rather than {@code equals}.
*/
public int indexOfValue(E value) {
if (mGarbage) {
gc();
}
for (int i = 0; i < mSize; i++)
if (mValues[i] == value)
return i;
return -1;
}
/**
* Removes all key-value mappings from this SparseArray.
*/
public void clear() {
int n = mSize;
Object[] values = mValues;
for (int i = 0; i < n; i++) {
values[i] = null;
}
mSize = 0;
mGarbage = false;
}
/**
* Puts a key/value pair into the array, optimizing for the case where
* the key is greater than all existing keys in the array.
*/
public void append(int key, E value) {
if (mSize != 0 && key <= mKeys[mSize - 1]) {
put(key, value);
return;
}
if (mGarbage && mSize >= mKeys.length) {
gc();
}
int pos = mSize;
if (pos >= mKeys.length) {
int n = idealIntArraySize(pos + 1);
int[] nkeys = new int[n];
Object[] nvalues = new Object[n];
// Log.e("SparseArray", "grow " + mKeys.length + " to " + n);
System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
mKeys = nkeys;
mValues = nvalues;
}
mKeys[pos] = key;
mValues[pos] = value;
mSize = pos + 1;
}
/**
* {@inheritDoc}
*
* <p>This implementation composes a string by iterating over its mappings. If
* this map contains itself as a value, the string "(this Map)"
* will appear in its place.
*/
@Override
public String toString() {
if (size() <= 0) {
return "{}";
}
StringBuilder buffer = new StringBuilder(mSize * 28);
buffer.append('{');
for (int i=0; i<mSize; i++) {
if (i > 0) {
buffer.append(", ");
}
int key = keyAt(i);
buffer.append(key);
buffer.append('=');
Object value = valueAt(i);
if (value != this) {
buffer.append(value);
} else {
buffer.append("(this Map)");
}
}
buffer.append('}');
return buffer.toString();
}
static int idealByteArraySize(int need) {
for (int i = 4; i < 32; i++)
if (need <= (1 << i) - 12)
return (1 << i) - 12;
return need;
}
static int idealBooleanArraySize(int need) {
return idealByteArraySize(need);
}
static int idealShortArraySize(int need) {
return idealByteArraySize(need * 2) / 2;
}
static int idealCharArraySize(int need) {
return idealByteArraySize(need * 2) / 2;
}
static int idealIntArraySize(int need) {
return idealByteArraySize(need * 4) / 4;
}
static int idealFloatArraySize(int need) {
return idealByteArraySize(need * 4) / 4;
}
static int idealObjectArraySize(int need) {
return idealByteArraySize(need * 4) / 4;
}
static int idealLongArraySize(int need) {
return idealByteArraySize(need * 8) / 8;
}
static class ContainerHelpers {
static final boolean[] EMPTY_BOOLEANS = new boolean[0];
static final int[] EMPTY_INTS = new int[0];
static final long[] EMPTY_LONGS = new long[0];
static final Object[] EMPTY_OBJECTS = new Object[0];
// This is Arrays.binarySearch(), but doesn't do any argument validation.
static int binarySearch(int[] array, int size, int value) {
int lo = 0;
int hi = size - 1;
while (lo <= hi) {
final int mid = (lo + hi) >>> 1;
final int midVal = array[mid];
if (midVal < value) {
lo = mid + 1;
} else if (midVal > value) {
hi = mid - 1;
} else {
return mid; // value found
}
}
return ~lo; // value not present
}
}
}
@@ -7538,6 +7538,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro
resultMode = MeasureSpec.AT_MOST;
}
}
//noinspection WrongConstant
return MeasureSpec.makeMeasureSpec(resultSize, resultMode);
}
@@ -1,59 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.b44t.messenger.support.widget.util;
import com.b44t.messenger.support.util.SortedList;
import com.b44t.messenger.support.widget.RecyclerView;
/**
* A {@link SortedList.Callback} implementation that can bind a {@link SortedList} to a
* {@link RecyclerView.Adapter}.
*/
public abstract class SortedListAdapterCallback<T2> extends SortedList.Callback<T2> {
final RecyclerView.Adapter mAdapter;
/**
* Creates a {@link SortedList.Callback} that will forward data change events to the provided
* Adapter.
*
* @param adapter The Adapter instance which should receive events from the SortedList.
*/
public SortedListAdapterCallback(RecyclerView.Adapter adapter) {
mAdapter = adapter;
}
@Override
public void onInserted(int position, int count) {
mAdapter.notifyItemRangeInserted(position, count);
}
@Override
public void onRemoved(int position, int count) {
mAdapter.notifyItemRangeRemoved(position, count);
}
@Override
public void onMoved(int fromPosition, int toPosition) {
mAdapter.notifyItemMoved(fromPosition, toPosition);
}
@Override
public void onChanged(int position, int count) {
mAdapter.notifyItemRangeChanged(position, count);
}
}
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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.video;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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.video;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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.video;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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.video;
@@ -1,8 +1,8 @@
/*******************************************************************************
*
* Messenger Android Frontend
* Copyright (C) 2016 Björn Petersen Software Design and Development
* Contact: r10s@b44t.com, http://b44t.com
* (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
@@ -20,7 +20,6 @@
*******************************************************************************
*
* File: MrAccoutSettingsActivity.java
* Authors: Björn Petersen
* Purpose: Let the user configure his name
*
******************************************************************************/
@@ -41,9 +40,7 @@ import android.widget.ListView;
import android.widget.Toast;
import com.b44t.messenger.AndroidUtilities;
import com.b44t.messenger.ContactsController;
import com.b44t.messenger.LocaleController;
import com.b44t.messenger.MessagesController;
import com.b44t.messenger.MrMailbox;
import com.b44t.messenger.NotificationCenter;
import com.b44t.messenger.R;
@@ -53,7 +50,7 @@ import com.b44t.ui.ActionBar.ActionBarMenu;
import com.b44t.ui.ActionBar.BaseFragment;
import com.b44t.ui.Adapters.BaseFragmentAdapter;
import com.b44t.ui.Cells.HeaderCell;
import com.b44t.ui.Cells.MrEditTextCell;
import com.b44t.ui.Cells.EditTextCell;
import com.b44t.ui.Cells.ShadowSectionCell;
import com.b44t.ui.Cells.TextInfoPrivacyCell;
import com.b44t.ui.Components.LayoutHelper;
@@ -88,15 +85,15 @@ public class AccountSettingsActivity extends BaseFragment implements Notificatio
private final int typeShadowSection = 2;
private final int typeSection = 3;
MrEditTextCell addrCell; // warning all these objects may be null!
MrEditTextCell mailPwCell;
MrEditTextCell mailServerCell;
MrEditTextCell mailPortCell;
MrEditTextCell mailUserCell;
MrEditTextCell sendPwCell;
MrEditTextCell sendServerCell;
MrEditTextCell sendPortCell;
MrEditTextCell sendUserCell;
EditTextCell addrCell; // warning all these objects may be null!
EditTextCell mailPwCell;
EditTextCell mailServerCell;
EditTextCell mailPortCell;
EditTextCell mailUserCell;
EditTextCell sendPwCell;
EditTextCell sendServerCell;
EditTextCell sendPortCell;
EditTextCell sendUserCell;
// misc.
private View doneButton;
@@ -312,7 +309,11 @@ public class AccountSettingsActivity extends BaseFragment implements Notificatio
NotificationCenter.getInstance().postNotificationName(NotificationCenter.mainUserInfoChanged);
}
else {
Toast.makeText(getParentActivity(), LocaleController.getString("CannotConnect", R.string.CannotConnect), Toast.LENGTH_LONG).show();
String err = MrMailbox.getErrorDescr();
if( err.isEmpty() ) {
err = LocaleController.getString("CannotConnect", R.string.CannotConnect);
}
Toast.makeText(getParentActivity(), err, Toast.LENGTH_LONG).show();
}
}
}
@@ -388,7 +389,7 @@ public class AccountSettingsActivity extends BaseFragment implements Notificatio
if (type == typeTextEntry) {
if (i == rowAddr) {
if( addrCell==null) {
addrCell = new MrEditTextCell(mContext);
addrCell = new EditTextCell(mContext);
addrCell.setValueHintAndLabel(MrMailbox.getConfig("addr", ""),
"", LocaleController.getString("MyEmailAddress", R.string.MyEmailAddress), false);
addrCell.getEditTextView().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
@@ -397,7 +398,7 @@ public class AccountSettingsActivity extends BaseFragment implements Notificatio
}
else if (i == rowMailPw) {
if( mailPwCell==null) {
mailPwCell = new MrEditTextCell(mContext);
mailPwCell = new EditTextCell(mContext);
mailPwCell.setValueHintAndLabel(MrMailbox.getConfig("mail_pw", ""),
"", LocaleController.getString("Password", R.string.Password), false);
mailPwCell.getEditTextView().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_VARIATION_PASSWORD);
@@ -406,7 +407,7 @@ public class AccountSettingsActivity extends BaseFragment implements Notificatio
}
else if (i == rowMailServer) {
if( mailServerCell==null) {
mailServerCell = new MrEditTextCell(mContext);
mailServerCell = new EditTextCell(mContext);
mailServerCell.setValueHintAndLabel(MrMailbox.getConfig("mail_server", ""),
LocaleController.getString("Automatic", R.string.Automatic), LocaleController.getString("ImapServer", R.string.ImapServer), false);
}
@@ -414,7 +415,7 @@ public class AccountSettingsActivity extends BaseFragment implements Notificatio
}
else if (i == rowMailPort) {
if( mailPortCell==null) {
mailPortCell = new MrEditTextCell(mContext);
mailPortCell = new EditTextCell(mContext);
mailPortCell.setValueHintAndLabel(MrMailbox.getConfig("mail_port", ""),
LocaleController.getString("Default", R.string.Default), LocaleController.getString("ImapPort", R.string.ImapPort), false);
}
@@ -422,7 +423,7 @@ public class AccountSettingsActivity extends BaseFragment implements Notificatio
}
else if (i == rowMailUser) {
if( mailUserCell==null) {
mailUserCell = new MrEditTextCell(mContext);
mailUserCell = new EditTextCell(mContext);
mailUserCell.setValueHintAndLabel(MrMailbox.getConfig("mail_user", ""),
LocaleController.getString("FromAbove", R.string.FromAbove), LocaleController.getString("ImapLoginname", R.string.ImapLoginname), false);
}
@@ -430,7 +431,7 @@ public class AccountSettingsActivity extends BaseFragment implements Notificatio
}
else if (i == rowSendServer) {
if( sendServerCell==null) {
sendServerCell = new MrEditTextCell(mContext);
sendServerCell = new EditTextCell(mContext);
sendServerCell.setValueHintAndLabel(MrMailbox.getConfig("send_server", ""),
LocaleController.getString("Automatic", R.string.Automatic), LocaleController.getString("SmtpServer", R.string.SmtpServer), false);
}
@@ -438,7 +439,7 @@ public class AccountSettingsActivity extends BaseFragment implements Notificatio
}
else if (i == rowSendPort) {
if( sendPortCell==null) {
sendPortCell = new MrEditTextCell(mContext);
sendPortCell = new EditTextCell(mContext);
sendPortCell.setValueHintAndLabel(MrMailbox.getConfig("send_port", ""),
LocaleController.getString("Default", R.string.Default), LocaleController.getString("SmtpPort", R.string.SmtpPort), false);
}
@@ -446,7 +447,7 @@ public class AccountSettingsActivity extends BaseFragment implements Notificatio
}
else if (i == rowSendUser) {
if( sendUserCell==null) {
sendUserCell = new MrEditTextCell(mContext);
sendUserCell = new EditTextCell(mContext);
sendUserCell.setValueHintAndLabel(MrMailbox.getConfig("send_user", ""),
LocaleController.getString("FromAbove", R.string.FromAbove), LocaleController.getString("SmtpLoginname", R.string.SmtpLoginname), false);
}
@@ -454,7 +455,7 @@ public class AccountSettingsActivity extends BaseFragment implements Notificatio
}
else if (i == rowSendPw) {
if( sendPwCell==null) {
sendPwCell = new MrEditTextCell(mContext);
sendPwCell = new EditTextCell(mContext);
sendPwCell.setValueHintAndLabel(MrMailbox.getConfig("send_pw", ""),
LocaleController.getString("FromAbove", R.string.FromAbove), LocaleController.getString("SmtpPassword", R.string.SmtpPassword), false);
sendPwCell.getEditTextView().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_VARIATION_PASSWORD);
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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.ui.ActionBar;
@@ -43,14 +58,13 @@ public class ActionBar extends FrameLayout {
private ImageView backButtonImageView;
private SimpleTextView titleTextView;
private SimpleTextView subtitleTextView;
private View actionModeTop;
//private View actionModeTop;
private ActionBarMenu menu;
private ActionBarMenu actionMode;
private boolean occupyStatusBar = Build.VERSION.SDK_INT >= 21;
private boolean actionModeVisible;
private boolean addToContainer = true;
private boolean interceptTouches = true;
private int extraHeight;
private AnimatorSet actionModeAnimation;
private boolean allowOverlayTitle;
@@ -194,7 +208,7 @@ public class ActionBar extends FrameLayout {
return actionMode;
}
actionMode = new ActionBarMenu(getContext(), this);
actionMode.setBackgroundColor(0xffffffff);
actionMode.setBackgroundColor(0xfff8f8f8);
addView(actionMode, indexOfChild(backButtonImageView));
actionMode.setPadding(0, occupyStatusBar ? AndroidUtilities.statusBarHeight : 0, 0, 0);
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams)actionMode.getLayoutParams();
@@ -204,6 +218,7 @@ public class ActionBar extends FrameLayout {
actionMode.setLayoutParams(layoutParams);
actionMode.setVisibility(INVISIBLE);
/*
if (occupyStatusBar && actionModeTop == null) {
actionModeTop = new View(getContext());
actionModeTop.setBackgroundColor(0x99000000);
@@ -215,6 +230,7 @@ public class ActionBar extends FrameLayout {
actionModeTop.setLayoutParams(layoutParams);
actionModeTop.setVisibility(INVISIBLE);
}
*/
return actionMode;
}
@@ -226,9 +242,9 @@ public class ActionBar extends FrameLayout {
actionModeVisible = true;
ArrayList<Animator> animators = new ArrayList<>();
animators.add(ObjectAnimator.ofFloat(actionMode, "alpha", 0.0f, 1.0f));
if (occupyStatusBar && actionModeTop != null) {
/*if (occupyStatusBar && actionModeTop != null) {
animators.add(ObjectAnimator.ofFloat(actionModeTop, "alpha", 0.0f, 1.0f));
}
}*/
if (actionModeAnimation != null) {
actionModeAnimation.cancel();
}
@@ -239,9 +255,9 @@ public class ActionBar extends FrameLayout {
@Override
public void onAnimationStart(Animator animation) {
actionMode.setVisibility(VISIBLE);
if (occupyStatusBar && actionModeTop != null) {
/*if (occupyStatusBar && actionModeTop != null) {
actionModeTop.setVisibility(VISIBLE);
}
}*/
}
@Override
@@ -284,9 +300,9 @@ public class ActionBar extends FrameLayout {
actionModeVisible = false;
ArrayList<Animator> animators = new ArrayList<>();
animators.add(ObjectAnimator.ofFloat(actionMode, "alpha", 0.0f));
if (occupyStatusBar && actionModeTop != null) {
/*if (occupyStatusBar && actionModeTop != null) {
animators.add(ObjectAnimator.ofFloat(actionModeTop, "alpha", 0.0f));
}
}*/
if (actionModeAnimation != null) {
actionModeAnimation.cancel();
}
@@ -299,9 +315,9 @@ public class ActionBar extends FrameLayout {
if (actionModeAnimation != null && actionModeAnimation.equals(animation)) {
actionModeAnimation = null;
actionMode.setVisibility(INVISIBLE);
if (occupyStatusBar && actionModeTop != null) {
/*if (occupyStatusBar && actionModeTop != null) {
actionModeTop.setVisibility(INVISIBLE);
}
}*/
}
}
@@ -331,6 +347,7 @@ public class ActionBar extends FrameLayout {
}
}
/*
public void showActionModeTop() {
if (occupyStatusBar && actionModeTop == null) {
actionModeTop = new View(getContext());
@@ -343,6 +360,7 @@ public class ActionBar extends FrameLayout {
actionModeTop.setLayoutParams(layoutParams);
}
}
*/
public boolean isActionModeShowed() {
return actionMode != null && actionModeVisible;
@@ -366,10 +384,6 @@ public class ActionBar extends FrameLayout {
interceptTouches = value;
}
public void setExtraHeight(int value) {
extraHeight = value;
}
public void closeSearchField() {
if (!isSearchFieldVisible || menu == null) {
return;
@@ -391,7 +405,7 @@ public class ActionBar extends FrameLayout {
int actionBarHeight = getCurrentActionBarHeight();
int actionBarHeightSpec = MeasureSpec.makeMeasureSpec(actionBarHeight, MeasureSpec.EXACTLY);
setMeasuredDimension(width, actionBarHeight + (occupyStatusBar ? AndroidUtilities.statusBarHeight : 0) + extraHeight);
setMeasuredDimension(width, actionBarHeight + (occupyStatusBar ? AndroidUtilities.statusBarHeight : 0));
int textLeft;
if (backButtonImageView != null && backButtonImageView.getVisibility() != GONE) {
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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.ui.ActionBar;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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.ui.ActionBar;
@@ -31,6 +46,7 @@ public class ActionBarMenu extends LinearLayout {
super(context);
}
/*
public View addItemResource(int id, int resourceId) {
LayoutInflater li = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = li.inflate(resourceId, null);
@@ -48,6 +64,7 @@ public class ActionBarMenu extends LinearLayout {
});
return view;
}
*/
public ActionBarMenuItem addItem(int id, Drawable drawable) { /* */
return addItem(id, 0, parentActionBar.itemsBackgroundColor, drawable, AndroidUtilities.dp(48));
@@ -129,10 +146,10 @@ public class ActionBarMenu extends LinearLayout {
if (item.hasSubMenu()) {
item.toggleSubMenu();
break;
} else if (item.overrideMenuClick) {
} /*else if (item.overrideMenuClick) {
onItemClick((Integer) item.getTag());
break;
}
}*/
}
}
}
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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.ui.ActionBar;
@@ -55,6 +70,12 @@ public class ActionBarMenuItem extends FrameLayout {
public void onSearchPressed(EditText editText) {
}
public void onUpPressed() {
}
public void onDownPressed() {
}
}
public interface ActionBarMenuItemDelegate {
@@ -65,21 +86,23 @@ public class ActionBarMenuItem extends FrameLayout {
private ActionBarMenu parentMenu;
private ActionBarPopupWindow popupWindow;
private EditText searchField;
private ImageView clearButton;
private ImageView searchUpButton;
private ImageView searchDownButton;
private SimpleTextView searchCountText;
protected ImageView iconView;
private FrameLayout searchContainer;
private LinearLayout searchContainer;
private boolean isSearchField = false;
private ActionBarMenuItemSearchListener listener;
private Rect rect;
private int[] location;
private View selectedMenuView;
private Runnable showMenuRunnable;
private boolean showFromBottom;
//private boolean showFromBottom;
private int menuHeight = AndroidUtilities.dp(16);
private int subMenuOpenSide = 0;
private ActionBarMenuItemDelegate delegate;
private boolean allowCloseAnimation = true;
protected boolean overrideMenuClick;
//protected boolean overrideMenuClick;
private boolean processedPopupClick;
public ActionBarMenuItem(Context context, ActionBarMenu menu, int backgroundColor) {
@@ -179,12 +202,14 @@ public class ActionBarMenuItem extends FrameLayout {
this.delegate = delegate;
}
public void setShowFromBottom(boolean value) { /* */
/*
public void setShowFromBottom(boolean value) {
showFromBottom = value;
if (popupLayout != null) {
popupLayout.setShowedFromBotton(showFromBottom);
}
}
*/
public void setSubMenuOpenSide(int side) {
subMenuOpenSide = side;
@@ -239,7 +264,7 @@ public class ActionBarMenuItem extends FrameLayout {
textView.setCompoundDrawablesWithIntrinsicBounds(null, null, getResources().getDrawable(icon), null);
}
}
popupLayout.setShowedFromBotton(showFromBottom);
//popupLayout.setShowedFromBotton(showFromBottom);
popupLayout.addView(textView);
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) textView.getLayoutParams();
if (LocaleController.isRTL) {
@@ -296,7 +321,8 @@ public class ActionBarMenuItem extends FrameLayout {
popupWindow.setClippingEnabled(true);
popupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED);
popupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED);
popupLayout.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), MeasureSpec.AT_MOST));
int wh = MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), MeasureSpec.AT_MOST);
popupLayout.measure(wh, wh);
popupWindow.getContentView().setFocusableInTouchMode(true);
popupWindow.getContentView().setOnKeyListener(new OnKeyListener() {
@Override
@@ -374,17 +400,19 @@ public class ActionBarMenuItem extends FrameLayout {
return searchField;
}
/*
public ActionBarMenuItem setOverrideMenuClick(boolean value) {
overrideMenuClick = value;
return this;
}
*/
public ActionBarMenuItem setIsSearchField(boolean value) {
public ActionBarMenuItem setIsSearchField(boolean value, boolean applyHack) {
if (parentMenu == null) {
return this;
}
if (value && searchContainer == null) {
searchContainer = new FrameLayout(getContext());
searchContainer = new LinearLayout(getContext());
parentMenu.addView(searchContainer, 0);
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) searchContainer.getLayoutParams();
layoutParams.weight = 1;
@@ -403,6 +431,7 @@ public class ActionBarMenuItem extends FrameLayout {
searchField.setPadding(0, 0, 0, 0);
int inputType = searchField.getInputType() | EditorInfo.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
searchField.setInputType(inputType);
searchField.setImeOptions(EditorInfo.IME_ACTION_DONE | EditorInfo.IME_FLAG_NO_EXTRACT_UI); // IME_ACTION_SEARCH is confusing as we use a real time search and the search is already performed when the user will hit the "search" button
searchField.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
@@ -443,9 +472,6 @@ public class ActionBarMenuItem extends FrameLayout {
if (listener != null) {
listener.onTextChanged(searchField);
}
if (clearButton != null) {
clearButton.setAlpha(s == null || s.length() == 0 ? 0.6f : 1.0f);
}
}
@Override
@@ -461,38 +487,87 @@ public class ActionBarMenuItem extends FrameLayout {
} catch (Exception e) {
//nothing to do
}
searchField.setImeOptions(EditorInfo.IME_FLAG_NO_FULLSCREEN | EditorInfo.IME_ACTION_SEARCH);
searchField.setTextIsSelectable(false);
searchContainer.addView(searchField);
FrameLayout.LayoutParams layoutParams2 = (FrameLayout.LayoutParams) searchField.getLayoutParams();
layoutParams2.width = LayoutHelper.MATCH_PARENT;
layoutParams2.gravity = Gravity.CENTER_VERTICAL;
layoutParams2.height = AndroidUtilities.dp(36);
layoutParams2.rightMargin = AndroidUtilities.dp(48);
searchField.setLayoutParams(layoutParams2);
if( applyHack ) {
searchField.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
// This is a HACK: normally, the soft keyboard should show up automatically whenever the user
// clicks the search input field - however, if the user selected an item in the search and comes back to the search result,
// a click on the search input field does ... nothing.
AndroidUtilities.showKeyboard(v);
// ... maybe re-setting the soft input mode may help, I've not tested this.
// finally, a combinaction of showKeyboard()/hideKeyboard() will show up the keyboard on the next click, too.
//parentMenu.getParent().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
}
}
});
}
clearButton = new ImageView(getContext());
clearButton.setImageResource(R.drawable.ic_close_white);
clearButton.setScaleType(ImageView.ScaleType.CENTER);
clearButton.setOnClickListener(new OnClickListener() {
searchContainer.addView(searchField, LayoutHelper.createLinear(48, 48, 10.0f, Gravity.CENTER_VERTICAL));
searchCountText = new SimpleTextView(getContext());
searchCountText.setTextColor(Theme.ACTION_BAR_SUBTITLE_COLOR);
searchCountText.setTextSize(14);
searchCountText.setText("1/10");
searchCountText.setVisibility(View.GONE);
searchContainer.addView(searchCountText, LayoutHelper.createLinear(48, LayoutHelper.WRAP_CONTENT, Gravity.LEFT|Gravity.CENTER_VERTICAL));
searchUpButton = new ImageView(getContext());
searchUpButton.setImageResource(R.drawable.search_up);
searchUpButton.setScaleType(ImageView.ScaleType.CENTER);
searchContainer.addView(searchUpButton, LayoutHelper.createLinear(48, 48, Gravity.CENTER_VERTICAL));
searchUpButton.setVisibility(View.GONE);
searchUpButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
searchField.setText("");
searchField.requestFocus();
AndroidUtilities.showKeyboard(searchField);
listener.onUpPressed();
}
});
searchDownButton = new ImageView(getContext());
searchDownButton.setImageResource(R.drawable.search_down);
searchDownButton.setScaleType(ImageView.ScaleType.CENTER);
searchContainer.addView(searchDownButton, LayoutHelper.createLinear(48, 48, Gravity.CENTER_VERTICAL));
searchDownButton.setVisibility(View.GONE);
searchDownButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
listener.onDownPressed();
}
});
searchContainer.addView(clearButton);
layoutParams2 = (FrameLayout.LayoutParams) clearButton.getLayoutParams();
layoutParams2.width = AndroidUtilities.dp(48);
layoutParams2.gravity = Gravity.CENTER_VERTICAL | Gravity.RIGHT;
layoutParams2.height = LayoutHelper.MATCH_PARENT;
clearButton.setLayoutParams(layoutParams2);
}
isSearchField = value;
return this;
}
public void setExtraSearchInfo(String text, boolean upDown, boolean enableUp, boolean enableDown)
{
if( searchCountText!=null && searchUpButton!=null && searchDownButton!=null ) {
if( text!=null && !text.isEmpty() ) {
searchCountText.setVisibility(View.VISIBLE);
searchCountText.setText(text);
}
else {
searchCountText.setVisibility(View.GONE);
}
if( upDown ) {
searchUpButton.setVisibility(View.VISIBLE);
searchUpButton.setEnabled(enableUp);
searchUpButton.setAlpha(enableUp ? 1.0f : 0.25f);
searchDownButton.setVisibility(View.VISIBLE);
searchDownButton.setEnabled(enableDown);
searchDownButton.setAlpha(enableDown ? 1.0f : 0.25f);
}
else {
searchUpButton.setVisibility(View.GONE);
searchDownButton.setVisibility(View.GONE);
}
}
}
public boolean isSearchField() {
return isSearchField;
}
@@ -517,16 +592,17 @@ public class ActionBarMenuItem extends FrameLayout {
private void updateOrShowPopup(boolean show, boolean update) {
int offsetY;
if (showFromBottom) {
/*if (showFromBottom) {
getLocationOnScreen(location);
int diff = location[1] - AndroidUtilities.statusBarHeight + getMeasuredHeight() - menuHeight;
offsetY = -menuHeight;
if (diff < 0) {
offsetY -= diff;
}
} else {
} else*/ {
if (parentMenu != null && subMenuOpenSide == 0) {
offsetY = -parentMenu.parentActionBar.getMeasuredHeight() + parentMenu.getTop();
ActionBarMenu pm = parentMenu.parentActionBar.createMenu(); // for normal items, this is identical to parentMenu; for the action bar we take the normal menu as a a reference for the position
offsetY = -pm.parentActionBar.getMeasuredHeight() + pm.getTop();
} else {
offsetY = -getMeasuredHeight();
}
@@ -537,14 +613,14 @@ public class ActionBarMenuItem extends FrameLayout {
}
if (subMenuOpenSide == 0) {
if (showFromBottom) {
/*if (showFromBottom) {
if (show) {
popupWindow.showAsDropDown(this, -popupLayout.getMeasuredWidth() + getMeasuredWidth(), offsetY);
}
if (update) {
popupWindow.update(this, -popupLayout.getMeasuredWidth() + getMeasuredWidth(), offsetY, -1, -1);
}
} else {
} else*/ {
if (parentMenu != null) {
View parent = parentMenu.parentActionBar;
if (show) {
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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/ .
*
******************************************************************************/
//Thanks to https://github.com/JakeWharton/ActionBarSherlock/
@@ -74,7 +89,7 @@ public class ActionBarPopupWindow extends PopupWindow {
private float backScaleY = 1;
private int backAlpha = 255;
private int lastStartedChild = 0;
private boolean showedFromBotton;
//private boolean showedFromBotton;
private HashMap<View, Integer> positions = new HashMap<>();
private ScrollView scrollView;
@@ -108,9 +123,11 @@ public class ActionBarPopupWindow extends PopupWindow {
}
}
/*
public void setShowedFromBotton(boolean value) {
showedFromBotton = value;
}
*/
public void setDispatchKeyEventListener(OnDispatchKeyEventListener listener) {
mOnDispatchKeyEventListener = listener;
@@ -130,16 +147,16 @@ public class ActionBarPopupWindow extends PopupWindow {
invalidate();
}
public void setBackScaleY(float value) {
public void setBackScaleY(float value) { /* AFAIK this and the other "back" functions are used for some animations */
backScaleY = value;
if (animationEnabled) {
int count = getItemsCount();
int visibleCount = 0;
/*int visibleCount = 0;
for (int a = 0; a < count; a++) {
visibleCount += getItemAt(a).getVisibility() == VISIBLE ? 1 : 0;
}
}*/
int height = getMeasuredHeight() - AndroidUtilities.dp(16);
if (showedFromBotton) {
/*if (showedFromBotton) {
for (int a = lastStartedChild; a >= 0; a--) {
View child = getItemAt(a);
if (child.getVisibility() != VISIBLE) {
@@ -152,7 +169,7 @@ public class ActionBarPopupWindow extends PopupWindow {
lastStartedChild = a - 1;
startChildAnimation(child);
}
} else {
} else*/ {
for (int a = lastStartedChild; a < count; a++) {
View child = getItemAt(a);
if (child.getVisibility() != VISIBLE) {
@@ -175,7 +192,7 @@ public class ActionBarPopupWindow extends PopupWindow {
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(
ObjectAnimator.ofFloat(child, "alpha", 0.0f, 1.0f),
ObjectAnimator.ofFloat(child, "translationY", AndroidUtilities.dp(showedFromBotton ? 6 : -6), 0));
ObjectAnimator.ofFloat(child, "translationY", AndroidUtilities.dp(/*showedFromBotton ? 6 :*/ -6), 0));
animatorSet.setDuration(180);
animatorSet.setInterpolator(decelerateInterpolator);
animatorSet.start();
@@ -208,9 +225,9 @@ public class ActionBarPopupWindow extends PopupWindow {
protected void onDraw(Canvas canvas) {
if (backgroundDrawable != null) {
backgroundDrawable.setAlpha(backAlpha);
if (showedFromBotton) {
/*if (showedFromBotton) {
backgroundDrawable.setBounds(0, (int) (getMeasuredHeight() * (1.0f - backScaleY)), (int) (getMeasuredWidth() * backScaleX), getMeasuredHeight());
} else {
} else*/ {
backgroundDrawable.setBounds(0, 0, (int) (getMeasuredWidth() * backScaleX), (int) (getMeasuredHeight() * backScaleY));
}
backgroundDrawable.draw(canvas);
@@ -330,9 +347,9 @@ public class ActionBarPopupWindow extends PopupWindow {
child.setAlpha(0.0f);
visibleCount++;
}
if (content.showedFromBotton) {
/*if (content.showedFromBotton) {
content.lastStartedChild = count - 1;
} else {
} else*/ {
content.lastStartedChild = 0;
}
windowAnimatorSet = new AnimatorSet();
@@ -397,7 +414,7 @@ public class ActionBarPopupWindow extends PopupWindow {
ActionBarPopupWindowLayout content = (ActionBarPopupWindowLayout) getContentView();
windowAnimatorSet = new AnimatorSet();
windowAnimatorSet.playTogether(
ObjectAnimator.ofFloat(content, "translationY", AndroidUtilities.dp(content.showedFromBotton ? 5 : -5)),
ObjectAnimator.ofFloat(content, "translationY", AndroidUtilities.dp(/*content.showedFromBotton ? 5 :*/ -5)),
ObjectAnimator.ofFloat(content, "alpha", 0.0f));
windowAnimatorSet.setDuration(150);
windowAnimatorSet.addListener(new Animator.AnimatorListener() {
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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.ui.ActionBar;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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.ui.ActionBar;
@@ -304,12 +319,4 @@ public class BaseFragment {
protected void onDialogDismiss(Dialog dialog) {
}
public Dialog getVisibleDialog() {
return visibleDialog;
}
public void setVisibleDialog(Dialog dialog) {
visibleDialog = dialog;
}
}
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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.ui.ActionBar;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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.ui.ActionBar;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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.ui.ActionBar;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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.ui.ActionBar;
@@ -1,10 +1,25 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
/*******************************************************************************
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
* Messenger Android Frontend
* (C) 2013-2016 Nikolai Kudashov
* (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.ui.ActionBar;
@@ -24,10 +39,11 @@ import android.os.Build;
import com.b44t.messenger.AndroidUtilities;
import com.b44t.messenger.ApplicationLoader;
import com.b44t.messenger.R;
import com.b44t.ui.Components.ChatAttachAlert;
public class Theme {
public static final int ACTION_BAR_COLOR = 0xff415e6b;
public static final int ACTION_BAR_COLOR = 0xff415e6b; // also used for the notification icon background
public static final int ACTION_BAR_PHOTO_VIEWER_COLOR = 0x7f000000;
public static final int ACTION_BAR_MEDIA_PICKER_COLOR = 0xff333333;
public static final int ACTION_BAR_PLAYER_COLOR = 0xffffffff;
@@ -52,21 +68,14 @@ public class Theme {
public static final int DIALOGS_PRINTING_TEXT_COLOR = 0xff4d83b3;
public static final int DIALOGS_DRAFT_TEXT_COLOR = 0xffdd4b39;
public static final int CHAT_UNREAD_TEXT_COLOR = 0xff5695cc;
public static final int CHAT_ADD_CONTACT_TEXT_COLOR = 0xff4a82b5;
public static final int CHAT_REPORT_SPAM_TEXT_COLOR = 0xffcf5957;
public static final int CHAT_BOTTOM_OVERLAY_TEXT_COLOR = 0xff7f7f7f;
public static final int CHAT_GIF_HINT_TEXT_COLOR = 0xffffffff;
public static final int CHAT_EMPTY_VIEW_TEXT_COLOR = 0xffffffff;
public static final int CHAT_SEARCH_COUNT_TEXT_COLOR = 0xff4e9ad4;
public static final int INAPP_PLAYER_PERFORMER_TEXT_COLOR = 0xff2f3438;
public static final int INAPP_PLAYER_TITLE_TEXT_COLOR = 0xff2f3438;
public static final int INAPP_PLAYER_BACKGROUND_COLOR = 0xffffffff;
public static final int REPLY_PANEL_NAME_TEXT_COLOR = 0xff3a8ccf;
public static final int REPLY_PANEL_MESSAGE_TEXT_COLOR = 0xff222222;
public static final int ALERT_PANEL_NAME_TEXT_COLOR = 0xff3a8ccf;
public static final int ALERT_PANEL_MESSAGE_TEXT_COLOR = 0xff999999;
@@ -80,7 +89,6 @@ public class Theme {
public static final int MSG_SELECTED_BACKGROUND_COLOR = 0x6633b5e5;
public static final int MSG_WEB_PREVIEW_DURATION_TEXT_COLOR = 0xffffffff;
public static final int MSG_SECRET_TIME_TEXT_COLOR = 0xffe4e2e0;
public static final int MSG_STICKER_NAME_TEXT_COLOR = 0xffffffff;
public static final int MSG_IN_FORDWARDED_NAME_TEXT_COLOR = 0xff3886c7;
public static final int MSG_OUT_FORDWARDED_NAME_TEXT_COLOR = 0xff55ab4f;
@@ -166,10 +174,6 @@ public class Theme {
public static Drawable backgroundDrawableInSelected;
public static Drawable backgroundDrawableOut;
public static Drawable backgroundDrawableOutSelected;
public static Drawable backgroundMediaDrawableIn;
public static Drawable backgroundMediaDrawableInSelected;
public static Drawable backgroundMediaDrawableOut;
public static Drawable backgroundMediaDrawableOutSelected;
public static Drawable checkDrawable;
public static Drawable halfCheckDrawable;
public static Drawable clockDrawable;
@@ -208,10 +212,6 @@ public class Theme {
backgroundDrawableInSelected = context.getResources().getDrawable(R.drawable.msg_in_selected);
backgroundDrawableOut = context.getResources().getDrawable(R.drawable.msg_out);
backgroundDrawableOutSelected = context.getResources().getDrawable(R.drawable.msg_out_selected);
backgroundMediaDrawableIn = context.getResources().getDrawable(R.drawable.msg_in_photo);
backgroundMediaDrawableInSelected = context.getResources().getDrawable(R.drawable.msg_in_photo_selected);
backgroundMediaDrawableOut = context.getResources().getDrawable(R.drawable.msg_out_photo);
backgroundMediaDrawableOutSelected = context.getResources().getDrawable(R.drawable.msg_out_photo_selected);
checkDrawable = context.getResources().getDrawable(R.drawable.msg_check);
halfCheckDrawable = context.getResources().getDrawable(R.drawable.msg_halfcheck);
clockDrawable = context.getResources().getDrawable(R.drawable.msg_clock);
@@ -281,9 +281,6 @@ public class Theme {
shareIconDrawable = context.getResources().getDrawable(R.drawable.ic_ab_reply);
geoInDrawable = context.getResources().getDrawable(R.drawable.location_b);
geoOutDrawable = context.getResources().getDrawable(R.drawable.location_g);
cornerOuter[0] = context.getResources().getDrawable(R.drawable.corner_out_tl);
cornerOuter[1] = context.getResources().getDrawable(R.drawable.corner_out_tr);
cornerOuter[2] = context.getResources().getDrawable(R.drawable.corner_out_br);
@@ -310,14 +307,14 @@ public class Theme {
public static void loadChatResources(Context context) {
if (attachButtonDrawables[0] == null) {
attachButtonDrawables[0] = context.getResources().getDrawable(R.drawable.attach_camera_states);
attachButtonDrawables[1] = context.getResources().getDrawable(R.drawable.attach_gallery_states);
attachButtonDrawables[2] = context.getResources().getDrawable(R.drawable.attach_video_states);
attachButtonDrawables[3] = context.getResources().getDrawable(R.drawable.attach_audio_states);
attachButtonDrawables[4] = context.getResources().getDrawable(R.drawable.attach_file_states);
attachButtonDrawables[5] = context.getResources().getDrawable(R.drawable.attach_contact_states);
attachButtonDrawables[6] = context.getResources().getDrawable(R.drawable.attach_location_states);
attachButtonDrawables[7] = context.getResources().getDrawable(R.drawable.attach_hide_states);
attachButtonDrawables[ChatAttachAlert.ATTACH_BUTTON_IDX_CAMERA] = context.getResources().getDrawable(R.drawable.attach_camera_states);
attachButtonDrawables[ChatAttachAlert.ATTACH_BUTTON_IDX_GALLERY] = context.getResources().getDrawable(R.drawable.attach_gallery_states);
attachButtonDrawables[ChatAttachAlert.ATTACH_BUTTON_IDX_VIDEO] = context.getResources().getDrawable(R.drawable.attach_video_states);
attachButtonDrawables[ChatAttachAlert.ATTACH_BUTTON_IDX_MUSIC] = context.getResources().getDrawable(R.drawable.attach_audio_states);
attachButtonDrawables[ChatAttachAlert.ATTACH_BUTTON_IDX_FILE] = context.getResources().getDrawable(R.drawable.attach_file_states);
attachButtonDrawables[ChatAttachAlert.ATTACH_BUTTON_IDX_CONTACT] = context.getResources().getDrawable(R.drawable.attach_contact_states);
attachButtonDrawables[ChatAttachAlert.ATTACH_BUTTON_IDX_LOCATION] = context.getResources().getDrawable(R.drawable.attach_location_states);
attachButtonDrawables[ChatAttachAlert.ATTACH_BUTTON_IDX_SENDSELECTED]= context.getResources().getDrawable(R.drawable.attach_hide_states);
}
}

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