mirror of
https://github.com/ArcaneChat/android.git
synced 2026-07-03 14:05:24 +02:00
Compare commits
438 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fab24ee956 | |||
| 94f4c8b302 | |||
| 008a2410a7 | |||
| b43f337af9 | |||
| 21895cf00f | |||
| 721d016d86 | |||
| 89aaa9c072 | |||
| bcb00a9d23 | |||
| 34cd40fdd9 | |||
| c8001cedce | |||
| 880353888b | |||
| 2c67d20233 | |||
| 42c08a4d5b | |||
| 01bf0f3af5 | |||
| e765968c2c | |||
| 3837463e41 | |||
| 545a2ddc24 | |||
| 4f6f0b4685 | |||
| 1d1bad8b3b | |||
| af5769f231 | |||
| 42c6337c4d | |||
| 37a49c9d39 | |||
| 3b2f778114 | |||
| b55cc03f6d | |||
| 2e6eead045 | |||
| e77c3303a1 | |||
| e83c4f315c | |||
| 833c75d874 | |||
| 9688003648 | |||
| a2609d5bbe | |||
| 227f129455 | |||
| 4e683e5b37 | |||
| c5a0a00dd8 | |||
| de0bce163f | |||
| 9dcb58c1ea | |||
| 4729642f87 | |||
| 751cbfa635 | |||
| e40cae149b | |||
| 758dfbaa67 | |||
| 29ec49b806 | |||
| 8afb5595d0 | |||
| 8430e9ddc6 | |||
| 7439fafe2b | |||
| e1655a40bd | |||
| 92fc521d5b | |||
| 023d34f2b6 | |||
| 8fc064a5a4 | |||
| b9a329f416 | |||
| 4997fa7301 | |||
| e267d67d6e | |||
| 83b04a97ef | |||
| 7852c9e9f9 | |||
| 009adc09bc | |||
| 4d3929576d | |||
| 7712def225 | |||
| 9509919431 | |||
| 15cc62f559 | |||
| ae46cbbf5e | |||
| 1664fcdc84 | |||
| 2c45f4af37 | |||
| b3d1747c0b | |||
| 693952d0eb | |||
| 0ad5bd6e48 | |||
| 89c34f89c9 | |||
| 70971a73ad | |||
| 2c5b377712 | |||
| ae4b5a711b | |||
| 252bc52d47 | |||
| 655783db1e | |||
| 10b2af3656 | |||
| 54c3a963a4 | |||
| a7836eaded | |||
| 10fcbdc81d | |||
| b2a5885787 | |||
| 9886a4feb4 | |||
| dcd04f7064 | |||
| 5773ce8b83 | |||
| 0c3eb19de6 | |||
| 5e72e30d58 | |||
| c9d8ad3d4a | |||
| 62bd4f6d9f | |||
| 15e1d55a77 | |||
| 04cab2ee0c | |||
| fd28868ea8 | |||
| 129e6ad487 | |||
| 082f7229f2 | |||
| 1c6001ed92 | |||
| 2ec48ef1e6 | |||
| 04397f3cb0 | |||
| 8697756083 | |||
| 7be5ec589c | |||
| d3fbf529eb | |||
| e47818b5df | |||
| 201c9ebf4c | |||
| 0626192659 | |||
| 0acdd3f885 | |||
| 6f0fd1072d | |||
| d17579b928 | |||
| 090039ec29 | |||
| df8bbcd00a | |||
| fffc77cc82 | |||
| 9ee5af9fd2 | |||
| 5462f3d341 | |||
| 46dca0d212 | |||
| 603572c796 | |||
| db6c2d9d7c | |||
| b6c6375492 | |||
| 3f5255c116 | |||
| 68f3974aa2 | |||
| 2c062d8d51 | |||
| 1097157f69 | |||
| 21784aa951 | |||
| f980f7285a | |||
| 622b6bc786 | |||
| 61fc0485b7 | |||
| be2af9c871 | |||
| 898e4a45e3 | |||
| e47c6406f8 | |||
| 1d0ed83bad | |||
| 404f6ea9da | |||
| 8d75f867fd | |||
| 83f60e6252 | |||
| c4bd6576d8 | |||
| 12df911162 | |||
| f5a37ee185 | |||
| 92d71ad150 | |||
| 8824b30c4a | |||
| 741e281a37 | |||
| 354295ae7a | |||
| 09af0640c7 | |||
| 1485eeecf6 | |||
| 8b78df6a14 | |||
| 686ee6c246 | |||
| ca8114d9af | |||
| b2392c90c2 | |||
| d207fa67e5 | |||
| 2e41fe756a | |||
| d533ea5c37 | |||
| 4365e176d8 | |||
| 486b03e031 | |||
| 1dbf08327c | |||
| 0d15bb3544 | |||
| e3b48206e9 | |||
| a0e364a50f | |||
| 0db3fc55c6 | |||
| 95c3fca389 | |||
| 68a72fb8fd | |||
| 473410ece2 | |||
| 4f760a790a | |||
| ad7ee4428f | |||
| 92cf756ad2 | |||
| 3d746f08ba | |||
| e272459fc9 | |||
| a793ae52f9 | |||
| f2349a9bdd | |||
| 7082798c03 | |||
| f4fc5fae2b | |||
| 5799e43b3a | |||
| f929d6cc31 | |||
| 9f92efc554 | |||
| 3338b83910 | |||
| a4c104431d | |||
| 31ba521244 | |||
| 50dfe15f09 | |||
| 4b06d19787 | |||
| 66d147eb8b | |||
| d2591922a6 | |||
| bcc6f79373 | |||
| 015edd6053 | |||
| bec562bfb2 | |||
| 01a7c93771 | |||
| 502bae625f | |||
| a34d511922 | |||
| e65aa19109 | |||
| 30585b8de4 | |||
| 0bd4234214 | |||
| db4ceb6d68 | |||
| 1612a5d7cd | |||
| f60f4539b5 | |||
| db7c8a9dfc | |||
| 9d1f4266c2 | |||
| 0614c4fc32 | |||
| 58e452b711 | |||
| b478696bed | |||
| f3584d9eaf | |||
| d9998167f4 | |||
| 874e300220 | |||
| 49e4b90cc3 | |||
| f492f2cd71 | |||
| 2800a282ec | |||
| 593e93304c | |||
| 77b6108ca8 | |||
| 90bf2b6b19 | |||
| dd91d52df4 | |||
| de29317fa6 | |||
| 44faee6208 | |||
| 41ccf19e58 | |||
| 05c390980a | |||
| 4446ed0792 | |||
| 11942da0c0 | |||
| 9a0604a1a8 | |||
| 93ca874e61 | |||
| 9ba21c4346 | |||
| c0e7798cad | |||
| 0aea5a2201 | |||
| 63873ec1d5 | |||
| 23f269d4b3 | |||
| 9ebacb23c4 | |||
| d1e83f46d8 | |||
| 5f2dd23a6e | |||
| d29b24e9a6 | |||
| 4f1415e127 | |||
| c604313c09 | |||
| e6bc14a8de | |||
| 4a5729d371 | |||
| d9ac76a317 | |||
| 867df35d44 | |||
| e946d61b92 | |||
| fa2ffbd70f | |||
| 1123f03134 | |||
| 49e86d08bf | |||
| 5f00826e65 | |||
| 82382f31f1 | |||
| 833cbf7302 | |||
| 4e329adaca | |||
| dbc9e4c3c2 | |||
| d9cff40fd5 | |||
| ef248712d6 | |||
| 9765ba1bac | |||
| afcccaa864 | |||
| 7caef2ceb9 | |||
| cb4480ad78 | |||
| 6388349c16 | |||
| 73a111aeac | |||
| 5869bdc9dd | |||
| ff7f75abed | |||
| 28ac3bd9eb | |||
| 49f07874f8 | |||
| 59779b7f2a | |||
| 677df359ae | |||
| 4e4aca675f | |||
| 76163e6012 | |||
| 85b319825d | |||
| 8edf8a6140 | |||
| acba74142c | |||
| c06f34923e | |||
| bb00342b5d | |||
| 25b43986d3 | |||
| 9b5984182f | |||
| ae9dfb1595 | |||
| 001a4a8675 | |||
| 13a1e92321 | |||
| fb97c8edaf | |||
| ffce59ea7e | |||
| dd7ef2d744 | |||
| a76f840368 | |||
| c4bac7359b | |||
| 67e028502d | |||
| e05b31a76b | |||
| d1b95e369d | |||
| 64a71f25f2 | |||
| 76e906579b | |||
| 23dc66622b | |||
| 997bbd336c | |||
| d8a0225b1a | |||
| ce656ca374 | |||
| dd202b4c72 | |||
| 522ff32432 | |||
| a96cb520dd | |||
| fe9cd52312 | |||
| d4355ad076 | |||
| 057d0eb39e | |||
| 82f35621e2 | |||
| 633856b350 | |||
| 1c0c9004c6 | |||
| 833533adc3 | |||
| 846df6a164 | |||
| f5de9e8a23 | |||
| 404a0ca032 | |||
| 6e8612172b | |||
| aed9e39287 | |||
| 597100d9e3 | |||
| b2775e0811 | |||
| 2425f0dcc7 | |||
| ede60340f6 | |||
| a9d58ab3f3 | |||
| 6d6b6f41c9 | |||
| f5f97e4bfc | |||
| c7ed50a225 | |||
| f843c531b4 | |||
| 2389a7d136 | |||
| e1d0306a29 | |||
| 04cbe3f825 | |||
| 9796ac1c53 | |||
| 5721b9f86d | |||
| aa090a9cd4 | |||
| 03c30bef47 | |||
| c59453f31b | |||
| 49e7f19cb7 | |||
| 469c56f1a6 | |||
| 239c56e77d | |||
| e32ca20604 | |||
| d00ef0af32 | |||
| e616e57be6 | |||
| 5485db8509 | |||
| df75d2917f | |||
| 0478ea5162 | |||
| 433e90072f | |||
| 5c646ea663 | |||
| e095d3f886 | |||
| 9a6315d0b2 | |||
| 8e81f0bb8f | |||
| d6bdebc865 | |||
| 7ddf368fd1 | |||
| 301c6a4430 | |||
| adaf91e383 | |||
| 40de9dfe98 | |||
| 18a8e2358c | |||
| e2a4008742 | |||
| 258633b672 | |||
| 96cc35b84d | |||
| 787efa3c5d | |||
| 848862ae84 | |||
| 6d3c170e96 | |||
| a921523014 | |||
| 29e5133c63 | |||
| 8d4aebe8e7 | |||
| c0139b1b49 | |||
| 920d55ee6d | |||
| 4348b80b02 | |||
| 1a62ed853b | |||
| f858cc7747 | |||
| 394b439a06 | |||
| b515660bac | |||
| 88719df0af | |||
| 495dfa0f59 | |||
| f7372819a1 | |||
| 9d622ecef7 | |||
| 221004354e | |||
| 442baa6aa9 | |||
| 2e4f748093 | |||
| 56a846ab3b | |||
| f67e24b49e | |||
| f40a3e49cb | |||
| 04b815bb49 | |||
| 3292979696 | |||
| 3e24ca9be1 | |||
| 38e5350219 | |||
| 39d5c40945 | |||
| ebcb132acf | |||
| 53447c793a | |||
| 54a2df818b | |||
| 09a3b3bd26 | |||
| f02d4cd21a | |||
| eb650ff089 | |||
| da263b1e56 | |||
| 44ee4aaef7 | |||
| 56874bd418 | |||
| bf1594fdef | |||
| e31821cf92 | |||
| 4efe3b4387 | |||
| 69d0537425 | |||
| 0852e09815 | |||
| 2fc8799241 | |||
| ea01205421 | |||
| 1ad31aa178 | |||
| 349b943a7e | |||
| 268006d027 | |||
| e2bad18153 | |||
| 4749ddf9a8 | |||
| de1c568714 | |||
| 0b90e66ad8 | |||
| 90fe75a764 | |||
| c27fd27789 | |||
| 5580f5ae62 | |||
| d4e94b2fbc | |||
| bb673dd992 | |||
| 2dfacc4858 | |||
| cce4e31b0f | |||
| 99615999b8 | |||
| cfca25d65d | |||
| 665a2cdfd0 | |||
| a2768728d3 | |||
| 2790082705 | |||
| ae8a15d524 | |||
| e39d7b5d4d | |||
| 1ae26ecfa5 | |||
| 1e58912226 | |||
| 87807db64a | |||
| 6221c97283 | |||
| 80226717b6 | |||
| 959f7af2ab | |||
| 2308990661 | |||
| 9f304f372a | |||
| 341580191f | |||
| 07065676f2 | |||
| 47c9dc6e31 | |||
| 2514494d02 | |||
| 1c28c2d475 | |||
| 41a92d56c4 | |||
| 6a6b024314 | |||
| 12c95971a2 | |||
| 62ca3b6331 | |||
| c69f2fd75d | |||
| 0fc45bc57a | |||
| 0b9614f0bd | |||
| e8a073a42c | |||
| 97b33ec9c4 | |||
| f6458870ae | |||
| 665f24db1e | |||
| a59be9d2af | |||
| 1036139cb7 | |||
| f1854e46be | |||
| bfad3e57c7 | |||
| 24ee24325b | |||
| c9f6db312f | |||
| 6f60ba113e | |||
| db112b226e | |||
| a87049e443 | |||
| 730b018b45 | |||
| 60e72f14d8 | |||
| e89b2855ce | |||
| 56fb73088e | |||
| 6623513c2a | |||
| 3da3325c9b | |||
| c73d3564d4 | |||
| 2b822ecd22 | |||
| a81c921504 | |||
| c902044cc3 | |||
| 072945b237 | |||
| ca49e9899d | |||
| f67d82452b | |||
| 1c3b7ce051 | |||
| cd6d8114ad | |||
| 1baa5a5d99 | |||
| a83dac9437 | |||
| e033c04d7a | |||
| bbd06d37da |
@@ -6,3 +6,6 @@ obj/
|
||||
local.properties
|
||||
*.keystore
|
||||
libs/
|
||||
|
||||
# ignore private scripts and directories, eg. local2github.prv.sh
|
||||
*.prv*
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[submodule "MessengerProj/jni/messenger-backend"]
|
||||
path = MessengerProj/jni/messenger-backend
|
||||
url = https://github.com/r10s/messenger-backend.git
|
||||
@@ -0,0 +1,69 @@
|
||||
# Delta Chat Changelog
|
||||
|
||||
## v0.1.22
|
||||
2017-03-22
|
||||
|
||||
* Show HTML-only messages
|
||||
* Show connection errors
|
||||
* Add options for SSL/TLS and STARTTLS
|
||||
* Automatic account configuration, if possible
|
||||
* Recode large videos
|
||||
* Add Hungarian translation
|
||||
* Add Korean translation
|
||||
|
||||
## v0.1.21
|
||||
2017-03-10
|
||||
|
||||
* Record and send voice messages
|
||||
* Record and send videos
|
||||
* Send and play music
|
||||
* Send contacts and email addresses
|
||||
* Sending and opening attachments of any type
|
||||
* Share and open commands for all attachments
|
||||
* Accept VCards send to us by other apps
|
||||
* Clickable email addresses
|
||||
* Update Polish translation
|
||||
* Fix tablet startup bug
|
||||
* Close the app when using the lock-app-via-pincode function
|
||||
* Protect data by using a content provider for sharing
|
||||
* Try to clear the task switcher's screenshots when locking the app via pincode
|
||||
* Pimp GUI
|
||||
|
||||
## v0.1.20
|
||||
2017-02-16
|
||||
|
||||
* Avoid unwanted downloads of lots of old messages
|
||||
* Make the "Chats" folder visible if the server hides new folders by default
|
||||
* Fix a crash when the server returns empty folders
|
||||
* Update Polish and Portuguese translations
|
||||
* Use API level 25 (Nougat 7.1) as target
|
||||
|
||||
## v0.1.18
|
||||
2017-02-11
|
||||
|
||||
* Add Polish translation
|
||||
* Use a new default background for chats
|
||||
* Improve typography by using the system font instead of a custom resource font
|
||||
* Remove custom plural handling, use Android's routines instead
|
||||
* Remove unused source code and strings
|
||||
* More fixes of lint errors and warnings
|
||||
|
||||
## v0.1.17
|
||||
2017-02-07
|
||||
|
||||
* Drop two unnecessary permissions: ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION
|
||||
* Really add French translation
|
||||
* Update Portuguese translation
|
||||
* Start fixing translation handling of the program
|
||||
* Remove special "foss" build, because the whole program is free now.
|
||||
|
||||
## v0.1.16
|
||||
2017-02-06
|
||||
|
||||
* Add French translation
|
||||
* Fix some lint errors and warnings
|
||||
|
||||
## v0.1.15
|
||||
2017-01-31
|
||||
|
||||
* Prepare for release on [F-Droid](https://f-droid.org/)
|
||||
+12
-25
@@ -24,15 +24,15 @@ tasks.withType(JavaCompile) {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile 'com.android.support:support-v4:23.4.0'
|
||||
compile 'com.android.support:appcompat-v7:25.1.1'
|
||||
compile 'com.googlecode.mp4parser:isoparser:1.0.6'
|
||||
compile 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'
|
||||
compile fileTree(dir: "$buildDir/native-libs", include: 'native-libs.jar')
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 23
|
||||
buildToolsVersion '23.0.3'
|
||||
compileSdkVersion 25
|
||||
buildToolsVersion '25.0.2'
|
||||
|
||||
useLibrary 'org.apache.http.legacy'
|
||||
defaultConfig.applicationId = "com.b44t.messenger"
|
||||
@@ -42,6 +42,10 @@ android {
|
||||
targetCompatibility JavaVersion.VERSION_1_7
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
debug {
|
||||
storeFile file("config/debug.keystore")
|
||||
@@ -70,34 +74,17 @@ android {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
|
||||
foss {
|
||||
debuggable false
|
||||
jniDebuggable false
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
}
|
||||
|
||||
defaultConfig.versionCode = 13
|
||||
defaultConfig.versionCode = 21
|
||||
|
||||
sourceSets.main {
|
||||
jniLibs.srcDir 'libs'
|
||||
jni.srcDirs = [] //disable automatic ndk-build call
|
||||
}
|
||||
|
||||
sourceSets.debug {
|
||||
manifest.srcFile 'config/debug/AndroidManifest.xml'
|
||||
}
|
||||
|
||||
sourceSets.release {
|
||||
manifest.srcFile 'config/release/AndroidManifest.xml'
|
||||
}
|
||||
|
||||
sourceSets.foss {
|
||||
manifest.srcFile 'config/foss/AndroidManifest.xml'
|
||||
}
|
||||
|
||||
productFlavors {
|
||||
/*
|
||||
x86 {
|
||||
ndk {
|
||||
abiFilter "x86"
|
||||
@@ -116,6 +103,7 @@ android {
|
||||
}
|
||||
versionCode = 1
|
||||
}
|
||||
*/
|
||||
fat {
|
||||
versionCode = 3
|
||||
}
|
||||
@@ -128,8 +116,7 @@ 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"
|
||||
targetSdkVersion 25
|
||||
versionName "0.1.22" // do NOT forget to increase defaultConfig.versionCode!
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.b44t.messenger"
|
||||
android:installLocation="auto">
|
||||
|
||||
<uses-feature android:name="android.hardware.location.gps" android:required="false" />
|
||||
<uses-feature android:name="android.hardware.location.network" android:required="false" />
|
||||
<uses-feature android:name="android.hardware.location" android:required="false" />
|
||||
<uses-feature android:name="android.hardware.LOCATION" android:required="false" />
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<application
|
||||
android:allowBackup="false"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/AppNameBeta"
|
||||
android:theme="@style/Theme.MessengerProj.Start"
|
||||
android:name=".ApplicationLoader"
|
||||
android:hardwareAccelerated="@bool/useHardwareAcceleration"
|
||||
android:largeHeap="true">
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.b44t.messenger"
|
||||
android:installLocation="auto">
|
||||
|
||||
<application
|
||||
android:allowBackup="false"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/AppName"
|
||||
android:theme="@style/Theme.MessengerProj.Start"
|
||||
android:name=".ApplicationLoader"
|
||||
android:hardwareAccelerated="@bool/useHardwareAcceleration"
|
||||
android:largeHeap="true">
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.b44t.messenger"
|
||||
android:installLocation="auto">
|
||||
|
||||
<uses-feature android:name="android.hardware.location.gps" android:required="false" />
|
||||
<uses-feature android:name="android.hardware.location.network" android:required="false" />
|
||||
<uses-feature android:name="android.hardware.location" android:required="false" />
|
||||
<uses-feature android:name="android.hardware.LOCATION" android:required="false" />
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<application
|
||||
android:allowBackup="false"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/AppName"
|
||||
android:theme="@style/Theme.MessengerProj.Start"
|
||||
android:name=".ApplicationLoader"
|
||||
android:hardwareAccelerated="@bool/useHardwareAcceleration"
|
||||
android:largeHeap="true">
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -1604,24 +1604,28 @@ 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/mrloginparam.c \
|
||||
./messenger-backend/src/mrmailbox.c \
|
||||
./messenger-backend/src/mrmailbox_configure.c \
|
||||
./messenger-backend/src/mrmailbox_log.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/mrsaxparser.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)
|
||||
|
||||
Submodule
+1
Submodule MessengerProj/jni/messenger-backend added at ea43f6b151
+388
-105
@@ -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,49 +36,79 @@
|
||||
#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!*/
|
||||
|
||||
|
||||
/* our log handler */
|
||||
|
||||
static void s_log_callback_(int type, const char* msg)
|
||||
#define JSTRING_NEW(a) jstring_new__(env, (a))
|
||||
static jstring jstring_new__(JNIEnv* env, const char* a)
|
||||
{
|
||||
int prio;
|
||||
|
||||
switch( type ) {
|
||||
case 'd': prio = ANDROID_LOG_DEBUG; break;
|
||||
case 'i': prio = ANDROID_LOG_INFO; break;
|
||||
case 'w': prio = ANDROID_LOG_WARN; break;
|
||||
default: prio = ANDROID_LOG_ERROR; break;
|
||||
if( a==NULL || a[0]==0 ) {
|
||||
return (*env)->NewStringUTF(env, "");
|
||||
}
|
||||
__android_log_print(prio, "DeltaChat", "%s\n", msg); /* on problems, add `-llog` to `Android.mk` */
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
||||
/* globl stuff */
|
||||
/* global stuff */
|
||||
|
||||
static JavaVM* s_jvm = NULL;
|
||||
static jclass s_MrMailbox_class = NULL;
|
||||
static jmethodID s_MrCallback_methodID = NULL;
|
||||
static int s_global_init_done = 0;
|
||||
|
||||
|
||||
static void s_init_globals(JNIEnv *env, jclass MrMailbox_class)
|
||||
{
|
||||
/* make sure, the intialisation is done only once */
|
||||
static bool s_global_init_done = 0;
|
||||
if( s_global_init_done ) { return; }
|
||||
s_global_init_done = 1;
|
||||
|
||||
/* init global callback */
|
||||
mrlog_set_handler(s_log_callback_);
|
||||
|
||||
/* prepare calling back a Java function */
|
||||
(*env)->GetJavaVM(env, &s_jvm); /* JNIEnv cannot be shared between threads, so we share the JavaVM object */
|
||||
s_MrMailbox_class = (*env)->NewGlobalRef(env, MrMailbox_class);
|
||||
s_MrCallback_methodID = (*env)->GetStaticMethodID(env, MrMailbox_class, "MrCallback","(IJJ)J" /*signature as "(param)ret" with I=int, J=long*/ );
|
||||
}
|
||||
|
||||
/* system-specific backend initialisations */
|
||||
mrosnative_init_android(env); /*this should be called before any other "important" routine is called*/
|
||||
|
||||
/* setup threads, only called directly by the backed */
|
||||
|
||||
int mrosnative_setup_thread(mrmailbox_t* mailbox)
|
||||
{
|
||||
if( s_jvm == NULL ) {
|
||||
mrmailbox_log_error(mailbox, 0, "Not ready, cannot setup thread.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mrmailbox_log_info(mailbox, 0, "Attaching C-thread to Java VM...");
|
||||
JNIEnv* env = NULL;
|
||||
(*s_jvm)->AttachCurrentThread(s_jvm, &env, NULL);
|
||||
mrmailbox_log_info(mailbox, 0, "Attaching ok.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void mrosnative_unsetup_thread(mrmailbox_t* mailbox)
|
||||
{
|
||||
mrmailbox_log_info(mailbox, 0, "Detaching C-thread from Java VM...");
|
||||
(*s_jvm)->DetachCurrentThread(s_jvm);
|
||||
mrmailbox_log_info(mailbox, 0, "Detaching done.");
|
||||
}
|
||||
|
||||
|
||||
@@ -112,9 +141,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 */
|
||||
@@ -124,15 +193,22 @@ static uintptr_t s_mailbox_callback_(mrmailbox_t* mailbox, int event, uintptr_t
|
||||
jlong l;
|
||||
JNIEnv* env;
|
||||
|
||||
if( event==MR_EVENT_INFO || event==MR_EVENT_WARNING ) {
|
||||
__android_log_print(event==MR_EVENT_INFO? ANDROID_LOG_INFO : ANDROID_LOG_WARN, "DeltaChat", "%s", (char*)data2); /* on problems, add `-llog` to `Android.mk` */
|
||||
return 0; /* speed up things for info/warning */
|
||||
}
|
||||
else if( event == MR_EVENT_ERROR ) {
|
||||
__android_log_print(ANDROID_LOG_ERROR, "DeltaChat", "%s", (char*)data2);
|
||||
/* errors are also forwarded to Java to show them in a bubble or so */
|
||||
}
|
||||
|
||||
if( s_jvm==NULL || s_MrMailbox_class==NULL || s_MrCallback_methodID==NULL ) {
|
||||
s_log_callback_('e', "Callback called but JavaVM not ready.");
|
||||
return 0;
|
||||
return 0; /* may happen on startup */
|
||||
}
|
||||
|
||||
(*s_jvm)->GetEnv(s_jvm, &env, JNI_VERSION_1_6); /* as this function may be called from _any_ thread, we cannot use a static pointer to JNIEnv */
|
||||
if( env==NULL ) {
|
||||
s_log_callback_('e', "Callback called but cannot get JNIEnv.");
|
||||
return 0;
|
||||
return 0; /* may happen on startup */
|
||||
}
|
||||
|
||||
l = (*env)->CallStaticLongMethod(env, s_MrMailbox_class, s_MrCallback_methodID, (jint)event, (jlong)data1, (jlong)data2);
|
||||
@@ -149,67 +225,78 @@ 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 jint Java_com_b44t_messenger_MrMailbox_MrMailboxConfigure(JNIEnv *env, jclass c, jlong hMailbox)
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_MrMailbox_getBlobdir(JNIEnv *env, jclass cls)
|
||||
{
|
||||
return mrmailbox_configure((mrmailbox_t*)hMailbox);
|
||||
mrmailbox_t* ths = get_mrmailbox_t(env, cls);
|
||||
return JSTRING_NEW((ths&&ths->m_blobdir)? ths->m_blobdir : NULL);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_MrMailboxIsConfigured(JNIEnv *env, jclass c, jlong hMailbox)
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_configureAndConnect(JNIEnv *env, jclass cls)
|
||||
{
|
||||
return (jint)mrmailbox_is_configured((mrmailbox_t*)hMailbox);
|
||||
mrmailbox_configure_and_connect(get_mrmailbox_t(env, cls));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_MrMailboxConnect(JNIEnv *env, jclass c, jlong hMailbox)
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_configureCancel(JNIEnv *env, jclass cls)
|
||||
{
|
||||
return mrmailbox_connect((mrmailbox_t*)hMailbox);
|
||||
mrmailbox_configure_cancel(get_mrmailbox_t(env, cls));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_MrMailboxDisconnect(JNIEnv *env, jclass c, jlong hMailbox)
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_isConfigured(JNIEnv *env, jclass cls)
|
||||
{
|
||||
mrmailbox_disconnect((mrmailbox_t*)hMailbox);
|
||||
return (jint)mrmailbox_is_configured(get_mrmailbox_t(env, cls));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_MrMailboxFetch(JNIEnv *env, jclass c, jlong hMailbox)
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_connect(JNIEnv *env, jclass cls)
|
||||
{
|
||||
return mrmailbox_fetch((mrmailbox_t*)hMailbox);
|
||||
mrmailbox_connect(get_mrmailbox_t(env, cls));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_disconnect(JNIEnv *env, jclass cls)
|
||||
{
|
||||
mrmailbox_disconnect(get_mrmailbox_t(env, cls));
|
||||
}
|
||||
|
||||
|
||||
/* 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 +332,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 +359,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 +377,45 @@ 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_isContactInChat(JNIEnv *env, jclass cls, jint chat_id, jint contact_id)
|
||||
{
|
||||
return (jint)mrmailbox_is_contact_in_chat(get_mrmailbox_t(env, cls), chat_id, contact_id);
|
||||
}
|
||||
|
||||
|
||||
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,30 +436,49 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
/* MrMailbox - handle config */
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_MrMailboxSetConfig(JNIEnv *env, jclass c, jlong hMailbox, jstring key, jstring value)
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_setConfig(JNIEnv *env, jclass cls, jstring key, jstring value)
|
||||
{
|
||||
CHAR_REF(key);
|
||||
CHAR_REF(value);
|
||||
jint ret = (jint)mrmailbox_set_config((mrmailbox_t*)hMailbox, keyPtr, valuePtr);
|
||||
mrmailbox_set_config(get_mrmailbox_t(env, cls), keyPtr, valuePtr);
|
||||
CHAR_UNREF(key);
|
||||
CHAR_UNREF(value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_MrMailbox_MrMailboxGetConfig(JNIEnv *env, jclass c, jlong hMailbox, jstring key, jstring def)
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_setConfigInt(JNIEnv *env, jclass cls, jstring key, jint value)
|
||||
{
|
||||
CHAR_REF(key);
|
||||
mrmailbox_set_config_int(get_mrmailbox_t(env, cls), keyPtr, value);
|
||||
CHAR_UNREF(key);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_MrMailbox_getConfig(JNIEnv *env, jclass cls, jstring key, jstring def)
|
||||
{
|
||||
CHAR_REF(key);
|
||||
CHAR_REF(def);
|
||||
char* temp = mrmailbox_get_config((mrmailbox_t*)hMailbox, keyPtr, defPtr);
|
||||
char* temp = mrmailbox_get_config(get_mrmailbox_t(env, cls), keyPtr, defPtr);
|
||||
jstring ret = JSTRING_NEW(temp);
|
||||
free(temp);
|
||||
CHAR_UNREF(key);
|
||||
@@ -330,10 +487,10 @@ JNIEXPORT jstring Java_com_b44t_messenger_MrMailbox_MrMailboxGetConfig(JNIEnv *e
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_MrMailboxGetConfigInt(JNIEnv *env, jclass c, jlong hMailbox, jstring key, jint def)
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_getConfigInt(JNIEnv *env, jclass cls, jstring key, jint def)
|
||||
{
|
||||
CHAR_REF(key);
|
||||
jint ret = mrmailbox_get_config_int((mrmailbox_t*)hMailbox, keyPtr, def);
|
||||
jint ret = mrmailbox_get_config_int(get_mrmailbox_t(env, cls), keyPtr, def);
|
||||
CHAR_UNREF(key);
|
||||
return ret;
|
||||
}
|
||||
@@ -341,19 +498,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 +562,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;
|
||||
@@ -486,20 +664,20 @@ JNIEXPORT jint Java_com_b44t_messenger_MrChat_MrChatSetDraft(JNIEnv *env, jclass
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrChat_MrChatSendText(JNIEnv *env, jclass c, jlong hChat, jstring text)
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrChat_sendText(JNIEnv *env, jclass cls, jstring text)
|
||||
{
|
||||
mrmsg_t* msg = mrmsg_new();
|
||||
msg->m_type = MR_MSG_TEXT;
|
||||
CHAR_REF(text);
|
||||
msg->m_text = textPtr? strdup(textPtr) : NULL;
|
||||
CHAR_UNREF(text);
|
||||
jint msg_id = mrchat_send_msg((mrchat_t*)hChat, msg);
|
||||
jint msg_id = mrchat_send_msg(get_mrchat_t(env, cls), msg);
|
||||
mrmsg_unref(msg);
|
||||
return msg_id;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrChat_MrChatSendMedia(JNIEnv *env, jclass c, jlong hChat, jint type, jstring file, jstring mime, jint w, jint h, jint ms)
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrChat_sendMedia(JNIEnv *env, jclass cls, jint type, jstring file, jstring mime, jint w, jint h, jint ms, jstring author, jstring trackname)
|
||||
{
|
||||
mrmsg_t* msg = mrmsg_new();
|
||||
msg->m_type = type;
|
||||
@@ -513,33 +691,62 @@ JNIEXPORT jint Java_com_b44t_messenger_MrChat_MrChatSendMedia(JNIEnv *env, jclas
|
||||
mrparam_set_int(msg->m_param, 'w', w);
|
||||
mrparam_set_int(msg->m_param, 'h', h);
|
||||
}
|
||||
if( type == MR_MSG_AUDIO || type == MR_MSG_VIDEO ) {
|
||||
if( type == MR_MSG_AUDIO || type == MR_MSG_VOICE || type == MR_MSG_VIDEO ) {
|
||||
mrparam_set_int(msg->m_param, 'd', ms);
|
||||
}
|
||||
jint msg_id = mrchat_send_msg((mrchat_t*)hChat, msg);
|
||||
if( type == MR_MSG_AUDIO ) {
|
||||
CHAR_REF(author);
|
||||
mrparam_set(msg->m_param, 'N', authorPtr);
|
||||
CHAR_UNREF(author);
|
||||
CHAR_REF(trackname);
|
||||
mrparam_set(msg->m_param, 'n', tracknamePtr);
|
||||
CHAR_UNREF(trackname);
|
||||
}
|
||||
jint msg_id = mrchat_send_msg(get_mrchat_t(env, cls), msg);
|
||||
mrmsg_unref(msg);
|
||||
return msg_id;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jintArray Java_com_b44t_messenger_MrMailbox_MrMailboxGetChatMedia(JNIEnv *env, jclass c, jlong hMailbox, jint chat_id, jint msg_type, jint or_msg_type)
|
||||
JNIEXPORT jintArray Java_com_b44t_messenger_MrMailbox_getChatMedia(JNIEnv *env, jclass cls, jint chat_id, jint msg_type, jint or_msg_type)
|
||||
{
|
||||
carray* ca = mrmailbox_get_chat_media((mrmailbox_t*)hMailbox, chat_id, msg_type, or_msg_type);
|
||||
carray* ca = mrmailbox_get_chat_media(get_mrmailbox_t(env, cls), chat_id, msg_type, or_msg_type);
|
||||
return carray2jintArray_n_carray_free(env, ca);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jintArray Java_com_b44t_messenger_MrMailbox_MrMailboxGetChatMsgs(JNIEnv *env, jclass c, jlong hMailbox, jint chat_id)
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_getNextMedia(JNIEnv *env, jclass cls, jint msg_id, jint dir)
|
||||
{
|
||||
carray* ca = mrmailbox_get_chat_msgs((mrmailbox_t*)hMailbox, chat_id);
|
||||
return mrmailbox_get_next_media(get_mrmailbox_t(env, cls), msg_id, dir);
|
||||
}
|
||||
|
||||
|
||||
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(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 +756,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);
|
||||
@@ -611,9 +832,9 @@ JNIEXPORT jint Java_com_b44t_messenger_MrMsg_MrMsgGetToId(JNIEnv *env, jclass c,
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_MrMsg_MrMsgGetParam(JNIEnv *env, jclass c, jlong hMsg, jint key, jstring def)
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_MrMsg_getParam(JNIEnv *env, jobject obj, jint key, jstring def)
|
||||
{
|
||||
mrmsg_t* ths = (mrmsg_t*)hMsg;
|
||||
mrmsg_t* ths = get_mrmsg_t(env, obj);
|
||||
CHAR_REF(def);
|
||||
char* temp = mrparam_get(ths? ths->m_param:NULL, key, defPtr);
|
||||
jstring ret = JSTRING_NEW(temp);
|
||||
@@ -623,10 +844,68 @@ 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)
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMsg_getParamInt(JNIEnv *env, jobject obj, jint key, jint def)
|
||||
{
|
||||
mrmsg_t* ths = (mrmsg_t*)hMsg;
|
||||
return mrparam_get_int(ths? ths->m_param:NULL, key, def);
|
||||
mrmsg_t* ths = get_mrmsg_t(env, obj);
|
||||
return mrparam_get_int(ths? ths->m_param:NULL, key, def);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMsg_setParamInt(JNIEnv *env, jobject obj, jint key, jint value)
|
||||
{
|
||||
mrmsg_t* ths = get_mrmsg_t(env, obj);
|
||||
mrparam_set_int(ths? ths->m_param:NULL, key, value);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMsg_saveParamToDisk(JNIEnv *env, jobject obj)
|
||||
{
|
||||
mrmsg_save_param_to_disk(get_mrmsg_t(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMsg_getBytes(JNIEnv *env, jobject obj)
|
||||
{
|
||||
jint ret = 0;
|
||||
mrmsg_t* ths = get_mrmsg_t(env, obj);
|
||||
if( ths ) {
|
||||
const char* file = mrparam_get(ths->m_param, 'f', NULL);
|
||||
if( file ) {
|
||||
ret = mr_get_filebytes(file);
|
||||
free(file);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMsg_getFilename(JNIEnv *env, jobject obj)
|
||||
{
|
||||
return JSTRING_NEW(mrmsg_get_filename(get_mrmsg_t(env, obj)));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jlong Java_com_b44t_messenger_MrMsg_getMediainfoCPtr(JNIEnv *env, jobject obj)
|
||||
{
|
||||
return (jlong)mrmsg_get_mediainfo(get_mrmsg_t(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrMsg_isIncreation(JNIEnv *env, jobject obj)
|
||||
{
|
||||
return (jint)mrmsg_is_increation(get_mrmsg_t(env, obj));
|
||||
}
|
||||
|
||||
|
||||
@@ -673,24 +952,24 @@ JNIEXPORT void Java_com_b44t_messenger_MrPoortext_MrPoortextUnref(JNIEnv *env, j
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_MrPoortext_MrPoortextGetTitle(JNIEnv *env, jclass c, jlong hPoortext)
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_MrPoortext_MrPoortextGetText1(JNIEnv *env, jclass c, jlong hPoortext)
|
||||
{
|
||||
mrpoortext_t* ths = (mrpoortext_t*)hPoortext; if( ths == NULL ) { return JSTRING_NEW(NULL); }
|
||||
return JSTRING_NEW(ths->m_title);
|
||||
return JSTRING_NEW(ths->m_text1);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrPoortext_MrPoortextGetTitleMeaning(JNIEnv *env, jclass c, jlong hPoortext)
|
||||
JNIEXPORT jint Java_com_b44t_messenger_MrPoortext_MrPoortextGetText1Meaning(JNIEnv *env, jclass c, jlong hPoortext)
|
||||
{
|
||||
mrpoortext_t* ths = (mrpoortext_t*)hPoortext; if( ths == NULL ) { return 0; }
|
||||
return ths->m_title_meaning;
|
||||
return ths->m_text1_meaning;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_MrPoortext_MrPoortextGetText(JNIEnv *env, jclass c, jlong hPoortext)
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_MrPoortext_MrPoortextGetText2(JNIEnv *env, jclass c, jlong hPoortext)
|
||||
{
|
||||
mrpoortext_t* ths = (mrpoortext_t*)hPoortext; if( ths == NULL ) { return JSTRING_NEW(NULL); }
|
||||
return JSTRING_NEW(ths->m_text);
|
||||
return JSTRING_NEW(ths->m_text2);
|
||||
}
|
||||
|
||||
|
||||
@@ -724,11 +1003,15 @@ JNIEXPORT jstring Java_com_b44t_messenger_MrMailbox_CPtr2String(JNIEnv *env, jcl
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_MrStockAddStr(JNIEnv* env, jclass c, jint id, jstring str)
|
||||
JNIEXPORT jlong Java_com_b44t_messenger_MrMailbox_String2CPtr(JNIEnv *env, jclass c, jstring str)
|
||||
{
|
||||
CHAR_REF(str);
|
||||
mrstock_add_str(id, strPtr);
|
||||
CHAR_UNREF(str)
|
||||
char* hStr = NULL;
|
||||
if( str ) {
|
||||
CHAR_REF(str);
|
||||
hStr = strdup(strPtr);
|
||||
CHAR_UNREF(str);
|
||||
}
|
||||
return (jlong)hStr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -20,34 +20,35 @@
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- we need it eg. for getActiveNetworkInfo() -->
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
|
||||
<!-- <uses-permission android:name="android.permission.GET_ACCOUNTS" /> - required for AccountManager -->
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
|
||||
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS"/>
|
||||
<uses-permission android:name="android.permission.READ_PROFILE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"/>
|
||||
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/>
|
||||
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>
|
||||
<!-- <uses-permission android:name="android.permission.WRITE_CONTACTS" /> -->
|
||||
<!-- <uses-permission android:name="android.permission.MANAGE_ACCOUNTS"/> - required for AccountManager in API level <= 22 -->
|
||||
<!-- <uses-permission android:name="android.permission.READ_PROFILE"/> - required for ContactsContract.Profile -->
|
||||
<!-- <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"/> required for AbstractThreadedSyncAdapter-->
|
||||
<!-- <uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/> - required for AbstractThreadedSyncAdapter -->
|
||||
<!-- <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/> - seems to be unneeded and is no longer supported by Android, was needed for AbstractAccountAuthenticator, see http://stackoverflow.com/questions/32601456/marshmallow-permission-implementation#36907308 -->
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<!-- <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> - required for windows using the TYPE_SYSTEM_ALERT flag -->
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!-- we need the TelephonyManager to pause the audio player on calls -->
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
|
||||
<uses-permission android:name="android.permission.INSTALL_SHORTCUT" />
|
||||
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
|
||||
<uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"/>
|
||||
<!--<uses-permission android:name="android.permission.CAMERA" />-->
|
||||
<!-- <uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT" /> - required for AndroidUtilities.uninstallShortcut() -->
|
||||
<!-- <uses-permission android:name="android.permission.CAMERA" /> - also disabled in T'gram; we're using the camera via an intent only -->
|
||||
|
||||
<application
|
||||
android:name=".ApplicationLoader"
|
||||
android:allowBackup="false"
|
||||
android:hardwareAccelerated="@bool/useHardwareAcceleration"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/AppName"
|
||||
android:largeHeap="true"
|
||||
android:theme="@style/Theme.MessengerProj.Start"
|
||||
android:manageSpaceActivity="com.b44t.ui.ManageSpaceActivity">
|
||||
@@ -113,7 +114,7 @@
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:scheme="tg" />
|
||||
</intent-filter> -->
|
||||
<meta-data android:name="android.service.chooser.chooser_target_service" android:value=".TgChooserTargetService" />
|
||||
<!-- see note below, <meta-data android:name="android.service.chooser.chooser_target_service" android:value=".TgChooserTargetService" /> -->
|
||||
</activity>
|
||||
<activity
|
||||
android:name="com.b44t.ui.ManageSpaceActivity"
|
||||
@@ -131,15 +132,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"
|
||||
@@ -165,6 +157,7 @@
|
||||
</receiver>
|
||||
-->
|
||||
|
||||
<!-- currently, we do not use the android account system
|
||||
<service android:name=".AuthenticatorService" android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.accounts.AccountAuthenticator"/>
|
||||
@@ -172,7 +165,9 @@
|
||||
<meta-data android:name="android.accounts.AccountAuthenticator"
|
||||
android:resource="@xml/auth"/>
|
||||
</service>
|
||||
-->
|
||||
|
||||
<!-- seems to be not needed, derived from AbstractThreadedSyncAdapter, would need the READ/WRITE_SYNC_SETTINGS
|
||||
<service android:name=".ContactsSyncAdapterService" android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.content.SyncAdapter" />
|
||||
@@ -182,7 +177,11 @@
|
||||
<meta-data android:name="android.provider.CONTACTS_STRUCTURE"
|
||||
android:resource="@xml/contacts" />
|
||||
</service>
|
||||
-->
|
||||
|
||||
<!-- this would implement the "direct share" functionality (the system shows some direct links eg.
|
||||
to the most recent chats when calling "share" from another app, see https://developer.android.com/reference/android/service/chooser/ChooserTargetService.html )
|
||||
however, if we want this feature, we have to reimplement TgChooserTargetService or sth. like that.
|
||||
<service
|
||||
android:name="com.b44t.messenger.TgChooserTargetService"
|
||||
android:label="@string/AppName"
|
||||
@@ -190,18 +189,18 @@
|
||||
<intent-filter>
|
||||
<action android:name="android.service.chooser.ChooserTargetService" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
</service> -->
|
||||
|
||||
<service android:name=".NotificationsService" android:enabled="true"/>
|
||||
<service android:name=".NotificationRepeat" android:exported="false"/>
|
||||
<service android:name=".ClearCacheService" android:exported="false"/>
|
||||
<service android:name=".VideoEncodingService" android:enabled="true"/>
|
||||
<service android:name=".MusicPlayerService" android:exported="true" android:enabled="true"/>
|
||||
<!-- Do not expose data through MediaBrowserService, this seems unexpected for an messenger.
|
||||
Instead, the user can use 'save to music' or 'share' explicitly for items not privacy related.
|
||||
<service android:name=".MusicBrowserService" android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.media.browse.MediaBrowserService"/>
|
||||
</intent-filter>
|
||||
</service>
|
||||
</service> -->
|
||||
|
||||
<receiver android:name=".MusicPlayerReceiver" >
|
||||
<intent-filter>
|
||||
@@ -225,10 +224,14 @@
|
||||
<receiver android:name=".WearReplyReceiver" android:enabled="true"/>
|
||||
<!-- <receiver android:name=".NetworkAlarm" android:enabled="true"/> -->
|
||||
|
||||
<!-- seems to be unneeded (bp)
|
||||
<receiver android:name=".ShareBroadcastReceiver" android:enabled="true"/>
|
||||
-->
|
||||
|
||||
<receiver android:name=".NotificationDismissReceiver" android:exported="false"/>
|
||||
|
||||
<provider android:name=".AttachmentsContentProvider" android:authorities="${applicationId}.attachments" android:exported="true" />
|
||||
|
||||
<uses-library android:name="com.sec.android.app.multiwindow" android:required="false" />
|
||||
<meta-data android:name="com.sec.android.support.multiwindow" android:value="true" />
|
||||
<meta-data android:name="com.sec.android.multiwindow.DEFAULT_SIZE_W" android:value="632dp" />
|
||||
|
||||
Binary file not shown.
@@ -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.
Binary file not shown.
@@ -1,40 +1,46 @@
|
||||
/*
|
||||
* 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.Manifest;
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.DownloadManager;
|
||||
import android.content.ContentUris;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
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.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Shader;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
@@ -56,10 +62,9 @@ import android.widget.AbsListView;
|
||||
import android.widget.EdgeEffect;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ListView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.b44t.ui.ActionBar.BaseFragment;
|
||||
import com.b44t.ui.Components.ForegroundDetector;
|
||||
import com.b44t.ui.Components.TypefaceSpan;
|
||||
|
||||
@@ -72,6 +77,7 @@ import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
@@ -81,12 +87,7 @@ import java.util.regex.Pattern;
|
||||
|
||||
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,10 +99,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 {
|
||||
final String GOOD_IRI_CHAR = "a-zA-Z0-9\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF";
|
||||
@@ -115,15 +112,6 @@ public class AndroidUtilities {
|
||||
final String GTLD = "[" + GOOD_GTLD_CHAR + "]{2,63}";
|
||||
final String HOST_NAME = "(" + IRI + "\\.)+" + GTLD;
|
||||
final Pattern DOMAIN_NAME = Pattern.compile("(" + HOST_NAME + "|" + IP_ADDRESS + ")");
|
||||
WEB_URL = Pattern.compile(
|
||||
"((?:(http|https|Http|Https):\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)"
|
||||
+ "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,64}(?:\\:(?:[a-zA-Z0-9\\$\\-\\_"
|
||||
+ "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@)?)?"
|
||||
+ "(?:" + DOMAIN_NAME + ")"
|
||||
+ "(?:\\:\\d{1,5})?)" // plus option port number
|
||||
+ "(\\/(?:(?:[" + GOOD_IRI_CHAR + "\\;\\/\\?\\:\\@\\&\\=\\#\\~" // plus option query params
|
||||
+ "\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])|(?:\\%[a-fA-F0-9]{2}))*)?"
|
||||
+ "(?:\\b|$)");
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
@@ -135,101 +123,6 @@ public class AndroidUtilities {
|
||||
checkDisplaySize();
|
||||
}
|
||||
|
||||
public static int[] calcDrawableColor(Drawable drawable) {
|
||||
int bitmapColor = 0xff000000;
|
||||
int result[] = new int[2];
|
||||
try {
|
||||
if (drawable instanceof BitmapDrawable) {
|
||||
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
|
||||
if (bitmap != null) {
|
||||
Bitmap b = Bitmaps.createScaledBitmap(bitmap, 1, 1, true);
|
||||
if (b != null) {
|
||||
bitmapColor = b.getPixel(0, 0);
|
||||
b.recycle();
|
||||
}
|
||||
}
|
||||
} else if (drawable instanceof ColorDrawable) {
|
||||
bitmapColor = ((ColorDrawable) drawable).getColor();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
|
||||
double[] hsv = rgbToHsv((bitmapColor >> 16) & 0xff, (bitmapColor >> 8) & 0xff, bitmapColor & 0xff);
|
||||
hsv[1] = Math.min(1.0, hsv[1] + 0.05 + 0.1 * (1.0 - hsv[1]));
|
||||
hsv[2] = Math.max(0, hsv[2] * 0.65);
|
||||
int rgb[] = hsvToRgb(hsv[0], hsv[1], hsv[2]);
|
||||
result[0] = Color.argb(0x66, rgb[0], rgb[1], rgb[2]);
|
||||
result[1] = Color.argb(0x88, rgb[0], rgb[1], rgb[2]);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static double[] rgbToHsv(int r, int g, int b) {
|
||||
double rf = r / 255.0;
|
||||
double gf = g / 255.0;
|
||||
double bf = b / 255.0;
|
||||
double max = (rf > gf && rf > bf) ? rf : (gf > bf) ? gf : bf;
|
||||
double min = (rf < gf && rf < bf) ? rf : (gf < bf) ? gf : bf;
|
||||
double h, s;
|
||||
double d = max - min;
|
||||
s = max == 0 ? 0 : d / max;
|
||||
if (max == min) {
|
||||
h = 0;
|
||||
} else {
|
||||
if (rf > gf && rf > bf) {
|
||||
h = (gf - bf) / d + (gf < bf ? 6 : 0);
|
||||
} else if (gf > bf) {
|
||||
h = (bf - rf) / d + 2;
|
||||
} else {
|
||||
h = (rf - gf) / d + 4;
|
||||
}
|
||||
h /= 6;
|
||||
}
|
||||
return new double[]{h, s, max};
|
||||
}
|
||||
|
||||
private static int[] hsvToRgb(double h, double s, double v) {
|
||||
double r = 0, g = 0, b = 0;
|
||||
double i = (int) Math.floor(h * 6);
|
||||
double f = h * 6 - i;
|
||||
double p = v * (1 - s);
|
||||
double q = v * (1 - f * s);
|
||||
double t = v * (1 - (1 - f) * s);
|
||||
switch ((int) i % 6) {
|
||||
case 0:
|
||||
r = v;
|
||||
g = t;
|
||||
b = p;
|
||||
break;
|
||||
case 1:
|
||||
r = q;
|
||||
g = v;
|
||||
b = p;
|
||||
break;
|
||||
case 2:
|
||||
r = p;
|
||||
g = v;
|
||||
b = t;
|
||||
break;
|
||||
case 3:
|
||||
r = p;
|
||||
g = q;
|
||||
b = v;
|
||||
break;
|
||||
case 4:
|
||||
r = t;
|
||||
g = p;
|
||||
b = v;
|
||||
break;
|
||||
case 5:
|
||||
r = v;
|
||||
g = p;
|
||||
b = q;
|
||||
break;
|
||||
}
|
||||
return new int[]{(int) (r * 255), (int) (g * 255), (int) (b * 255)};
|
||||
}
|
||||
|
||||
public static void requestAdjustResize(Activity activity, int classGuid) {
|
||||
if (activity == null || isTablet()) {
|
||||
return;
|
||||
@@ -247,34 +140,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) {
|
||||
@@ -346,49 +211,6 @@ public class AndroidUtilities {
|
||||
}
|
||||
}
|
||||
|
||||
public static Typeface getTypeface(String assetPath) {
|
||||
synchronized (typefaceCache) {
|
||||
if (!typefaceCache.containsKey(assetPath)) {
|
||||
try {
|
||||
Typeface t = Typeface.createFromAsset(ApplicationLoader.applicationContext.getAssets(), assetPath);
|
||||
typefaceCache.put(assetPath, t);
|
||||
} catch (Exception e) {
|
||||
FileLog.e("Typefaces", "Could not get typeface '" + assetPath + "' because " + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return typefaceCache.get(assetPath);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -401,19 +223,6 @@ public class AndroidUtilities {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isKeyboardShowed(View view) {
|
||||
if (view == null) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
InputMethodManager inputManager = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
return inputManager.isActive(view);
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void hideKeyboard(View view) {
|
||||
if (view == null) {
|
||||
return;
|
||||
@@ -429,6 +238,7 @@ public class AndroidUtilities {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
public static File getCacheDir() {
|
||||
String state = null;
|
||||
try {
|
||||
@@ -456,6 +266,7 @@ public class AndroidUtilities {
|
||||
}
|
||||
return new File("");
|
||||
}
|
||||
*/
|
||||
|
||||
public static int dp(float value) {
|
||||
if (value == 0) {
|
||||
@@ -502,10 +313,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);
|
||||
}
|
||||
@@ -564,97 +371,6 @@ public class AndroidUtilities {
|
||||
return photoSize;
|
||||
}
|
||||
|
||||
public static String formatTTLString(int ttl) {
|
||||
if (ttl < 60) {
|
||||
return LocaleController.formatPluralString("Seconds", ttl);
|
||||
} else if (ttl < 60 * 60) {
|
||||
return LocaleController.formatPluralString("Minutes", ttl / 60);
|
||||
} else if (ttl < 60 * 60 * 24) {
|
||||
return LocaleController.formatPluralString("Hours", ttl / 60 / 60);
|
||||
} else if (ttl < 60 * 60 * 24 * 7) {
|
||||
return LocaleController.formatPluralString("Days", ttl / 60 / 60 / 24);
|
||||
} else {
|
||||
int days = ttl / 60 / 60 / 24;
|
||||
if (ttl % 7 == 0) {
|
||||
return LocaleController.formatPluralString("Weeks", days / 7);
|
||||
} else {
|
||||
return String.format("%s %s", LocaleController.formatPluralString("Weeks", days / 7), LocaleController.formatPluralString("Days", days % 7));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
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;
|
||||
@@ -668,71 +384,13 @@ public class AndroidUtilities {
|
||||
}
|
||||
}
|
||||
|
||||
public static void setProgressBarAnimationDuration(ProgressBar progressBar, int duration) {
|
||||
if (progressBar == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Field mCursorDrawableRes = ProgressBar.class.getDeclaredField("mDuration");
|
||||
mCursorDrawableRes.setAccessible(true);
|
||||
mCursorDrawableRes.setInt(progressBar, duration);
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
}
|
||||
|
||||
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 +398,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,15 +414,18 @@ public class AndroidUtilities {
|
||||
}
|
||||
}
|
||||
|
||||
public static void uninstallShortcut(long did) {
|
||||
/* -- uninstalling shortcuts would be needed if a chat is deleted. However,
|
||||
-- com.b44t.messenger.openchatNNN just opens the overview in this case, which is okay for the moment.
|
||||
-- uninstalling shortcuts would required the permission com.android.launcher.permission.UNINSTALL_SHORTCUT
|
||||
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) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
public static int getViewInset(View view) {
|
||||
if (view == null || Build.VERSION.SDK_INT < 21 || view.getHeight() == AndroidUtilities.displaySize.y || view.getHeight() == AndroidUtilities.displaySize.y - statusBarHeight) {
|
||||
@@ -969,7 +575,7 @@ public class AndroidUtilities {
|
||||
}
|
||||
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(stringBuilder);
|
||||
for (int a = 0; a < bolds.size() / 2; a++) {
|
||||
spannableStringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")), bolds.get(a * 2), bolds.get(a * 2 + 1), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
spannableStringBuilder.setSpan(new TypefaceSpan(Typeface.DEFAULT_BOLD), bolds.get(a * 2), bolds.get(a * 2 + 1), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
for (int a = 0; a < colors.size() / 3; a++) {
|
||||
spannableStringBuilder.setSpan(new ForegroundColorSpan(colors.get(a * 3 + 2)), colors.get(a * 3), colors.get(a * 3 + 1), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
@@ -1007,54 +613,25 @@ 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 showDoneHint(Context context)
|
||||
{
|
||||
// this hint should be shown when an action is complete and not directly visible on the screen,
|
||||
// eg. copy-to-clipboard or item deletion in a long list
|
||||
Toast.makeText(context, ApplicationLoader.applicationContext.getString(R.string.DoneHint), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
/*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 showErrorHint(Context context)
|
||||
{
|
||||
// this hint should be shown on errors that normally should not happen.
|
||||
showHint(context, ApplicationLoader.applicationContext.getString(R.string.ErrorHint));
|
||||
}
|
||||
|
||||
public static Toast showHint(Context context, String text)
|
||||
{
|
||||
Toast t = Toast.makeText(context, text, Toast.LENGTH_LONG);
|
||||
t.show();
|
||||
return t;
|
||||
}
|
||||
|
||||
public static void addToClipboard(CharSequence str) {
|
||||
try {
|
||||
@@ -1211,49 +788,6 @@ public class AndroidUtilities {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static CharSequence generateSearchName(String name, String name2, String q) {
|
||||
if (name == null && name2 == null) {
|
||||
return "";
|
||||
}
|
||||
SpannableStringBuilder builder = new SpannableStringBuilder();
|
||||
String wholeString = name;
|
||||
if (wholeString == null || wholeString.length() == 0) {
|
||||
wholeString = name2;
|
||||
} else if (name2 != null && name2.length() != 0) {
|
||||
wholeString += " " + name2;
|
||||
}
|
||||
wholeString = wholeString.trim();
|
||||
String lower = " " + wholeString.toLowerCase();
|
||||
|
||||
int index;
|
||||
int lastIndex = 0;
|
||||
while ((index = lower.indexOf(" " + q, lastIndex)) != -1) {
|
||||
int idx = index - (index == 0 ? 0 : 1);
|
||||
int end = q.length() + (index == 0 ? 0 : 1) + idx;
|
||||
|
||||
if (lastIndex != 0 && lastIndex != idx + 1) {
|
||||
builder.append(wholeString.substring(lastIndex, idx));
|
||||
} else if (lastIndex == 0 && idx != 0) {
|
||||
builder.append(wholeString.substring(0, idx));
|
||||
}
|
||||
|
||||
String query = wholeString.substring(idx, end);
|
||||
if (query.startsWith(" ")) {
|
||||
builder.append(" ");
|
||||
}
|
||||
query = query.trim();
|
||||
builder.append(AndroidUtilities.replaceTags("<c#ff4d83b3>" + query + "</c>"));
|
||||
|
||||
lastIndex = end;
|
||||
}
|
||||
|
||||
if (lastIndex != -1 && lastIndex != wholeString.length()) {
|
||||
builder.append(wholeString.substring(lastIndex, wholeString.length()));
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static File generateVideoPath() {
|
||||
try {
|
||||
File storageDir = getAlbumDir();
|
||||
@@ -1265,15 +799,15 @@ public class AndroidUtilities {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String formatFileSize(long size) {
|
||||
if (size < 1024) {
|
||||
return String.format("%d B", size);
|
||||
} else if (size < 1024 * 1024) {
|
||||
return String.format("%.1f KB", size / 1024.0f);
|
||||
} else if (size < 1024 * 1024 * 1024) {
|
||||
return String.format("%.1f MB", size / 1024.0f / 1024.0f);
|
||||
public static String formatFileSize(long bytes) {
|
||||
// We use the SI-prefix with the usual base as defined in the 1990's.
|
||||
// The other option would be to show MiB and KiB, however, these abbreviations are not very usual.
|
||||
if (bytes < 1000) {
|
||||
return String.format("%d Byte", bytes);
|
||||
} else if (bytes < (1000 * 1000)-500) { // 999499 Byte=999 KB, 999500 Byte=1,0 MB
|
||||
return String.format("%.0f KB", bytes / 1000.0f);
|
||||
} else {
|
||||
return String.format("%.1f GB", size / 1024.0f / 1024.0f / 1024.0f);
|
||||
return String.format("%.1f MB", bytes / 1000.0f / 1000.0f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1342,56 +876,186 @@ public class AndroidUtilities {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static byte[] calcAuthKeyHash(byte[] auth_key) {
|
||||
byte[] sha1 = Utilities.computeSHA1(auth_key);
|
||||
byte[] key_hash = new byte[16];
|
||||
System.arraycopy(sha1, 0, key_hash, 0, 16);
|
||||
return key_hash;
|
||||
}
|
||||
/* open, view, download files
|
||||
**********************************************************************************************/
|
||||
|
||||
public static void openForView(MessageObject message, Activity activity) throws Exception {
|
||||
File f = null;
|
||||
String fileName = message.getFileName();
|
||||
if (message.messageOwner.attachPath != null && message.messageOwner.attachPath.length() != 0) {
|
||||
f = new File(message.messageOwner.attachPath);
|
||||
}
|
||||
if (f == null || !f.exists()) {
|
||||
f = FileLoader.getPathToMessage(message.messageOwner);
|
||||
}
|
||||
if (f != null && f.exists()) {
|
||||
String realMimeType = null;
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
MimeTypeMap myMime = MimeTypeMap.getSingleton();
|
||||
public static String getMimetype(String fileName, String def)
|
||||
{
|
||||
String mimeType = "application/octet-stream";
|
||||
try {
|
||||
MimeTypeMap mimeMap = MimeTypeMap.getSingleton();
|
||||
int idx = fileName.lastIndexOf('.');
|
||||
if (idx != -1) {
|
||||
String ext = fileName.substring(idx + 1);
|
||||
realMimeType = myMime.getMimeTypeFromExtension(ext.toLowerCase());
|
||||
if (realMimeType == null) {
|
||||
if (message.type == 9 || message.type == 0) {
|
||||
realMimeType = message.getDocument().mime_type;
|
||||
}
|
||||
if (realMimeType == null || realMimeType.length() == 0) {
|
||||
realMimeType = null;
|
||||
}
|
||||
}
|
||||
if (realMimeType != null) {
|
||||
intent.setDataAndType(Uri.fromFile(f), realMimeType);
|
||||
} else {
|
||||
intent.setDataAndType(Uri.fromFile(f), "text/plain");
|
||||
}
|
||||
} else {
|
||||
intent.setDataAndType(Uri.fromFile(f), "text/plain");
|
||||
mimeType = mimeMap.getMimeTypeFromExtension(ext.toLowerCase());
|
||||
}
|
||||
if (realMimeType != null) {
|
||||
try {
|
||||
activity.startActivityForResult(intent, 500);
|
||||
} catch (Exception e) {
|
||||
intent.setDataAndType(Uri.fromFile(f), "text/plain");
|
||||
activity.startActivityForResult(intent, 500);
|
||||
}
|
||||
} else {
|
||||
activity.startActivityForResult(intent, 500);
|
||||
if (mimeType == null) {
|
||||
mimeType = def==null? "application/octet-stream" : def;
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
}
|
||||
return mimeType;
|
||||
}
|
||||
|
||||
public static void openForViewOrShare(Activity activity, int msg_id, String cmd)
|
||||
{
|
||||
MrMsg msg = MrMailbox.getMsg(msg_id);
|
||||
String path = msg.getParam('f', "");
|
||||
String mimeType = getMimetype(path, msg.getParam('m', "application/octet-stream"));
|
||||
try {
|
||||
File file = new File(path);
|
||||
if( !file.exists() ) {
|
||||
showHint(activity, LocaleController.formatString("FileNotFound", R.string.FileNotFound, path));
|
||||
return;
|
||||
}
|
||||
|
||||
Uri uri;
|
||||
if (path.startsWith(MrMailbox.getBlobdir())) {
|
||||
uri = Uri.parse("content://" + BuildConfig.APPLICATION_ID + ".attachments/" + file.getName());
|
||||
} else {
|
||||
uri = Uri.fromFile(file);
|
||||
}
|
||||
|
||||
if( cmd == Intent.ACTION_VIEW ) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setDataAndType(uri, mimeType);
|
||||
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
activity.startActivity(intent);
|
||||
}
|
||||
else {
|
||||
Intent intent = new Intent(Intent.ACTION_SEND);
|
||||
intent.setType(mimeType);
|
||||
intent.putExtra(Intent.EXTRA_STREAM, uri);
|
||||
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
activity.startActivity(Intent.createChooser(intent, ApplicationLoader.applicationContext.getString(R.string.Share)));
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
showHint(activity, LocaleController.formatString("NoHandleAppInstalled", R.string.NoHandleAppInstalled, mimeType));
|
||||
}
|
||||
}
|
||||
|
||||
public static File getFineFilename(File path, String desiredName)
|
||||
{
|
||||
// get a fine file name by adding a number to the basename and avoid overwrites
|
||||
for( int i = 0; i < 1000; i++ ) {
|
||||
String testName = desiredName;
|
||||
if( i > 0 ) {
|
||||
String baseName=desiredName, ext = "";
|
||||
int idx = desiredName.lastIndexOf('.');
|
||||
if( idx != -1 ) {
|
||||
baseName = desiredName.substring(0, idx);
|
||||
ext = desiredName.substring(idx);
|
||||
}
|
||||
testName = String.format("%s-%d%s", baseName, i, ext);
|
||||
}
|
||||
File pathNFile = new File(path, testName);
|
||||
if (!pathNFile.exists()) {
|
||||
return pathNFile;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void saveMessageFileToExt(final Activity context, int msg_id)
|
||||
{
|
||||
if (Build.VERSION.SDK_INT >= 23 && context.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||
context.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 4);
|
||||
return;
|
||||
}
|
||||
|
||||
MrMsg msg = MrMailbox.getMsg(msg_id);
|
||||
final int msg_type = msg.getType();
|
||||
String msg_file_path = msg.getParam('f', "");
|
||||
final String msg_mime = msg.getParam('m', "application/octet-stream");
|
||||
final String msg_file_name = msg.getFilename();
|
||||
final File sourceFile = new File(msg_file_path);
|
||||
if( !sourceFile.exists() ) {
|
||||
showHint(context, LocaleController.formatString("FileNotFound", R.string.FileNotFound, msg_file_path));
|
||||
return;
|
||||
}
|
||||
|
||||
final Toast waitingHint = showHint(context, ApplicationLoader.applicationContext.getString(R.string.OneMoment));
|
||||
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
boolean allOkay = false;
|
||||
|
||||
try {
|
||||
// get destination path
|
||||
File destPath = null;
|
||||
boolean add_to_download_manager = false;
|
||||
if (msg_type == MrMsg.MR_MSG_IMAGE || msg_type == MrMsg.MR_MSG_VIDEO) {
|
||||
destPath = AndroidUtilities.getAlbumDir();
|
||||
} else if (msg_type == MrMsg.MR_MSG_FILE) {
|
||||
destPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
|
||||
add_to_download_manager = true;
|
||||
} else if (msg_type == MrMsg.MR_MSG_AUDIO || msg_type == MrMsg.MR_MSG_VOICE ) {
|
||||
destPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC);
|
||||
}
|
||||
|
||||
// create destination path (must be done, see documentation for getExternalStoragePublicDirectory())
|
||||
destPath.mkdirs();
|
||||
|
||||
File destPathNFile = getFineFilename(destPath, msg_file_name);
|
||||
if( destPathNFile != null )
|
||||
{
|
||||
destPathNFile.createNewFile();
|
||||
boolean copied = true;
|
||||
FileChannel source = null;
|
||||
FileChannel destination = null;
|
||||
try {
|
||||
source = new FileInputStream(sourceFile).getChannel();
|
||||
destination = new FileOutputStream(destPathNFile).getChannel();
|
||||
long size = source.size();
|
||||
for (long a = 0; a < size; a += 4096) {
|
||||
destination.transferFrom(source, a, Math.min(4096, size - a));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
copied = false;
|
||||
} finally {
|
||||
if (source != null) {
|
||||
source.close();
|
||||
}
|
||||
if (destination != null) {
|
||||
destination.close();
|
||||
}
|
||||
}
|
||||
|
||||
if (copied) {
|
||||
if ( add_to_download_manager ) {
|
||||
DownloadManager downloadManager = (DownloadManager) ApplicationLoader.applicationContext.getSystemService(Context.DOWNLOAD_SERVICE);
|
||||
downloadManager.addCompletedDownload(destPathNFile.getName(), destPathNFile.getName(), false, getMimetype(msg_file_name, msg_mime), destPathNFile.getAbsolutePath(), destPathNFile.length(), true);
|
||||
} else {
|
||||
addMediaToGallery(Uri.fromFile(destPathNFile));
|
||||
}
|
||||
allOkay = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
;
|
||||
}
|
||||
|
||||
final boolean allOkayFinal = allOkay;
|
||||
AndroidUtilities.runOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
waitingHint.cancel();
|
||||
if( allOkayFinal ) {
|
||||
showDoneHint(context);
|
||||
}
|
||||
else {
|
||||
showHint(context, ApplicationLoader.applicationContext.getString(R.string.AccessError));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -38,9 +53,6 @@ public class ApplicationLoader extends Application {
|
||||
private static boolean isCustomTheme;
|
||||
private static final Object sync = new Object();
|
||||
|
||||
private static int serviceMessageColor;
|
||||
private static int serviceSelectedMessageColor;
|
||||
|
||||
public static volatile Context applicationContext;
|
||||
public static volatile Handler applicationHandler;
|
||||
private static volatile boolean applicationInited = false;
|
||||
@@ -58,25 +70,11 @@ public class ApplicationLoader extends Application {
|
||||
|
||||
public static void reloadWallpaper() {
|
||||
cachedWallpaper = null;
|
||||
serviceMessageColor = 0;
|
||||
ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE).edit().remove("serviceMessageColor").commit();
|
||||
loadWallpaper();
|
||||
}
|
||||
|
||||
private static void calcBackgroundColor() {
|
||||
int result[] = AndroidUtilities.calcDrawableColor(cachedWallpaper);
|
||||
serviceMessageColor = result[0];
|
||||
serviceSelectedMessageColor = result[1];
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
|
||||
preferences.edit().putInt("serviceMessageColor", serviceMessageColor).putInt("serviceSelectedMessageColor", serviceSelectedMessageColor).commit();
|
||||
}
|
||||
|
||||
public static int getServiceMessageColor() {
|
||||
return serviceMessageColor;
|
||||
}
|
||||
|
||||
public static int getServiceSelectedMessageColor() {
|
||||
return serviceSelectedMessageColor;
|
||||
return 0x44000000; // this color is used as a background for date headlines, empty chat hints and in the drawer
|
||||
}
|
||||
|
||||
public static void loadWallpaper() {
|
||||
@@ -92,8 +90,6 @@ public class ApplicationLoader extends Application {
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
|
||||
int selectedBackground = preferences.getInt("selectedBackground", 1000001);
|
||||
selectedColor = preferences.getInt("selectedColor", 0);
|
||||
serviceMessageColor = preferences.getInt("serviceMessageColor", 0);
|
||||
serviceSelectedMessageColor = preferences.getInt("serviceSelectedMessageColor", 0);
|
||||
if (selectedColor == 0) {
|
||||
if (selectedBackground == 1000001) {
|
||||
cachedWallpaper = applicationContext.getResources().getDrawable(R.drawable.background_hd);
|
||||
@@ -118,9 +114,6 @@ public class ApplicationLoader extends Application {
|
||||
}
|
||||
cachedWallpaper = new ColorDrawable(selectedColor);
|
||||
}
|
||||
if (serviceMessageColor == 0) {
|
||||
calcBackgroundColor();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -183,26 +176,20 @@ public class ApplicationLoader extends Application {
|
||||
|
||||
UserConfig.loadConfig();
|
||||
String deviceModel;
|
||||
String langCode;
|
||||
String appVersion;
|
||||
String systemVersion;
|
||||
String configPath = getFilesDirFixed().toString();
|
||||
|
||||
try {
|
||||
langCode = LocaleController.getLocaleStringIso639();
|
||||
deviceModel = Build.MANUFACTURER + Build.MODEL;
|
||||
PackageInfo pInfo = ApplicationLoader.applicationContext.getPackageManager().getPackageInfo(ApplicationLoader.applicationContext.getPackageName(), 0);
|
||||
appVersion = pInfo.versionName + " (" + pInfo.versionCode + ")";
|
||||
systemVersion = "SDK " + Build.VERSION.SDK_INT;
|
||||
} catch (Exception e) {
|
||||
langCode = "en";
|
||||
deviceModel = "Android unknown";
|
||||
appVersion = "App version unknown";
|
||||
systemVersion = "SDK " + Build.VERSION.SDK_INT;
|
||||
}
|
||||
if (langCode.trim().length() == 0) {
|
||||
langCode = "en";
|
||||
}
|
||||
if (deviceModel.trim().length() == 0) {
|
||||
deviceModel = "Android unknown";
|
||||
}
|
||||
@@ -220,26 +207,22 @@ public class ApplicationLoader extends Application {
|
||||
// make sure, the notifications for the "deaddrop" dialog are muted by default
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putInt("notify2_"+MrChat.MR_CHAT_ID_DEADDROP, 2);
|
||||
editor.commit();
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
// 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);
|
||||
ConnectionsManager.getInstance().init();
|
||||
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 +238,12 @@ 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));
|
||||
|
||||
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);
|
||||
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* 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;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
|
||||
public class AttachmentsContentProvider extends ContentProvider {
|
||||
|
||||
/* We save all attachments in our private files-directory
|
||||
that cannot be read by other apps.
|
||||
|
||||
So starting, when starting an Intent for viewing (eg. openForView()), we cannot use the paths.
|
||||
Instead, we give a content://-url that results in calls to this class.
|
||||
|
||||
(An alternative would be to copy files to view to a public directory, however, this would
|
||||
lead to duplicate data.
|
||||
Another alterntive would be to write all attachments to a public directory, however, this
|
||||
may lead to security problems as files are system-wide-readable and would also cause problems
|
||||
if the user or another app deletes these files) */
|
||||
|
||||
@Override
|
||||
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
|
||||
File privateFile = new File(MrMailbox.getBlobdir(), uri.getPath());
|
||||
return ParcelFileDescriptor.open(privateFile, ParcelFileDescriptor.MODE_READ_ONLY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int delete(Uri arg0, String arg1, String[] arg2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType(Uri arg0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri insert(Uri arg0, ContentValues arg1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor query(Uri arg0, String[] arg1, String arg2, String[] arg3,
|
||||
String arg4) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,97 +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;
|
||||
|
||||
import android.accounts.AbstractAccountAuthenticator;
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountAuthenticatorResponse;
|
||||
import android.accounts.AccountManager;
|
||||
import android.accounts.NetworkErrorException;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
|
||||
public class AuthenticatorService extends Service {
|
||||
|
||||
private static class Authenticator extends AbstractAccountAuthenticator {
|
||||
private final Context context;
|
||||
|
||||
public Authenticator(Context context) {
|
||||
super(context);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options)
|
||||
throws NetworkErrorException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle getAccountRemovalAllowed(AccountAuthenticatorResponse response, Account account) throws NetworkErrorException {
|
||||
return super.getAccountRemovalAllowed(response, account);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) throws NetworkErrorException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options)
|
||||
throws NetworkErrorException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthTokenLabel(String authTokenType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle hasFeatures(AccountAuthenticatorResponse response,
|
||||
Account account, String[] features)
|
||||
throws NetworkErrorException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options)
|
||||
throws NetworkErrorException {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static Authenticator authenticator = null;
|
||||
|
||||
protected Authenticator getAuthenticator() {
|
||||
if (authenticator == null) {
|
||||
authenticator = new Authenticator(this);
|
||||
}
|
||||
return authenticator;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
if (intent.getAction().equals(AccountManager.ACTION_AUTHENTICATOR_INTENT)) {
|
||||
return getAuthenticator().getIBinder();
|
||||
} else {
|
||||
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;
|
||||
|
||||
@@ -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);
|
||||
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,82 +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;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.IntentService;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Build;
|
||||
import android.system.Os;
|
||||
import android.system.StructStat;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class ClearCacheService extends IntentService {
|
||||
|
||||
public ClearCacheService() {
|
||||
super("ClearCacheService");
|
||||
}
|
||||
|
||||
@Override
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
Utilities.globalQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
long diff = 60 * 60 * 1000 * 24 * (keepMedia == 0 ? 7 : 30);
|
||||
final HashMap<Integer, File> paths = ImageLoader.getInstance().createMediaPaths();
|
||||
for (HashMap.Entry<Integer, File> entry : paths.entrySet()) {
|
||||
if (entry.getKey() == FileLoader.MEDIA_DIR_CACHE) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
File[] array = entry.getValue().listFiles();
|
||||
if (array != null) {
|
||||
for (int b = 0; b < array.length; b++) {
|
||||
File f = array[b];
|
||||
if (f.isFile()) {
|
||||
if (f.getName().equals(".nomedia")) {
|
||||
continue;
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
try {
|
||||
StructStat stat = Os.stat(f.getPath());
|
||||
if (stat.st_atime != 0) {
|
||||
if (stat.st_atime + diff < currentTime) {
|
||||
f.delete();
|
||||
}
|
||||
} else if (stat.st_mtime + diff < currentTime) {
|
||||
f.delete();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
} else if (f.lastModified() + diff < currentTime) {
|
||||
f.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -73,7 +73,7 @@ public class ConnectionsManager {
|
||||
//native_setPushConnectionEnabled(value);
|
||||
}
|
||||
|
||||
public void init(String deviceModel, String systemVersion, String appVersion, String langCode, String configPath, String logPath, int userId, boolean enablePushConnection) {
|
||||
public void init() {
|
||||
//native_init(version, layer, apiId, deviceModel, systemVersion, appVersion, langCode, configPath, logPath, userId, enablePushConnection);
|
||||
//checkConnection();
|
||||
BroadcastReceiver networkStateReceiver = new BroadcastReceiver() {
|
||||
@@ -117,6 +117,7 @@ public class ConnectionsManager {
|
||||
return lastClassGuid++;
|
||||
}
|
||||
|
||||
/* -- leave this for future use
|
||||
public static boolean isRoaming() {
|
||||
try {
|
||||
ConnectivityManager cm = (ConnectivityManager) ApplicationLoader.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
@@ -128,8 +129,9 @@ public class ConnectionsManager {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} */
|
||||
|
||||
/* -- leave this for future use
|
||||
public static boolean isConnectedToWiFi() {
|
||||
try {
|
||||
ConnectivityManager cm = (ConnectivityManager) ApplicationLoader.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
@@ -141,17 +143,16 @@ public class ConnectionsManager {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} */
|
||||
|
||||
public static boolean isNetworkOnline() {
|
||||
try {
|
||||
ConnectivityManager cm = (ConnectivityManager) ApplicationLoader.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo netInfo = cm.getActiveNetworkInfo();
|
||||
if (netInfo != null && (netInfo.isConnectedOrConnecting() || netInfo.isAvailable())) {
|
||||
if (netInfo != null && netInfo.isConnected()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
netInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
|
||||
/* netInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
|
||||
|
||||
if (netInfo != null && netInfo.isConnectedOrConnecting()) {
|
||||
return true;
|
||||
@@ -160,10 +161,8 @@ public class ConnectionsManager {
|
||||
if (netInfo != null && netInfo.isConnectedOrConnecting()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} */
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -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,63 +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;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.OperationCanceledException;
|
||||
import android.app.Service;
|
||||
import android.content.AbstractThreadedSyncAdapter;
|
||||
import android.content.ContentProviderClient;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SyncResult;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
|
||||
public class ContactsSyncAdapterService extends Service {
|
||||
private static SyncAdapterImpl sSyncAdapter = null;
|
||||
|
||||
public ContactsSyncAdapterService() {
|
||||
super();
|
||||
}
|
||||
|
||||
private static class SyncAdapterImpl extends AbstractThreadedSyncAdapter {
|
||||
private Context mContext;
|
||||
|
||||
public SyncAdapterImpl(Context context) {
|
||||
super(context, true);
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
|
||||
try {
|
||||
ContactsSyncAdapterService.performSync(mContext, account, extras, authority, provider, syncResult);
|
||||
} catch (OperationCanceledException e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return getSyncAdapter().getSyncAdapterBinder();
|
||||
}
|
||||
|
||||
private SyncAdapterImpl getSyncAdapter() {
|
||||
if (sSyncAdapter == null) {
|
||||
sSyncAdapter = new SyncAdapterImpl(this);
|
||||
}
|
||||
return sSyncAdapter;
|
||||
}
|
||||
|
||||
private static void performSync(Context context, Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult)
|
||||
throws OperationCanceledException {
|
||||
FileLog.d("messenger", "performSync: " + account.toString());
|
||||
}
|
||||
}
|
||||
@@ -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,15 +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 DownloadObject {
|
||||
public TLObject object;
|
||||
public int type;
|
||||
public long id;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -18,11 +33,6 @@ import java.util.concurrent.Semaphore;
|
||||
public class FileLoader {
|
||||
|
||||
public interface FileLoaderDelegate {
|
||||
void fileUploadProgressChanged(String location, float progress, boolean isEncrypted);
|
||||
|
||||
void fileDidUploaded(String location, TLRPC.InputFile inputFile, TLRPC.InputEncryptedFile inputEncryptedFile, byte[] key, byte[] iv, long totalFileSize);
|
||||
|
||||
void fileDidFailedUpload(String location, boolean isEncrypted);
|
||||
|
||||
void fileDidLoaded(String location, File finalFile, int type);
|
||||
|
||||
@@ -40,23 +50,16 @@ public class FileLoader {
|
||||
private HashMap<Integer, File> mediaDirs = null;
|
||||
private volatile DispatchQueue fileLoaderQueue = new DispatchQueue("fileUploadQueue");
|
||||
|
||||
private LinkedList<FileUploadOperation> uploadOperationQueue = new LinkedList<>();
|
||||
private LinkedList<FileUploadOperation> uploadSmallOperationQueue = new LinkedList<>();
|
||||
private LinkedList<FileLoadOperation> loadOperationQueue = new LinkedList<>();
|
||||
private LinkedList<FileLoadOperation> audioLoadOperationQueue = new LinkedList<>();
|
||||
private LinkedList<FileLoadOperation> photoLoadOperationQueue = new LinkedList<>();
|
||||
private ConcurrentHashMap<String, FileUploadOperation> uploadOperationPaths = new ConcurrentHashMap<>();
|
||||
private ConcurrentHashMap<String, FileUploadOperation> uploadOperationPathsEnc = new ConcurrentHashMap<>();
|
||||
private ConcurrentHashMap<String, FileLoadOperation> loadOperationPaths = new ConcurrentHashMap<>();
|
||||
private HashMap<String, Long> uploadSizes = new HashMap<>();
|
||||
|
||||
private FileLoaderDelegate delegate = null;
|
||||
|
||||
private int currentLoadOperationsCount = 0;
|
||||
private int currentAudioLoadOperationsCount = 0;
|
||||
private int currentPhotoLoadOperationsCount = 0;
|
||||
private int currentUploadOperationsCount = 0;
|
||||
private int currentUploadSmallOperationsCount = 0;
|
||||
|
||||
private static volatile FileLoader Instance = null;
|
||||
|
||||
@@ -77,11 +80,7 @@ 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);
|
||||
@@ -96,160 +95,6 @@ public class FileLoader {
|
||||
return dir;
|
||||
}
|
||||
|
||||
/*
|
||||
public void checkUploadNewDataAvailable(final String location, final boolean encrypted, final long finalSize) {
|
||||
fileLoaderQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
FileUploadOperation operation;
|
||||
if (encrypted) {
|
||||
operation = uploadOperationPathsEnc.get(location);
|
||||
} else {
|
||||
operation = uploadOperationPaths.get(location);
|
||||
}
|
||||
if (operation != null) {
|
||||
operation.checkNewDataAvailable(finalSize);
|
||||
} else if (finalSize != 0) {
|
||||
uploadSizes.put(location, finalSize);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
public void uploadFile(final String location, final boolean encrypted, final boolean small) {
|
||||
uploadFile(location, encrypted, small, 0);
|
||||
}
|
||||
|
||||
public void uploadFile(final String location, final boolean encrypted, final boolean small, final int estimatedSize) {
|
||||
if (location == null) {
|
||||
return;
|
||||
}
|
||||
fileLoaderQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (encrypted) {
|
||||
if (uploadOperationPathsEnc.containsKey(location)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (uploadOperationPaths.containsKey(location)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
int esimated = estimatedSize;
|
||||
if (esimated != 0) {
|
||||
Long finalSize = uploadSizes.get(location);
|
||||
if (finalSize != null) {
|
||||
esimated = 0;
|
||||
uploadSizes.remove(location);
|
||||
}
|
||||
}
|
||||
FileUploadOperation operation = new FileUploadOperation(location, encrypted, esimated);
|
||||
if (encrypted) {
|
||||
uploadOperationPathsEnc.put(location, operation);
|
||||
} else {
|
||||
uploadOperationPaths.put(location, operation);
|
||||
}
|
||||
operation.delegate = new FileUploadOperation.FileUploadOperationDelegate() {
|
||||
@Override
|
||||
public void didFinishUploadingFile(final FileUploadOperation operation, final TLRPC.InputFile inputFile, final TLRPC.InputEncryptedFile inputEncryptedFile, final byte[] key, final byte[] iv) {
|
||||
fileLoaderQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (encrypted) {
|
||||
uploadOperationPathsEnc.remove(location);
|
||||
} else {
|
||||
uploadOperationPaths.remove(location);
|
||||
}
|
||||
if (small) {
|
||||
currentUploadSmallOperationsCount--;
|
||||
if (currentUploadSmallOperationsCount < 1) {
|
||||
FileUploadOperation operation = uploadSmallOperationQueue.poll();
|
||||
if (operation != null) {
|
||||
currentUploadSmallOperationsCount++;
|
||||
operation.start();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
currentUploadOperationsCount--;
|
||||
if (currentUploadOperationsCount < 1) {
|
||||
FileUploadOperation operation = uploadOperationQueue.poll();
|
||||
if (operation != null) {
|
||||
currentUploadOperationsCount++;
|
||||
operation.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (delegate != null) {
|
||||
delegate.fileDidUploaded(location, inputFile, inputEncryptedFile, key, iv, operation.getTotalFileSize());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void didFailedUploadingFile(final FileUploadOperation operation) {
|
||||
fileLoaderQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (encrypted) {
|
||||
uploadOperationPathsEnc.remove(location);
|
||||
} else {
|
||||
uploadOperationPaths.remove(location);
|
||||
}
|
||||
if (delegate != null) {
|
||||
delegate.fileDidFailedUpload(location, encrypted);
|
||||
}
|
||||
if (small) {
|
||||
currentUploadSmallOperationsCount--;
|
||||
if (currentUploadSmallOperationsCount < 1) {
|
||||
FileUploadOperation operation = uploadSmallOperationQueue.poll();
|
||||
if (operation != null) {
|
||||
currentUploadSmallOperationsCount++;
|
||||
operation.start();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
currentUploadOperationsCount--;
|
||||
if (currentUploadOperationsCount < 1) {
|
||||
FileUploadOperation operation = uploadOperationQueue.poll();
|
||||
if (operation != null) {
|
||||
currentUploadOperationsCount++;
|
||||
operation.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void didChangedUploadProgress(FileUploadOperation operation, final float progress) {
|
||||
if (delegate != null) {
|
||||
delegate.fileUploadProgressChanged(location, progress, encrypted);
|
||||
}
|
||||
}
|
||||
};
|
||||
if (small) {
|
||||
if (currentUploadSmallOperationsCount < 1) {
|
||||
currentUploadSmallOperationsCount++;
|
||||
operation.start();
|
||||
} else {
|
||||
uploadSmallOperationQueue.add(operation);
|
||||
}
|
||||
} else {
|
||||
if (currentUploadOperationsCount < 1) {
|
||||
currentUploadOperationsCount++;
|
||||
operation.start();
|
||||
} else {
|
||||
uploadOperationQueue.add(operation);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void cancelLoadFile(TLRPC.Document document) {
|
||||
cancelLoadFile(document, null, null);
|
||||
}
|
||||
@@ -507,7 +352,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 +362,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 +373,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 +385,7 @@ public class FileLoader {
|
||||
} else if (message.media.webpage.document != null) {
|
||||
return getAttachFileName(message.media.webpage.document);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
return "";
|
||||
}
|
||||
@@ -549,7 +394,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 +404,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 +415,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 +427,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,79 +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;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
|
||||
public class FileUploadOperation {
|
||||
|
||||
public int state = 0;
|
||||
public FileUploadOperationDelegate delegate;
|
||||
private int requestToken = 0;
|
||||
private long totalFileSize = 0;
|
||||
private boolean isEncrypted = false;
|
||||
private int estimatedSize = 0;
|
||||
private FileInputStream stream;
|
||||
|
||||
public interface FileUploadOperationDelegate {
|
||||
void didFinishUploadingFile(FileUploadOperation operation, TLRPC.InputFile inputFile, TLRPC.InputEncryptedFile inputEncryptedFile, byte[] key, byte[] iv);
|
||||
void didFailedUploadingFile(FileUploadOperation operation);
|
||||
void didChangedUploadProgress(FileUploadOperation operation, float progress);
|
||||
}
|
||||
|
||||
public FileUploadOperation(String location, boolean encrypted, int estimated) {
|
||||
isEncrypted = encrypted;
|
||||
estimatedSize = estimated;
|
||||
}
|
||||
|
||||
public long getTotalFileSize() {
|
||||
return totalFileSize;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
if (state == 3) {
|
||||
return;
|
||||
}
|
||||
state = 2;
|
||||
if (requestToken != 0) {
|
||||
ConnectionsManager.getInstance().cancelRequest(requestToken, true);
|
||||
}
|
||||
delegate.didFailedUploadingFile(this);
|
||||
cleanup();
|
||||
}
|
||||
|
||||
private void cleanup() {
|
||||
}
|
||||
|
||||
/*
|
||||
protected void checkNewDataAvailable(final long finalSize) {
|
||||
Utilities.stageQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (estimatedSize != 0 && finalSize != 0) {
|
||||
estimatedSize = 0;
|
||||
totalFileSize = finalSize;
|
||||
totalPartsCount = (int) (totalFileSize + uploadChunkSize - 1) / uploadChunkSize;
|
||||
if (started) {
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("uploadinfo", Activity.MODE_PRIVATE);
|
||||
storeFileUploadInfo(preferences);
|
||||
}
|
||||
}
|
||||
if (requestToken == 0) {
|
||||
startUploadRequest();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
@@ -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,7 +37,6 @@ import android.media.ThumbnailUtils;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.provider.MediaStore;
|
||||
|
||||
import com.b44t.ui.Components.AnimatedFileDrawable;
|
||||
@@ -70,147 +84,18 @@ public class ImageLoader {
|
||||
private static byte[] headerThumb = new byte[12];
|
||||
private int currentHttpTasksCount = 0;
|
||||
|
||||
private LinkedList<HttpFileTask> httpFileLoadTasks = new LinkedList<>();
|
||||
private HashMap<String, HttpFileTask> httpFileLoadTasksByKeys = new HashMap<>();
|
||||
private HashMap<String, Runnable> retryHttpsTasks = new HashMap<>();
|
||||
private int currentHttpFileLoadTasksCount = 0;
|
||||
|
||||
private String ignoreRemoval = null;
|
||||
|
||||
private volatile long lastCacheOutTime = 0;
|
||||
private int lastImageNum = 0;
|
||||
private long lastProgressUpdateTime = 0;
|
||||
|
||||
private File messengerPath = null;
|
||||
|
||||
private class ThumbGenerateInfo {
|
||||
private int count;
|
||||
private TLRPC.FileLocation fileLocation;
|
||||
private String filter;
|
||||
}
|
||||
|
||||
private class HttpFileTask extends AsyncTask<Void, Void, Boolean> {
|
||||
|
||||
private String url;
|
||||
private File tempFile;
|
||||
private String ext;
|
||||
private RandomAccessFile fileOutputStream = null;
|
||||
private boolean canRetry = true;
|
||||
|
||||
public HttpFileTask(String url, File tempFile, String ext) {
|
||||
this.url = url;
|
||||
this.tempFile = tempFile;
|
||||
this.ext = ext;
|
||||
}
|
||||
|
||||
protected Boolean doInBackground(Void... voids) {
|
||||
InputStream httpConnectionStream = null;
|
||||
boolean done = false;
|
||||
|
||||
URLConnection httpConnection = null;
|
||||
try {
|
||||
URL downloadUrl = new URL(url);
|
||||
httpConnection = downloadUrl.openConnection();
|
||||
httpConnection.addRequestProperty("User-Agent", "Mozilla/5.0 (Linux; Android 4.4; Nexus 5 Build/_BuildID_) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36");
|
||||
httpConnection.addRequestProperty("Referer", "google.com");
|
||||
httpConnection.setConnectTimeout(5000);
|
||||
httpConnection.setReadTimeout(5000);
|
||||
if (httpConnection instanceof HttpURLConnection) {
|
||||
HttpURLConnection httpURLConnection = (HttpURLConnection) httpConnection;
|
||||
httpURLConnection.setInstanceFollowRedirects(true);
|
||||
int status = httpURLConnection.getResponseCode();
|
||||
if (status == HttpURLConnection.HTTP_MOVED_TEMP || status == HttpURLConnection.HTTP_MOVED_PERM || status == HttpURLConnection.HTTP_SEE_OTHER) {
|
||||
String newUrl = httpURLConnection.getHeaderField("Location");
|
||||
String cookies = httpURLConnection.getHeaderField("Set-Cookie");
|
||||
downloadUrl = new URL(newUrl);
|
||||
httpConnection = downloadUrl.openConnection();
|
||||
httpConnection.setRequestProperty("Cookie", cookies);
|
||||
httpConnection.addRequestProperty("User-Agent", "Mozilla/5.0 (Linux; Android 4.4; Nexus 5 Build/_BuildID_) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36");
|
||||
httpConnection.addRequestProperty("Referer", "google.com");
|
||||
}
|
||||
}
|
||||
httpConnection.connect();
|
||||
httpConnectionStream = httpConnection.getInputStream();
|
||||
|
||||
fileOutputStream = new RandomAccessFile(tempFile, "rws");
|
||||
} catch (Throwable e) {
|
||||
if (e instanceof UnknownHostException) {
|
||||
canRetry = false;
|
||||
}
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
|
||||
if (canRetry) {
|
||||
try {
|
||||
if (httpConnection != null && httpConnection instanceof HttpURLConnection) {
|
||||
int code = ((HttpURLConnection) httpConnection).getResponseCode();
|
||||
if (code != HttpURLConnection.HTTP_OK && code != HttpURLConnection.HTTP_ACCEPTED && code != HttpURLConnection.HTTP_NOT_MODIFIED) {
|
||||
canRetry = false;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
|
||||
if (httpConnectionStream != null) {
|
||||
try {
|
||||
byte[] data = new byte[1024 * 4];
|
||||
while (true) {
|
||||
if (isCancelled()) {
|
||||
break;
|
||||
}
|
||||
try {
|
||||
int read = httpConnectionStream.read(data);
|
||||
if (read > 0) {
|
||||
fileOutputStream.write(data, 0, read);
|
||||
} else if (read == -1) {
|
||||
done = true;
|
||||
break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (fileOutputStream != null) {
|
||||
fileOutputStream.close();
|
||||
fileOutputStream = null;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
|
||||
try {
|
||||
if (httpConnectionStream != null) {
|
||||
httpConnectionStream.close();
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
}
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result) {
|
||||
runHttpFileLoadTasks(this, result ? 2 : 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCancelled() {
|
||||
runHttpFileLoadTasks(this, 2);
|
||||
}
|
||||
}
|
||||
|
||||
private class HttpImageTask extends AsyncTask<Void, Void, Boolean> {
|
||||
|
||||
private CacheImage cacheImage = null;
|
||||
@@ -515,16 +400,6 @@ public class ImageLoader {
|
||||
kf += "@" + filter;
|
||||
}
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageThumbGenerated, bitmapDrawable, kf);
|
||||
/*BitmapDrawable old = memCache.get(kf);
|
||||
if (old != null) {
|
||||
Bitmap image = old.getBitmap();
|
||||
if (runtimeHack != null) {
|
||||
runtimeHack.trackAlloc(image.getRowBytes() * image.getHeight());
|
||||
}
|
||||
if (!image.isRecycled()) {
|
||||
image.recycle();
|
||||
}
|
||||
}*/
|
||||
memCache.put(kf, bitmapDrawable);
|
||||
}
|
||||
});
|
||||
@@ -1105,6 +980,7 @@ public class ImageLoader {
|
||||
};
|
||||
|
||||
FileLoader.getInstance().setDelegate(new FileLoader.FileLoaderDelegate() {
|
||||
/*
|
||||
@Override
|
||||
public void fileUploadProgressChanged(final String location, final float progress, final boolean isEncrypted) {
|
||||
fileProgresses.put(location, progress);
|
||||
@@ -1152,6 +1028,7 @@ public class ImageLoader {
|
||||
}
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void fileDidLoaded(final String location, final File finalFile, final int type) {
|
||||
@@ -1159,11 +1036,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,165 +1105,19 @@ 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() {
|
||||
cacheOutQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final HashMap<Integer, File> paths = createMediaPaths();
|
||||
AndroidUtilities.runOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
FileLoader.getInstance().setMediaDirs(paths);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public HashMap<Integer, File> createMediaPaths() {
|
||||
HashMap<Integer, File> mediaDirs = new HashMap<>();
|
||||
File cachePath = AndroidUtilities.getCacheDir();
|
||||
if (!cachePath.isDirectory()) {
|
||||
try {
|
||||
cachePath.mkdirs();
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
}
|
||||
File cachePath = new File(MrMailbox.getBlobdir());
|
||||
try {
|
||||
new File(cachePath, ".nomedia").createNewFile();
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
|
||||
mediaDirs.put(FileLoader.MEDIA_DIR_CACHE, cachePath);
|
||||
FileLog.e("messenger", "cache path = " + cachePath);
|
||||
|
||||
try {
|
||||
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
|
||||
messengerPath = new File(Environment.getExternalStorageDirectory(), "Delta Chat");
|
||||
messengerPath.mkdirs();
|
||||
|
||||
if (messengerPath.isDirectory()) {
|
||||
try {
|
||||
File imagePath = new File(messengerPath, "Delta Chat Images");
|
||||
imagePath.mkdir();
|
||||
if (imagePath.isDirectory() && canMoveFiles(cachePath, imagePath, FileLoader.MEDIA_DIR_IMAGE)) {
|
||||
mediaDirs.put(FileLoader.MEDIA_DIR_IMAGE, imagePath);
|
||||
FileLog.e("messenger", "image path = " + imagePath);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
|
||||
try {
|
||||
File videoPath = new File(messengerPath, "Delta Chat Video");
|
||||
videoPath.mkdir();
|
||||
if (videoPath.isDirectory() && canMoveFiles(cachePath, videoPath, FileLoader.MEDIA_DIR_VIDEO)) {
|
||||
mediaDirs.put(FileLoader.MEDIA_DIR_VIDEO, videoPath);
|
||||
FileLog.e("messenger", "video path = " + videoPath);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
|
||||
try {
|
||||
File audioPath = new File(messengerPath, "Delta Chat Audio");
|
||||
audioPath.mkdir();
|
||||
if (audioPath.isDirectory() && canMoveFiles(cachePath, audioPath, FileLoader.MEDIA_DIR_AUDIO)) {
|
||||
new File(audioPath, ".nomedia").createNewFile();
|
||||
mediaDirs.put(FileLoader.MEDIA_DIR_AUDIO, audioPath);
|
||||
FileLog.e("messenger", "audio path = " + audioPath);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
|
||||
try {
|
||||
File documentPath = new File(messengerPath, "Delta Chat Documents");
|
||||
documentPath.mkdir();
|
||||
if (documentPath.isDirectory() && canMoveFiles(cachePath, documentPath, FileLoader.MEDIA_DIR_DOCUMENT)) {
|
||||
new File(documentPath, ".nomedia").createNewFile();
|
||||
mediaDirs.put(FileLoader.MEDIA_DIR_DOCUMENT, documentPath);
|
||||
FileLog.e("messenger", "documents path = " + documentPath);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
FileLog.e("messenger", "this Android can't rename files");
|
||||
}
|
||||
MediaController.getInstance().checkSaveToGalleryFiles();
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
|
||||
return mediaDirs;
|
||||
}
|
||||
|
||||
private boolean canMoveFiles(File from, File to, int type) {
|
||||
RandomAccessFile file = null;
|
||||
try {
|
||||
File srcFile = null;
|
||||
File dstFile = null;
|
||||
if (type == FileLoader.MEDIA_DIR_IMAGE) {
|
||||
srcFile = new File(from, "000000000_999999_temp.jpg");
|
||||
dstFile = new File(to, "000000000_999999.jpg");
|
||||
} else if (type == FileLoader.MEDIA_DIR_DOCUMENT) {
|
||||
srcFile = new File(from, "000000000_999999_temp.doc");
|
||||
dstFile = new File(to, "000000000_999999.doc");
|
||||
} else if (type == FileLoader.MEDIA_DIR_AUDIO) {
|
||||
srcFile = new File(from, "000000000_999999_temp.ogg");
|
||||
dstFile = new File(to, "000000000_999999.ogg");
|
||||
} else if (type == FileLoader.MEDIA_DIR_VIDEO) {
|
||||
srcFile = new File(from, "000000000_999999_temp.mp4");
|
||||
dstFile = new File(to, "000000000_999999.mp4");
|
||||
}
|
||||
byte[] buffer = new byte[1024];
|
||||
srcFile.createNewFile();
|
||||
file = new RandomAccessFile(srcFile, "rws");
|
||||
file.write(buffer);
|
||||
file.close();
|
||||
file = null;
|
||||
boolean canRename = srcFile.renameTo(dstFile);
|
||||
srcFile.delete();
|
||||
dstFile.delete();
|
||||
if (canRename) {
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
} finally {
|
||||
try {
|
||||
if (file != null) {
|
||||
file.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
FileLoader.getInstance().setMediaDirs(mediaDirs);
|
||||
}
|
||||
|
||||
public Float getFileProgress(String location) {
|
||||
@@ -1396,21 +1127,6 @@ public class ImageLoader {
|
||||
return fileProgresses.get(location);
|
||||
}
|
||||
|
||||
private void performReplace(String oldKey, String newKey) {
|
||||
BitmapDrawable b = memCache.get(oldKey);
|
||||
if (b != null) {
|
||||
ignoreRemoval = oldKey;
|
||||
memCache.remove(oldKey);
|
||||
memCache.put(newKey, b);
|
||||
ignoreRemoval = null;
|
||||
}
|
||||
Integer val = bitmapUseCounts.get(oldKey);
|
||||
if (val != null) {
|
||||
bitmapUseCounts.put(newKey, val);
|
||||
bitmapUseCounts.remove(oldKey);
|
||||
}
|
||||
}
|
||||
|
||||
public void incrementUseCount(String key) {
|
||||
Integer count = bitmapUseCounts.get(key);
|
||||
if (count == null) {
|
||||
@@ -1491,65 +1207,6 @@ public class ImageLoader {
|
||||
});
|
||||
}
|
||||
|
||||
public BitmapDrawable getImageFromMemory(String key) {
|
||||
return memCache.get(key);
|
||||
}
|
||||
|
||||
public BitmapDrawable getImageFromMemory(TLObject fileLocation, String httpUrl, String filter) {
|
||||
if (fileLocation == null && httpUrl == null) {
|
||||
return null;
|
||||
}
|
||||
String key = null;
|
||||
if (httpUrl != null) {
|
||||
key = Utilities.MD5(httpUrl);
|
||||
} else {
|
||||
if (fileLocation instanceof TLRPC.FileLocation) {
|
||||
TLRPC.FileLocation location = (TLRPC.FileLocation) fileLocation;
|
||||
key = location.volume_id + "_" + location.local_id;
|
||||
} else if (fileLocation instanceof TLRPC.Document) {
|
||||
TLRPC.Document location = (TLRPC.Document) fileLocation;
|
||||
key = location.dc_id + "_" + location.id;
|
||||
}
|
||||
}
|
||||
if (filter != null) {
|
||||
key += "@" + filter;
|
||||
}
|
||||
return memCache.get(key);
|
||||
}
|
||||
|
||||
private void replaceImageInCacheInternal(final String oldKey, final String newKey, final TLRPC.FileLocation newLocation) {
|
||||
ArrayList<String> arr = memCache.getFilterKeys(oldKey);
|
||||
if (arr != null) {
|
||||
for (int a = 0; a < arr.size(); a++) {
|
||||
String filter = arr.get(a);
|
||||
String oldK = oldKey + "@" + filter;
|
||||
String newK = newKey + "@" + filter;
|
||||
performReplace(oldK, newK);
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.didReplacedPhotoInMemCache, oldK, newK, newLocation);
|
||||
}
|
||||
} else {
|
||||
performReplace(oldKey, newKey);
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.didReplacedPhotoInMemCache, oldKey, newKey, newLocation);
|
||||
}
|
||||
}
|
||||
|
||||
public void replaceImageInCache(final String oldKey, final String newKey, final TLRPC.FileLocation newLocation, boolean post) {
|
||||
if (post) {
|
||||
AndroidUtilities.runOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
replaceImageInCacheInternal(oldKey, newKey, newLocation);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
replaceImageInCacheInternal(oldKey, newKey, newLocation);
|
||||
}
|
||||
}
|
||||
|
||||
public void putImageToCache(BitmapDrawable bitmap, String key) {
|
||||
memCache.put(key, bitmap);
|
||||
}
|
||||
|
||||
private void generateThumb(int mediaType, File originalPath, TLRPC.FileLocation thumbLocation, String filter) {
|
||||
if (mediaType != FileLoader.MEDIA_DIR_IMAGE && mediaType != FileLoader.MEDIA_DIR_VIDEO && mediaType != FileLoader.MEDIA_DIR_DOCUMENT || originalPath == null || thumbLocation == null) {
|
||||
return;
|
||||
@@ -1607,7 +1264,6 @@ public class ImageLoader {
|
||||
|
||||
if (!added) {
|
||||
boolean onlyCache = false;
|
||||
boolean isQuality = false;
|
||||
File cacheFile = null;
|
||||
|
||||
if (httpLocation != null) {
|
||||
@@ -1920,80 +1576,12 @@ public class ImageLoader {
|
||||
}
|
||||
}
|
||||
|
||||
public void loadHttpFile(String url, String defaultExt) {
|
||||
if (url == null || url.length() == 0 || httpFileLoadTasksByKeys.containsKey(url)) {
|
||||
return;
|
||||
}
|
||||
String ext = getHttpUrlExtension(url, defaultExt);
|
||||
File file = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), Utilities.MD5(url) + "_temp." + ext);
|
||||
file.delete();
|
||||
|
||||
HttpFileTask task = new HttpFileTask(url, file, ext);
|
||||
httpFileLoadTasks.add(task);
|
||||
httpFileLoadTasksByKeys.put(url, task);
|
||||
runHttpFileLoadTasks(null, 0);
|
||||
}
|
||||
|
||||
public void cancelLoadHttpFile(String url) {
|
||||
HttpFileTask task = httpFileLoadTasksByKeys.get(url);
|
||||
if (task != null) {
|
||||
task.cancel(true);
|
||||
httpFileLoadTasksByKeys.remove(url);
|
||||
httpFileLoadTasks.remove(task);
|
||||
}
|
||||
Runnable runnable = retryHttpsTasks.get(url);
|
||||
if (runnable != null) {
|
||||
AndroidUtilities.cancelRunOnUIThread(runnable);
|
||||
}
|
||||
runHttpFileLoadTasks(null, 0);
|
||||
}
|
||||
|
||||
private void runHttpFileLoadTasks(final HttpFileTask oldTask, final int reason) {
|
||||
AndroidUtilities.runOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (oldTask != null) {
|
||||
currentHttpFileLoadTasksCount--;
|
||||
}
|
||||
if (oldTask != null) {
|
||||
if (reason == 1) {
|
||||
if (oldTask.canRetry) {
|
||||
final HttpFileTask newTask = new HttpFileTask(oldTask.url, oldTask.tempFile, oldTask.ext);
|
||||
Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
httpFileLoadTasks.add(newTask);
|
||||
runHttpFileLoadTasks(null, 0);
|
||||
}
|
||||
};
|
||||
retryHttpsTasks.put(oldTask.url, runnable);
|
||||
AndroidUtilities.runOnUIThread(runnable, 1000);
|
||||
} else {
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.httpFileDidFailedLoad, oldTask.url);
|
||||
}
|
||||
} else if (reason == 2) {
|
||||
httpFileLoadTasksByKeys.remove(oldTask.url);
|
||||
File file = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), Utilities.MD5(oldTask.url) + "." + oldTask.ext);
|
||||
String result = oldTask.tempFile.renameTo(file) ? file.toString() : oldTask.tempFile.toString();
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.httpFileDidLoaded, oldTask.url, result);
|
||||
}
|
||||
}
|
||||
while (currentHttpFileLoadTasksCount < 2 && !httpFileLoadTasks.isEmpty()) {
|
||||
HttpFileTask task = httpFileLoadTasks.poll();
|
||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null, null, null);
|
||||
currentHttpFileLoadTasksCount++;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static Bitmap loadBitmap(String path, Uri uri, float maxWidth, float maxHeight, boolean useMaxScale) {
|
||||
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
|
||||
bmOptions.inJustDecodeBounds = true;
|
||||
InputStream inputStream = null;
|
||||
|
||||
if (path == null && uri != null && uri.getScheme() != null) {
|
||||
String imageFilePath = null;
|
||||
if (uri.getScheme().contains("file")) {
|
||||
path = uri.getPath();
|
||||
} else {
|
||||
@@ -2008,7 +1596,6 @@ public class ImageLoader {
|
||||
if (path != null) {
|
||||
BitmapFactory.decodeFile(path, bmOptions);
|
||||
} else if (uri != null) {
|
||||
boolean error = false;
|
||||
try {
|
||||
inputStream = ApplicationLoader.applicationContext.getContentResolver().openInputStream(uri);
|
||||
BitmapFactory.decodeStream(inputStream, null, bmOptions);
|
||||
@@ -2122,7 +1709,7 @@ public class ImageLoader {
|
||||
return b;
|
||||
}
|
||||
|
||||
private static TLRPC.PhotoSize scaleAndSaveImageInternal(Bitmap bitmap, int w, int h, float photoW, float photoH, float scaleFactor, int quality, boolean cache, boolean scaleAnyway) throws Exception {
|
||||
private static TLRPC.PhotoSize scaleAndSaveImageInternal(File cacheFile, Bitmap bitmap, int w, int h, float photoW, float photoH, float scaleFactor, int quality, boolean cache, boolean scaleAnyway) throws Exception {
|
||||
Bitmap scaledBitmap;
|
||||
if (scaleFactor > 1 || scaleAnyway) {
|
||||
scaledBitmap = Bitmaps.createScaledBitmap(bitmap, w, h, true);
|
||||
@@ -2151,8 +1738,11 @@ public class ImageLoader {
|
||||
size.type = "w";
|
||||
}
|
||||
|
||||
String fileName = location.volume_id + "_" + location.local_id + ".jpg";
|
||||
final File cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName);
|
||||
if( cacheFile == null ) {
|
||||
String fileName = location.volume_id + "_" + location.local_id + ".jpg";
|
||||
cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName);
|
||||
}
|
||||
|
||||
FileOutputStream stream = new FileOutputStream(cacheFile);
|
||||
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, quality, stream);
|
||||
if (cache) {
|
||||
@@ -2173,10 +1763,18 @@ public class ImageLoader {
|
||||
}
|
||||
|
||||
public static TLRPC.PhotoSize scaleAndSaveImage(Bitmap bitmap, float maxWidth, float maxHeight, int quality, boolean cache) {
|
||||
return scaleAndSaveImage(bitmap, maxWidth, maxHeight, quality, cache, 0, 0);
|
||||
return scaleAndSaveImage(null, bitmap, maxWidth, maxHeight, quality, cache, 0, 0);
|
||||
}
|
||||
|
||||
public static TLRPC.PhotoSize scaleAndSaveImage(Bitmap bitmap, float maxWidth, float maxHeight, int quality, boolean cache, int minWidth, int minHeight) {
|
||||
return scaleAndSaveImage(null, bitmap, maxWidth, maxHeight, quality, cache, minWidth, minHeight);
|
||||
}
|
||||
|
||||
public static TLRPC.PhotoSize scaleAndSaveImage(File cacheFile, Bitmap bitmap, float maxWidth, float maxHeight, int quality, boolean cache) {
|
||||
return scaleAndSaveImage(cacheFile, bitmap, maxWidth, maxHeight, quality, cache, 0, 0);
|
||||
}
|
||||
|
||||
private static TLRPC.PhotoSize scaleAndSaveImage(File cacheFile, Bitmap bitmap, float maxWidth, float maxHeight, int quality, boolean cache, int minWidth, int minHeight) {
|
||||
if (bitmap == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -2204,13 +1802,13 @@ public class ImageLoader {
|
||||
}
|
||||
|
||||
try {
|
||||
return scaleAndSaveImageInternal(bitmap, w, h, photoW, photoH, scaleFactor, quality, cache, scaleAnyway);
|
||||
return scaleAndSaveImageInternal(cacheFile, bitmap, w, h, photoW, photoH, scaleFactor, quality, cache, scaleAnyway);
|
||||
} catch (Throwable e) {
|
||||
FileLog.e("messenger", e);
|
||||
ImageLoader.getInstance().clearMemory();
|
||||
System.gc();
|
||||
try {
|
||||
return scaleAndSaveImageInternal(bitmap, w, h, photoW, photoH, scaleFactor, quality, cache, scaleAnyway);
|
||||
return scaleAndSaveImageInternal(cacheFile, bitmap, w, h, photoW, photoH, scaleFactor, quality, cache, scaleAnyway);
|
||||
} catch (Throwable e2) {
|
||||
FileLog.e("messenger", e2);
|
||||
return null;
|
||||
@@ -2230,6 +1828,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 +1842,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 +1887,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 +1910,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;
|
||||
@@ -349,12 +371,10 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
||||
setImageBackup.ext = currentExt;
|
||||
setImageBackup.cacheOnly = currentCacheOnly;
|
||||
}
|
||||
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.didReplacedPhotoInMemCache);
|
||||
clearImage();
|
||||
}
|
||||
|
||||
public boolean onAttachedToWindow() {
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.didReplacedPhotoInMemCache);
|
||||
if (setImageBackup != null && (setImageBackup.fileLocation != null || setImageBackup.httpUrl != null || setImageBackup.thumbLocation != null || setImageBackup.thumb != null)) {
|
||||
setImage(setImageBackup.fileLocation, setImageBackup.httpUrl, setImageBackup.filter, setImageBackup.thumb, setImageBackup.thumbLocation, setImageBackup.thumbFilter, setImageBackup.size, setImageBackup.ext, setImageBackup.cacheOnly);
|
||||
return true;
|
||||
@@ -1036,26 +1056,6 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (id == NotificationCenter.didReplacedPhotoInMemCache) {
|
||||
String oldKey = (String) args[0];
|
||||
if (currentKey != null && currentKey.equals(oldKey)) {
|
||||
currentKey = (String) args[1];
|
||||
currentImageLocation = (TLRPC.FileLocation) args[2];
|
||||
}
|
||||
if (currentThumbKey != null && currentThumbKey.equals(oldKey)) {
|
||||
currentThumbKey = (String) args[1];
|
||||
currentThumbLocation = (TLRPC.FileLocation) args[2];
|
||||
}
|
||||
if (setImageBackup != null) {
|
||||
if (currentKey != null && currentKey.equals(oldKey)) {
|
||||
currentKey = (String) args[1];
|
||||
currentImageLocation = (TLRPC.FileLocation) args[2];
|
||||
}
|
||||
if (currentThumbKey != null && currentThumbKey.equals(oldKey)) {
|
||||
currentThumbKey = (String) args[1];
|
||||
currentThumbLocation = (TLRPC.FileLocation) args[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
@@ -82,29 +76,18 @@ public class MrChat {
|
||||
return MrChatGetTotalMsgCount(m_hChat);
|
||||
}
|
||||
|
||||
public int sendText(String text) {
|
||||
return MrChatSendText(m_hChat, text);
|
||||
}
|
||||
public native int sendText(String text);
|
||||
|
||||
public int sendMedia(int type, String file, String mime, int w, int h, int time_ms) {
|
||||
return MrChatSendMedia(m_hChat, type, file, mime, w, h, time_ms);
|
||||
}
|
||||
public native int sendMedia(int type, String file, String mime, int w, int h, int time_ms, String author, String trackname);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
/* additional functions that are not 1:1 available in the backend
|
||||
@@ -128,7 +111,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
|
||||
*
|
||||
******************************************************************************/
|
||||
@@ -29,84 +28,46 @@
|
||||
package com.b44t.messenger;
|
||||
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
public class MrMailbox {
|
||||
|
||||
public static void init () {
|
||||
m_hMailbox = MrMailboxNew();
|
||||
}
|
||||
|
||||
public static int open(String dbfile, String blobdir) {
|
||||
return MrMailboxOpen(m_hMailbox, dbfile, blobdir);
|
||||
}
|
||||
public native static int open(String dbfile);
|
||||
public native static void close();
|
||||
public native static String getBlobdir();
|
||||
|
||||
public static void close() {
|
||||
MrMailboxClose(m_hMailbox);
|
||||
}
|
||||
public native static void configureAndConnect();
|
||||
public native static void configureCancel();
|
||||
|
||||
public static int configure() {
|
||||
return MrMailboxConfigure(m_hMailbox);
|
||||
}
|
||||
public native static int isConfigured();
|
||||
|
||||
public static int isConfigured() {
|
||||
return MrMailboxIsConfigured(m_hMailbox);
|
||||
}
|
||||
public native static void connect();
|
||||
public native static void disconnect();
|
||||
|
||||
public static int connect() {
|
||||
return MrMailboxConnect(m_hMailbox);
|
||||
}
|
||||
public native static void setConfig(String key, String value);
|
||||
public native static void setConfigInt(String key, int value);
|
||||
public native static String getConfig(String key, String def);
|
||||
public native static int getConfigInt(String key, int def);
|
||||
|
||||
public static void disconnect() {
|
||||
MrMailboxDisconnect(m_hMailbox);
|
||||
}
|
||||
|
||||
public static int fetch() {
|
||||
return MrMailboxFetch(m_hMailbox);
|
||||
}
|
||||
|
||||
public static int setConfig(String key, String value) {
|
||||
return MrMailboxSetConfig(m_hMailbox, key, value);
|
||||
}
|
||||
|
||||
public static String getConfig(String key, String def) {
|
||||
return MrMailboxGetConfig(m_hMailbox, key, def);
|
||||
}
|
||||
|
||||
public static int getConfigInt(String key, int def) {
|
||||
return MrMailboxGetConfigInt(m_hMailbox, key, def);
|
||||
}
|
||||
|
||||
public static String getInfo() {
|
||||
return MrMailboxGetInfo(m_hMailbox);
|
||||
}
|
||||
|
||||
public static String execute(String cmd) {
|
||||
return MrMailboxExecute(m_hMailbox, cmd);
|
||||
}
|
||||
|
||||
private static long m_hMailbox = 0;
|
||||
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);
|
||||
private native static void MrMailboxDisconnect (long hMailbox);
|
||||
private native static int MrMailboxFetch (long hMailbox);
|
||||
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);
|
||||
public native static String getInfo();
|
||||
public native static String cmdline(String cmd);
|
||||
|
||||
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)
|
||||
|
||||
// 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 +89,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 +97,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 +116,28 @@ 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 isContactInChat (int chat_id, int contact_id);
|
||||
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 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 final static int MR_GCM_ADDDAYMARKER = 0x01;
|
||||
public native static int[] getChatMsgs(int chat_id, int flags, int marker1before);
|
||||
|
||||
public static int[] getChatContacts(int chat_id) {
|
||||
return MrMailboxGetChatContacts(m_hMailbox, chat_id);
|
||||
}
|
||||
public native static int[] searchMsgs(int chat_id, String query);
|
||||
|
||||
public static int deleteChat(int chat_id) {
|
||||
return MrMailboxDeleteChat(m_hMailbox, chat_id);
|
||||
}
|
||||
public native static int[] getUnseenMsgs();
|
||||
|
||||
private native static long MrMailboxGetChatlist (long hMailbox); // returns hChatlist which must be unref'd after usage
|
||||
public native static int[] getChatMedia(int chat_id, int msg_type, int or_msg_type);
|
||||
public native static int getNextMedia(int msg_id, int dir);
|
||||
public native static int[] getChatContacts(int chat_id);
|
||||
public native static int deleteChat(int chat_id);
|
||||
|
||||
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,46 +149,76 @@ 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);
|
||||
public native static String MrGetVersionStr ();
|
||||
public native static String CPtr2String (long hString); // get strings eg. from data1 from the callback
|
||||
|
||||
public native static long String2CPtr (String str);
|
||||
|
||||
/* receive events
|
||||
**********************************************************************************************/
|
||||
|
||||
public final static int MR_EVENT_MSGS_UPDATED = 2000;
|
||||
public final static int MR_EVENT_ERROR = 400; // INFO and WARNING are blocked in the mrwrapper.c
|
||||
|
||||
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_CONFIGURE_ENDED = 2040;
|
||||
public final static int MR_EVENT_CONFIGURE_PROGRESS = 2041;
|
||||
|
||||
public final static int MR_EVENT_IS_ONLINE = 2080;
|
||||
public final static int MR_EVENT_GET_STRING = 2091;
|
||||
public final static int MR_EVENT_GET_QUANTITIY_STRING = 2092;
|
||||
public final static int MR_EVENT_HTTP_GET = 2100;
|
||||
|
||||
|
||||
public static final Object m_lastErrorLock = new Object();
|
||||
public static int m_lastErrorCode = 0;
|
||||
public static String m_lastErrorString = "";
|
||||
public static boolean m_showNextErrorAsToast = true;
|
||||
|
||||
public static long MrCallback(final int event, final long data1, final long data2) // this function is called from within the C-wrapper
|
||||
{
|
||||
switch(event) {
|
||||
case MR_EVENT_CONNECTION_STATE_CHANGED:
|
||||
case MR_EVENT_CONFIGURE_ENDED:
|
||||
AndroidUtilities.runOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.connectionStateChanged, (int)data1);
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.configureEnded, (int)data1);
|
||||
}
|
||||
});
|
||||
return 0;
|
||||
|
||||
case MR_EVENT_MSGS_UPDATED:
|
||||
case MR_EVENT_CONFIGURE_PROGRESS:
|
||||
AndroidUtilities.runOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.configureProgress, (int)data1);
|
||||
}
|
||||
});
|
||||
return 0;
|
||||
|
||||
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 +246,96 @@ 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_ERROR:
|
||||
synchronized (m_lastErrorLock) {
|
||||
m_lastErrorCode = (int)data1;
|
||||
m_lastErrorString = CPtr2String(data2);
|
||||
}
|
||||
AndroidUtilities.runOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (m_lastErrorLock) {
|
||||
if( m_showNextErrorAsToast ) {
|
||||
AndroidUtilities.showHint(ApplicationLoader.applicationContext, m_lastErrorString);
|
||||
}
|
||||
m_showNextErrorAsToast = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
return 0;
|
||||
|
||||
case MR_EVENT_GET_STRING:
|
||||
String s = "ErrStrBadId";
|
||||
switch( (int)data1 ) {
|
||||
// the string-IDs are defined in the backend; as this is the only place where they're used, there is no benefit in creating an enum or sth. like that.
|
||||
case 1: s = ApplicationLoader.applicationContext.getString(R.string.NoMessages); break;
|
||||
case 2: s = ApplicationLoader.applicationContext.getString(R.string.FromSelf); break;
|
||||
case 3: s = ApplicationLoader.applicationContext.getString(R.string.Draft); break;
|
||||
case 7: s = ApplicationLoader.applicationContext.getString(R.string.AttachVoiceMessage); break;
|
||||
case 8: s = ApplicationLoader.applicationContext.getString(R.string.Deaddrop); break;
|
||||
case 9: s = ApplicationLoader.applicationContext.getString(R.string.AttachPhoto); break;
|
||||
case 10: s = ApplicationLoader.applicationContext.getString(R.string.AttachVideo); break;
|
||||
case 11: s = ApplicationLoader.applicationContext.getString(R.string.AttachMusic); break;
|
||||
case 12: s = ApplicationLoader.applicationContext.getString(R.string.AttachDocument); break;
|
||||
case 13: s = ApplicationLoader.applicationContext.getString(R.string.DefaultStatusText); break;
|
||||
case 14: s = ApplicationLoader.applicationContext.getString(R.string.MsgNewGroupDraft); break;
|
||||
case 15: s = ApplicationLoader.applicationContext.getString(R.string.MsgGroupNameChanged); break;
|
||||
case 16: s = ApplicationLoader.applicationContext.getString(R.string.MsgGroupImageChanged); break;
|
||||
case 17: s = ApplicationLoader.applicationContext.getString(R.string.MsgMemberAddedToGroup); break;
|
||||
case 18: s = ApplicationLoader.applicationContext.getString(R.string.MsgMemberRemovedFromToGroup); break;
|
||||
case 19: s = ApplicationLoader.applicationContext.getString(R.string.MsgGroupLeft); break;
|
||||
case 20: s = ApplicationLoader.applicationContext.getString(R.string.Error); break;
|
||||
case 21: s = ApplicationLoader.applicationContext.getString(R.string.ErrSelfNotInGroup); break;
|
||||
case 22: s = ApplicationLoader.applicationContext.getString(R.string.NoNetwork); break;
|
||||
}
|
||||
return String2CPtr(s);
|
||||
|
||||
case MR_EVENT_GET_QUANTITIY_STRING:
|
||||
String sp = "ErrQtyStrBadId";
|
||||
switch( (int)data1 ) {
|
||||
// the string-IDs are defined in the backend; as this is the only place where they're used, there is no benefit in creating an enum or sth. like that.
|
||||
case 4: sp = ApplicationLoader.applicationContext.getResources().getQuantityString(R.plurals.Members, (int)data2, (int)data2); break;
|
||||
case 6: sp = ApplicationLoader.applicationContext.getResources().getQuantityString(R.plurals.Contacts, (int)data2, (int)data2); break;
|
||||
}
|
||||
return String2CPtr(sp);
|
||||
|
||||
case MR_EVENT_IS_ONLINE:
|
||||
return ConnectionsManager.isNetworkOnline()? 1 : 0;
|
||||
|
||||
case MR_EVENT_HTTP_GET:
|
||||
String httpContent = null;
|
||||
try {
|
||||
URL url = new URL(CPtr2String(data1));
|
||||
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
|
||||
try {
|
||||
InputStream inputStream = new BufferedInputStream(urlConnection.getInputStream());
|
||||
|
||||
BufferedReader r = new BufferedReader(new InputStreamReader(inputStream));
|
||||
StringBuilder total = new StringBuilder();
|
||||
String line;
|
||||
while ((line = r.readLine()) != null) {
|
||||
total.append(line).append('\n');
|
||||
}
|
||||
httpContent = total.toString();
|
||||
} finally {
|
||||
urlConnection.disconnect();
|
||||
}
|
||||
}
|
||||
catch(Exception e) {}
|
||||
return String2CPtr(httpContent);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -273,6 +348,31 @@ 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 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,12 +27,22 @@
|
||||
|
||||
package com.b44t.messenger;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.media.ThumbnailUtils;
|
||||
import android.provider.MediaStore;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
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;
|
||||
public final static int MR_MSG_AUDIO = 40;
|
||||
public final static int MR_MSG_VOICE = 41;
|
||||
public final static int MR_MSG_VIDEO = 50;
|
||||
public final static int MR_MSG_FILE = 60;
|
||||
|
||||
@@ -46,6 +55,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;
|
||||
}
|
||||
@@ -84,14 +96,21 @@ public class MrMsg {
|
||||
return MrMsgGetToId(m_hMsg);
|
||||
}
|
||||
|
||||
public String getParam (int key, String def) {
|
||||
return MrMsgGetParam(m_hMsg, key, def);
|
||||
}
|
||||
public int getParamInt(int key, int def) {
|
||||
return MrMsgGetParamInt(m_hMsg, key, def);
|
||||
}
|
||||
public native String getParam(int key, String def);
|
||||
public native int getParamInt(int key, int def);
|
||||
public native void setParamInt(int key, int def);
|
||||
public native void saveParamToDisk();
|
||||
|
||||
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);
|
||||
public MrPoortext getMediainfo() { return new MrPoortext(getMediainfoCPtr()); }
|
||||
private native long getMediainfoCPtr();
|
||||
public native String getFilename();
|
||||
public native int isIncreation();
|
||||
|
||||
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);
|
||||
@@ -101,8 +120,6 @@ public class MrMsg {
|
||||
private native static int MrMsgGetChatId (long hMsg);
|
||||
private native static int MrMsgGetFromId (long hMsg);
|
||||
private native static int MrMsgGetToId (long hMsg);
|
||||
private native static String MrMsgGetParam (long hMsg, int key, String def);
|
||||
private native static int MrMsgGetParamInt (long hMsg, int key, int def);
|
||||
|
||||
|
||||
/* additional functions that are not 1:1 available in the backend
|
||||
@@ -132,7 +149,6 @@ public class MrMsg {
|
||||
ret.unread = state!=MR_OUT_READ; // the state of outgoing messages
|
||||
ret.media_unread = ret.unread;
|
||||
ret.flags = 0; // posible flags: MESSAGE_FLAG_HAS_FROM_ID, however, this seems to be read only
|
||||
ret.post = false; // ? true=avatar wird in gruppen nicht angezeigt, wird aber in isFromUser() auch überprüft...
|
||||
ret.out = ret.from_id==MrContact.MR_CONTACT_ID_SELF; // true=outgoing message, read eg. in MessageObject.isOutOwner()
|
||||
ret.created_by_mr = true;
|
||||
|
||||
@@ -147,11 +163,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) {
|
||||
@@ -169,37 +195,78 @@ public class MrMsg {
|
||||
ret.message = "<cannot load image>";
|
||||
}
|
||||
}
|
||||
else if( type == MR_MSG_AUDIO || type == MR_MSG_VIDEO ) {
|
||||
else if( type == MR_MSG_AUDIO || type == MR_MSG_VOICE || type == MR_MSG_VIDEO || type == MR_MSG_FILE ) {
|
||||
String path = getParam('f', "");
|
||||
if( !path.isEmpty()) {
|
||||
ret.message = "-1"; // may be misused for video editing information
|
||||
ret.media = new TLRPC.TL_messageMediaDocument();
|
||||
ret.media.caption = "";
|
||||
ret.media.document = new TLRPC.TL_document();
|
||||
ret.media.document.file_name = getFilename();
|
||||
ret.media.document.mr_path = path;
|
||||
if( type == MR_MSG_AUDIO ) {
|
||||
ret.media.document.size = getBytes();
|
||||
if( type == MR_MSG_AUDIO || type == MR_MSG_VOICE ) {
|
||||
TLRPC.TL_documentAttributeAudio attr = new TLRPC.TL_documentAttributeAudio();
|
||||
attr.voice = true; // !voice = music
|
||||
attr.voice = type == MR_MSG_VOICE;
|
||||
attr.duration = getParamInt('d', 0) / 1000;
|
||||
ret.media.document.attributes.add(attr);
|
||||
}
|
||||
else if( type == MR_MSG_VIDEO) {
|
||||
else if( type == MR_MSG_VIDEO ) {
|
||||
File vfile = new File(path);
|
||||
File tfile = new File(MrMailbox.getBlobdir(), vfile.getName()+"-preview.jpg");
|
||||
if( !tfile.exists() ) {
|
||||
try {
|
||||
Bitmap thumb = ThumbnailUtils.createVideoThumbnail(path, MediaStore.Video.Thumbnails.MINI_KIND);
|
||||
TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(tfile, thumb, 90, 90, 55, false);
|
||||
size.location.mr_path = tfile.getAbsolutePath();
|
||||
size.type = "s";
|
||||
ret.media.document.thumb = size;
|
||||
|
||||
setParamInt('w', size.w);
|
||||
setParamInt('h', size.h);
|
||||
saveParamToDisk();
|
||||
}
|
||||
catch (Exception e) {}
|
||||
}
|
||||
else {
|
||||
TLRPC.PhotoSize size = new TLRPC.PhotoSize();
|
||||
size.location = new TLRPC.TL_fileLocation();
|
||||
size.location.mr_path = tfile.getAbsolutePath();
|
||||
size.location.local_id = -ret.id;
|
||||
size.w = getParamInt('w', 320);
|
||||
size.h = getParamInt('h', 240);
|
||||
size.type = "s";
|
||||
ret.media.document.thumb = size;
|
||||
}
|
||||
|
||||
TLRPC.TL_documentAttributeVideo attr = new TLRPC.TL_documentAttributeVideo();
|
||||
attr.duration = getParamInt('d', 0) / 1000;
|
||||
attr.w = getParamInt('w', 0);
|
||||
attr.h = getParamInt('h', 0);
|
||||
attr.w = getParamInt('w', 320);
|
||||
attr.h = getParamInt('h', 240);
|
||||
ret.media.document.attributes.add(attr);
|
||||
}
|
||||
else {
|
||||
ret.media.document.mime_type = getParam('m', "application/octet-stream");
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
ret.message = "<path missing>";
|
||||
ret.message = "<file path missing>";
|
||||
}
|
||||
}
|
||||
else {
|
||||
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
|
||||
*
|
||||
******************************************************************************/
|
||||
@@ -31,10 +30,10 @@ package com.b44t.messenger;
|
||||
|
||||
public class MrPoortext {
|
||||
|
||||
public final static int MR_TITLE_NORMAL = 0;
|
||||
public final static int MR_TITLE_DRAFT = 1;
|
||||
public final static int MR_TITLE_USERNAME = 2;
|
||||
public final static int MR_TITLE_SELF = 3;
|
||||
public final static int MR_TEXT1_NORMAL = 0;
|
||||
public final static int MR_TEXT1_DRAFT = 1;
|
||||
public final static int MR_TEXT1_USERNAME = 2;
|
||||
public final static int MR_TEXT1_SELF = 3;
|
||||
|
||||
public MrPoortext(long hPoortext) {
|
||||
m_hPoortext = hPoortext;
|
||||
@@ -45,16 +44,16 @@ public class MrPoortext {
|
||||
MrPoortextUnref(m_hPoortext);
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return MrPoortextGetTitle(m_hPoortext);
|
||||
public String getText1() {
|
||||
return MrPoortextGetText1(m_hPoortext);
|
||||
}
|
||||
|
||||
public int getTitleMeaning() {
|
||||
return MrPoortextGetTitleMeaning(m_hPoortext);
|
||||
public int getText1Meaning() {
|
||||
return MrPoortextGetText1Meaning(m_hPoortext);
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return MrPoortextGetText(m_hPoortext);
|
||||
public String getText2() {
|
||||
return MrPoortextGetText2(m_hPoortext);
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
@@ -67,9 +66,9 @@ public class MrPoortext {
|
||||
|
||||
private long m_hPoortext;
|
||||
private native static void MrPoortextUnref (long hPoortext);
|
||||
private native static String MrPoortextGetTitle (long hPoortext);
|
||||
private native static int MrPoortextGetTitleMeaning (long hPoortext);
|
||||
private native static String MrPoortextGetText (long hPoortext);
|
||||
private native static String MrPoortextGetText1 (long hPoortext);
|
||||
private native static int MrPoortextGetText1Meaning (long hPoortext);
|
||||
private native static String MrPoortextGetText2 (long hPoortext);
|
||||
private native static long MrPoortextGetTimestamp (long hPoortext);
|
||||
private native static int MrPoortextGetState (long hPoortext);
|
||||
}
|
||||
|
||||
@@ -1,589 +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;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
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.media.MediaDescription;
|
||||
import android.media.MediaMetadata;
|
||||
import android.media.browse.MediaBrowser;
|
||||
import android.media.session.MediaSession;
|
||||
import android.media.session.PlaybackState;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.Process;
|
||||
import android.os.SystemClock;
|
||||
import android.service.media.MediaBrowserService;
|
||||
|
||||
import com.b44t.messenger.audioinfo.AudioInfo;
|
||||
import com.b44t.ui.LaunchActivity;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
public class MusicBrowserService extends MediaBrowserService implements NotificationCenter.NotificationCenterDelegate {
|
||||
|
||||
private static final String AUTO_APP_PACKAGE_NAME = "com.google.android.projection.gearhead";
|
||||
private static final String SLOT_RESERVATION_SKIP_TO_NEXT = "com.google.android.gms.car.media.ALWAYS_RESERVE_SPACE_FOR.ACTION_SKIP_TO_NEXT";
|
||||
private static final String SLOT_RESERVATION_SKIP_TO_PREV = "com.google.android.gms.car.media.ALWAYS_RESERVE_SPACE_FOR.ACTION_SKIP_TO_PREVIOUS";
|
||||
private static final String SLOT_RESERVATION_QUEUE = "com.google.android.gms.car.media.ALWAYS_RESERVE_SPACE_FOR.ACTION_QUEUE";
|
||||
|
||||
private MediaSession mediaSession;
|
||||
private static final String MEDIA_ID_ROOT = "__ROOT__";
|
||||
|
||||
private boolean chatsLoaded;
|
||||
private boolean loadingChats;
|
||||
private ArrayList<Integer> dialogs = new ArrayList<>();
|
||||
private HashMap<Integer, TLRPC.User> users = new HashMap<>();
|
||||
private HashMap<Integer, TLRPC.Chat> chats = new HashMap<>();
|
||||
private HashMap<Integer, ArrayList<MessageObject>> musicObjects = new HashMap<>();
|
||||
private HashMap<Integer, ArrayList<MediaSession.QueueItem>> musicQueues = new HashMap<>();
|
||||
|
||||
public static final String ACTION_CMD = "com.example.android.mediabrowserservice.ACTION_CMD";
|
||||
public static final String CMD_NAME = "CMD_NAME";
|
||||
public static final String CMD_PAUSE = "CMD_PAUSE";
|
||||
|
||||
private Paint roundPaint;
|
||||
private RectF bitmapRect;
|
||||
|
||||
private boolean serviceStarted;
|
||||
|
||||
private int lastSelectedDialog;
|
||||
|
||||
private static final int STOP_DELAY = 30000;
|
||||
|
||||
private DelayedStopHandler delayedStopHandler = new DelayedStopHandler(this);
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
ApplicationLoader.postInitApplication();
|
||||
|
||||
lastSelectedDialog = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE).getInt("auto_lastSelectedDialog", 0);
|
||||
|
||||
mediaSession = new MediaSession(this, "MusicService");
|
||||
setSessionToken(mediaSession.getSessionToken());
|
||||
mediaSession.setCallback(new MediaSessionCallback());
|
||||
mediaSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS | MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
|
||||
|
||||
Context context = getApplicationContext();
|
||||
Intent intent = new Intent(context, LaunchActivity.class);
|
||||
PendingIntent pi = PendingIntent.getActivity(context, 99, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
mediaSession.setSessionActivity(pi);
|
||||
|
||||
Bundle extras = new Bundle();
|
||||
extras.putBoolean(SLOT_RESERVATION_QUEUE, true);
|
||||
extras.putBoolean(SLOT_RESERVATION_SKIP_TO_PREV, true);
|
||||
extras.putBoolean(SLOT_RESERVATION_SKIP_TO_NEXT, true);
|
||||
mediaSession.setExtras(extras);
|
||||
|
||||
updatePlaybackState(null);
|
||||
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioPlayStateChanged);
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioDidStarted);
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioDidReset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent startIntent, int flags, int startId) {
|
||||
/*if (startIntent != null) {
|
||||
String action = startIntent.getAction();
|
||||
String command = startIntent.getStringExtra(CMD_NAME);
|
||||
if (ACTION_CMD.equals(action)) {
|
||||
if (CMD_PAUSE.equals(command)) {
|
||||
if (mPlayback != null && mPlayback.isPlaying()) {
|
||||
handlePauseRequest();
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
handleStopRequest(null);
|
||||
delayedStopHandler.removeCallbacksAndMessages(null);
|
||||
mediaSession.release();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BrowserRoot onGetRoot(String clientPackageName, int clientUid, Bundle rootHints) {
|
||||
if (clientPackageName == null || Process.SYSTEM_UID != clientUid && Process.myUid() != clientUid && !clientPackageName.equals("com.google.android.mediasimulator") && !clientPackageName.equals("com.google.android.projection.gearhead")) {
|
||||
return null;
|
||||
}
|
||||
return new BrowserRoot(MEDIA_ID_ROOT, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadChildren(final String parentMediaId, final Result<List<MediaBrowser.MediaItem>> result) {
|
||||
if (!chatsLoaded) {
|
||||
result.detach();
|
||||
if (loadingChats) {
|
||||
return;
|
||||
}
|
||||
loadingChats = true;
|
||||
/*
|
||||
MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
ArrayList<Integer> usersToLoad = new ArrayList<>();
|
||||
ArrayList<Integer> chatsToLoad = new ArrayList<>();
|
||||
SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT DISTINCT uid FROM media_v2 WHERE uid != 0 AND mid > 0 AND type = %d", SharedMediaQuery.MEDIA_MUSIC));
|
||||
while (cursor.next()) {
|
||||
int lower_part = (int) cursor.longValue(0);
|
||||
if (lower_part == 0) {
|
||||
continue;
|
||||
}
|
||||
dialogs.add(lower_part);
|
||||
if (lower_part > 0) {
|
||||
usersToLoad.add(lower_part);
|
||||
} else {
|
||||
chatsToLoad.add(-lower_part);
|
||||
}
|
||||
}
|
||||
cursor.dispose();
|
||||
if (!dialogs.isEmpty()) {
|
||||
String ids = TextUtils.join(",", dialogs);
|
||||
cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT uid, data, mid FROM media_v2 WHERE uid IN (%s) AND mid > 0 AND type = %d ORDER BY date DESC, mid DESC", ids, SharedMediaQuery.MEDIA_MUSIC));
|
||||
while (cursor.next()) {
|
||||
NativeByteBuffer data = cursor.byteBufferValue(1);
|
||||
if (data != null) {
|
||||
TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false);
|
||||
data.reuse();
|
||||
if (MessageObject.isMusicMessage(message)) {
|
||||
int did = cursor.intValue(0);
|
||||
message.id = cursor.intValue(2);
|
||||
message.dialog_id = did;
|
||||
ArrayList<MessageObject> arrayList = musicObjects.get(did);
|
||||
ArrayList<MediaSession.QueueItem> arrayList1 = musicQueues.get(did);
|
||||
if (arrayList == null) {
|
||||
arrayList = new ArrayList<>();
|
||||
musicObjects.put(did, arrayList);
|
||||
arrayList1 = new ArrayList<>();
|
||||
musicQueues.put(did, arrayList1);
|
||||
}
|
||||
MessageObject messageObject = new MessageObject(message, null, false);
|
||||
arrayList.add(0, messageObject);
|
||||
MediaDescription.Builder builder = new MediaDescription.Builder().setMediaId(did + "_" + arrayList.size());
|
||||
builder.setTitle(messageObject.getMusicTitle());
|
||||
builder.setSubtitle(messageObject.getMusicAuthor());
|
||||
arrayList1.add(0, new MediaSession.QueueItem(builder.build(), arrayList1.size()));
|
||||
}
|
||||
}
|
||||
}
|
||||
cursor.dispose();
|
||||
if (!usersToLoad.isEmpty()) {
|
||||
ArrayList<TLRPC.User> usersArrayList = new ArrayList<>();
|
||||
//MessagesStorage.getInstance().getUsersInternal(TextUtils.join(",", usersToLoad), usersArrayList);
|
||||
for (int a = 0; a < usersArrayList.size(); a++) {
|
||||
TLRPC.User user = usersArrayList.get(a);
|
||||
users.put(user.id, user);
|
||||
}
|
||||
}
|
||||
if (!chatsToLoad.isEmpty()) {
|
||||
ArrayList<TLRPC.Chat> chatsArrayList = new ArrayList<>();
|
||||
//MessagesStorage.getInstance().getChatsInternal(TextUtils.join(",", chatsToLoad), chatsArrayList);
|
||||
for (int a = 0; a < chatsArrayList.size(); a++) {
|
||||
TLRPC.Chat chat = chatsArrayList.get(a);
|
||||
chats.put(chat.id, chat);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
AndroidUtilities.runOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
chatsLoaded = true;
|
||||
loadingChats = false;
|
||||
loadChildrenImpl(parentMediaId, result);
|
||||
if (lastSelectedDialog == 0 && !dialogs.isEmpty()) {
|
||||
lastSelectedDialog = dialogs.get(0);
|
||||
}
|
||||
if (lastSelectedDialog != 0) {
|
||||
ArrayList<MessageObject> arrayList = musicObjects.get(lastSelectedDialog);
|
||||
ArrayList<MediaSession.QueueItem> arrayList1 = musicQueues.get(lastSelectedDialog);
|
||||
if (arrayList != null && !arrayList.isEmpty()) {
|
||||
mediaSession.setQueue(arrayList1);
|
||||
if (lastSelectedDialog > 0) {
|
||||
TLRPC.User user = users.get(lastSelectedDialog);
|
||||
if (user != null) {
|
||||
mediaSession.setQueueTitle(ContactsController.formatName(user.first_name, user.last_name));
|
||||
} else {
|
||||
mediaSession.setQueueTitle("DELETED USER");
|
||||
}
|
||||
} else {
|
||||
TLRPC.Chat chat = chats.get(-lastSelectedDialog);
|
||||
if (chat != null) {
|
||||
mediaSession.setQueueTitle(chat.title);
|
||||
} else {
|
||||
mediaSession.setQueueTitle("DELETED CHAT");
|
||||
}
|
||||
}
|
||||
MessageObject messageObject = arrayList.get(0);
|
||||
MediaMetadata.Builder builder = new MediaMetadata.Builder();
|
||||
builder.putLong(MediaMetadata.METADATA_KEY_DURATION, messageObject.getDuration() * 1000);
|
||||
builder.putString(MediaMetadata.METADATA_KEY_ARTIST, messageObject.getMusicAuthor());
|
||||
builder.putString(MediaMetadata.METADATA_KEY_TITLE, messageObject.getMusicTitle());
|
||||
mediaSession.setMetadata(builder.build());
|
||||
}
|
||||
}
|
||||
updatePlaybackState(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
*/
|
||||
} else {
|
||||
loadChildrenImpl(parentMediaId, result);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadChildrenImpl(final String parentMediaId, final Result<List<MediaBrowser.MediaItem>> result) {
|
||||
List<MediaBrowser.MediaItem> mediaItems = new ArrayList<>();
|
||||
|
||||
if (MEDIA_ID_ROOT.equals(parentMediaId)) {
|
||||
for (int a = 0; a < dialogs.size(); a++) {
|
||||
int did = dialogs.get(a);
|
||||
MediaDescription.Builder builder = new MediaDescription.Builder().setMediaId("__CHAT_" + did);
|
||||
TLRPC.FileLocation avatar = null;
|
||||
if (did > 0) {
|
||||
TLRPC.User user = users.get(did);
|
||||
if (user != null) {
|
||||
builder.setTitle(ContactsController.formatName(user.first_name, user.last_name));
|
||||
if (user.photo != null && user.photo.photo_small instanceof TLRPC.TL_fileLocation) {
|
||||
avatar = user.photo.photo_small;
|
||||
}
|
||||
} else {
|
||||
builder.setTitle("DELETED USER");
|
||||
}
|
||||
} else {
|
||||
TLRPC.Chat chat = chats.get(-did);
|
||||
if (chat != null) {
|
||||
builder.setTitle(chat.title);
|
||||
if (chat.photo != null && chat.photo.photo_small instanceof TLRPC.TL_fileLocation) {
|
||||
avatar = chat.photo.photo_small;
|
||||
}
|
||||
} else {
|
||||
builder.setTitle("DELETED CHAT");
|
||||
}
|
||||
}
|
||||
Bitmap bitmap = null;
|
||||
if (avatar != null) {
|
||||
bitmap = createRoundBitmap(FileLoader.getPathToAttach(avatar, true));
|
||||
if (bitmap != null) {
|
||||
builder.setIconBitmap(bitmap);
|
||||
}
|
||||
}
|
||||
if (avatar == null || bitmap == null) {
|
||||
builder.setIconUri(Uri.parse("android.resource://" + getApplicationContext().getPackageName() + "/drawable/contact_blue"));
|
||||
}
|
||||
mediaItems.add(new MediaBrowser.MediaItem(builder.build(), MediaBrowser.MediaItem.FLAG_BROWSABLE));
|
||||
}
|
||||
} else if (parentMediaId != null && parentMediaId.startsWith("__CHAT_")) {
|
||||
int did = 0;
|
||||
try {
|
||||
did = Integer.parseInt(parentMediaId.replace("__CHAT_", ""));
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
ArrayList<MessageObject> arrayList = musicObjects.get(did);
|
||||
if (arrayList != null) {
|
||||
for (int a = 0; a < arrayList.size(); a++) {
|
||||
MessageObject messageObject = arrayList.get(a);
|
||||
MediaDescription.Builder builder = new MediaDescription.Builder().setMediaId(did + "_" + a);
|
||||
builder.setTitle(messageObject.getMusicTitle());
|
||||
builder.setSubtitle(messageObject.getMusicAuthor());
|
||||
mediaItems.add(new MediaBrowser.MediaItem(builder.build(), MediaBrowser.MediaItem.FLAG_PLAYABLE));
|
||||
}
|
||||
}
|
||||
}
|
||||
result.sendResult(mediaItems);
|
||||
}
|
||||
|
||||
private Bitmap createRoundBitmap(File path) {
|
||||
try {
|
||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
options.inSampleSize = 2;
|
||||
Bitmap bitmap = BitmapFactory.decodeFile(path.toString(), options);
|
||||
if (bitmap != null) {
|
||||
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) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private final class MediaSessionCallback extends MediaSession.Callback {
|
||||
@Override
|
||||
public void onPlay() {
|
||||
MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject();
|
||||
if (messageObject == null) {
|
||||
onPlayFromMediaId(lastSelectedDialog + "_" + 0, null);
|
||||
} else {
|
||||
MediaController.getInstance().playAudio(messageObject);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSkipToQueueItem(long queueId) {
|
||||
MediaController.getInstance().playMessageAtIndex((int) queueId);
|
||||
handlePlayRequest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSeekTo(long position) {
|
||||
MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject();
|
||||
if (messageObject != null) {
|
||||
MediaController.getInstance().seekToProgress(messageObject, position / 1000 / (float) messageObject.getDuration());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayFromMediaId(String mediaId, Bundle extras) {
|
||||
String args[] = mediaId.split("_");
|
||||
if (args.length != 2) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
int did = Integer.parseInt(args[0]);
|
||||
int id = Integer.parseInt(args[1]);
|
||||
ArrayList<MessageObject> arrayList = musicObjects.get(did);
|
||||
ArrayList<MediaSession.QueueItem> arrayList1 = musicQueues.get(did);
|
||||
if (arrayList == null || id < 0 || id >= arrayList.size()) {
|
||||
return;
|
||||
}
|
||||
lastSelectedDialog = did;
|
||||
ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE).edit().putInt("auto_lastSelectedDialog", did).commit();
|
||||
MediaController.getInstance().setPlaylist(arrayList, arrayList.get(id), false);
|
||||
mediaSession.setQueue(arrayList1);
|
||||
if (did > 0) {
|
||||
TLRPC.User user = users.get(did);
|
||||
if (user != null) {
|
||||
mediaSession.setQueueTitle(ContactsController.formatName(user.first_name, user.last_name));
|
||||
} else {
|
||||
mediaSession.setQueueTitle("DELETED USER");
|
||||
}
|
||||
} else {
|
||||
TLRPC.Chat chat = chats.get(-did);
|
||||
if (chat != null) {
|
||||
mediaSession.setQueueTitle(chat.title);
|
||||
} else {
|
||||
mediaSession.setQueueTitle("DELETED CHAT");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
handlePlayRequest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
handlePauseRequest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
handleStopRequest(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSkipToNext() {
|
||||
MediaController.getInstance().playNextMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSkipToPrevious() {
|
||||
MediaController.getInstance().playPreviousMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayFromSearch(String query, Bundle extras) {
|
||||
if (query == null || query.length() == 0) {
|
||||
return;
|
||||
}
|
||||
query = query.toLowerCase();
|
||||
for (int a = 0; a < dialogs.size(); a++) {
|
||||
int did = dialogs.get(a);
|
||||
if (did > 0) {
|
||||
TLRPC.User user = users.get(did);
|
||||
if (user == null) {
|
||||
continue;
|
||||
}
|
||||
if (user.first_name != null && user.first_name.startsWith(query) || user.last_name != null && user.last_name.startsWith(query)) {
|
||||
onPlayFromMediaId(did + "_" + 0, null);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
TLRPC.Chat chat = chats.get(-did);
|
||||
if (chat == null) {
|
||||
continue;
|
||||
}
|
||||
if (chat.title != null && chat.title.toLowerCase().contains(query)) {
|
||||
onPlayFromMediaId(did + "_" + 0, null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePlaybackState(String error) {
|
||||
long position = PlaybackState.PLAYBACK_POSITION_UNKNOWN;
|
||||
MessageObject playingMessageObject = MediaController.getInstance().getPlayingMessageObject();
|
||||
if (playingMessageObject != null) {
|
||||
position = playingMessageObject.audioProgressSec * 1000;
|
||||
}
|
||||
|
||||
PlaybackState.Builder stateBuilder = new PlaybackState.Builder().setActions(getAvailableActions());
|
||||
int state;
|
||||
if (playingMessageObject == null) {
|
||||
state = PlaybackState.STATE_STOPPED;
|
||||
} else {
|
||||
if (MediaController.getInstance().isDownloadingCurrentMessage()) {
|
||||
state = PlaybackState.STATE_BUFFERING;
|
||||
} else {
|
||||
state = MediaController.getInstance().isAudioPaused() ? PlaybackState.STATE_PAUSED : PlaybackState.STATE_PLAYING;
|
||||
}
|
||||
}
|
||||
|
||||
if (error != null) {
|
||||
stateBuilder.setErrorMessage(error);
|
||||
state = PlaybackState.STATE_ERROR;
|
||||
}
|
||||
stateBuilder.setState(state, position, 1.0f, SystemClock.elapsedRealtime());
|
||||
if (playingMessageObject != null) {
|
||||
stateBuilder.setActiveQueueItemId(MediaController.getInstance().getPlayingMessageObjectNum());
|
||||
} else {
|
||||
stateBuilder.setActiveQueueItemId(0);
|
||||
}
|
||||
|
||||
mediaSession.setPlaybackState(stateBuilder.build());
|
||||
}
|
||||
|
||||
private long getAvailableActions() {
|
||||
long actions = PlaybackState.ACTION_PLAY | PlaybackState.ACTION_PLAY_FROM_MEDIA_ID | PlaybackState.ACTION_PLAY_FROM_SEARCH;
|
||||
MessageObject playingMessageObject = MediaController.getInstance().getPlayingMessageObject();
|
||||
if (playingMessageObject != null) {
|
||||
if (!MediaController.getInstance().isAudioPaused()) {
|
||||
actions |= PlaybackState.ACTION_PAUSE;
|
||||
}
|
||||
actions |= PlaybackState.ACTION_SKIP_TO_PREVIOUS;
|
||||
actions |= PlaybackState.ACTION_SKIP_TO_NEXT;
|
||||
}
|
||||
return actions;
|
||||
}
|
||||
|
||||
private void handleStopRequest(String withError) {
|
||||
delayedStopHandler.removeCallbacksAndMessages(null);
|
||||
delayedStopHandler.sendEmptyMessageDelayed(0, STOP_DELAY);
|
||||
updatePlaybackState(withError);
|
||||
stopSelf();
|
||||
serviceStarted = false;
|
||||
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioPlayStateChanged);
|
||||
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioDidStarted);
|
||||
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioDidReset);
|
||||
}
|
||||
|
||||
private void handlePlayRequest() {
|
||||
delayedStopHandler.removeCallbacksAndMessages(null);
|
||||
if (!serviceStarted) {
|
||||
startService(new Intent(getApplicationContext(), MusicBrowserService.class));
|
||||
serviceStarted = true;
|
||||
}
|
||||
|
||||
if (!mediaSession.isActive()) {
|
||||
mediaSession.setActive(true);
|
||||
}
|
||||
|
||||
MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject();
|
||||
if (messageObject == null) {
|
||||
return;
|
||||
}
|
||||
MediaMetadata.Builder builder = new MediaMetadata.Builder();
|
||||
builder.putLong(MediaMetadata.METADATA_KEY_DURATION, messageObject.getDuration() * 1000);
|
||||
builder.putString(MediaMetadata.METADATA_KEY_ARTIST, messageObject.getMusicAuthor());
|
||||
builder.putString(MediaMetadata.METADATA_KEY_TITLE, messageObject.getMusicTitle());
|
||||
AudioInfo audioInfo = MediaController.getInstance().getAudioInfo();
|
||||
if (audioInfo != null) {
|
||||
Bitmap bitmap = audioInfo.getCover();
|
||||
if (bitmap != null) {
|
||||
builder.putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, bitmap);
|
||||
}
|
||||
}
|
||||
mediaSession.setMetadata(builder.build());
|
||||
}
|
||||
|
||||
private void handlePauseRequest() {
|
||||
MediaController.getInstance().pauseAudio(MediaController.getInstance().getPlayingMessageObject());
|
||||
delayedStopHandler.removeCallbacksAndMessages(null);
|
||||
delayedStopHandler.sendEmptyMessageDelayed(0, STOP_DELAY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void didReceivedNotification(int id, Object... args) {
|
||||
updatePlaybackState(null);
|
||||
handlePlayRequest();
|
||||
}
|
||||
|
||||
private static class DelayedStopHandler extends Handler {
|
||||
private final WeakReference<MusicBrowserService> mWeakReference;
|
||||
|
||||
private DelayedStopHandler(MusicBrowserService service) {
|
||||
mWeakReference = new WeakReference<>(service);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
MusicBrowserService service = mWeakReference.get();
|
||||
if (service != null) {
|
||||
MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject();
|
||||
if (messageObject != null && !MediaController.getInstance().isAudioPaused()) {
|
||||
return;
|
||||
}
|
||||
service.stopSelf();
|
||||
service.serviceStarted = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -46,10 +61,10 @@ public class MusicPlayerReceiver extends BroadcastReceiver {
|
||||
case KeyEvent.KEYCODE_MEDIA_STOP:
|
||||
break;
|
||||
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
||||
MediaController.getInstance().playNextMessage();
|
||||
MediaController.getInstance().playNextMessage(+1, false);
|
||||
break;
|
||||
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
|
||||
MediaController.getInstance().playPreviousMessage();
|
||||
MediaController.getInstance().playNextMessage(-1, false);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@@ -58,11 +73,11 @@ public class MusicPlayerReceiver extends BroadcastReceiver {
|
||||
} else if (intent.getAction().equals(MusicPlayerService.NOTIFY_PAUSE) || intent.getAction().equals(android.media.AudioManager.ACTION_AUDIO_BECOMING_NOISY)) {
|
||||
MediaController.getInstance().pauseAudio(MediaController.getInstance().getPlayingMessageObject());
|
||||
} else if (intent.getAction().equals(MusicPlayerService.NOTIFY_NEXT)) {
|
||||
MediaController.getInstance().playNextMessage();
|
||||
MediaController.getInstance().playNextMessage(+1, false);
|
||||
} else if (intent.getAction().equals(MusicPlayerService.NOTIFY_CLOSE)) {
|
||||
MediaController.getInstance().cleanupPlayer(true, true);
|
||||
} else if (intent.getAction().equals(MusicPlayerService.NOTIFY_PREVIOUS)) {
|
||||
MediaController.getInstance().playPreviousMessage();
|
||||
MediaController.getInstance().playNextMessage(-1, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -38,7 +53,6 @@ public class MusicPlayerService extends Service implements NotificationCenter.No
|
||||
private RemoteControlClient remoteControlClient;
|
||||
private AudioManager audioManager;
|
||||
|
||||
private static boolean supportBigNotifications = Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
|
||||
private static boolean supportLockScreenControls = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH;
|
||||
|
||||
@Override
|
||||
@@ -93,95 +107,70 @@ public class MusicPlayerService extends Service implements NotificationCenter.No
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
private void createNotification(MessageObject messageObject) {
|
||||
String songName = messageObject.getMusicTitle();
|
||||
String authorName = messageObject.getMusicAuthor();
|
||||
private void createNotification(MessageObject messageObject)
|
||||
{
|
||||
AudioInfo audioInfo = MediaController.getInstance().getAudioInfo();
|
||||
|
||||
RemoteViews simpleContentView = new RemoteViews(getApplicationContext().getPackageName(), R.layout.player_small_notification);
|
||||
RemoteViews expandedView = null;
|
||||
if (supportBigNotifications) {
|
||||
expandedView = new RemoteViews(getApplicationContext().getPackageName(), R.layout.player_big_notification);
|
||||
MrPoortext pt = MrMailbox.getMsg(messageObject.getId()).getMediainfo();
|
||||
String authorName = pt.getText1();
|
||||
String songName = pt.getText2();
|
||||
if( songName == null || songName.length()==0 ) {
|
||||
TLRPC.Document document = messageObject.messageOwner.media.document;
|
||||
for (int i = 0; i < document.attributes.size(); i++) {
|
||||
TLRPC.DocumentAttribute attr = document.attributes.get(i);
|
||||
if (attr instanceof TLRPC.TL_documentAttributeAudio) {
|
||||
authorName = attr.performer;
|
||||
songName = attr.title;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Intent intent = new Intent(ApplicationLoader.applicationContext, LaunchActivity.class);
|
||||
intent.setAction("com.b44t.messenger.openplayer");
|
||||
intent.setFlags(32768);
|
||||
PendingIntent contentIntent = PendingIntent.getActivity(ApplicationLoader.applicationContext, 0, intent, 0);
|
||||
if( songName == null || songName.length()==0 ) {
|
||||
// preview of just recorded and not send voice messages
|
||||
authorName = ApplicationLoader.applicationContext.getString(R.string.FromSelf);
|
||||
songName = ApplicationLoader.applicationContext.getString(R.string.AttachVoiceMessage);
|
||||
}
|
||||
|
||||
RemoteViews simpleContentView = new RemoteViews(getApplicationContext().getPackageName(), R.layout.player_small_notification);
|
||||
|
||||
//Intent intent = new Intent(ApplicationLoader.applicationContext, LaunchActivity.class);
|
||||
//intent.setAction("com.b44t.messenger.openchat"+messageObject.getDialogId());
|
||||
//intent.setFlags(32768);
|
||||
//PendingIntent contentIntent = PendingIntent.getActivity(ApplicationLoader.applicationContext, 0, intent, 0);
|
||||
|
||||
Notification notification = new NotificationCompat.Builder(getApplicationContext())
|
||||
.setSmallIcon(R.drawable.player)
|
||||
.setContentIntent(contentIntent)
|
||||
.setSmallIcon(R.drawable.notification_player)
|
||||
//.setContentIntent(contentIntent)
|
||||
.setContentTitle(songName).build();
|
||||
|
||||
notification.contentView = simpleContentView;
|
||||
if (supportBigNotifications) {
|
||||
notification.bigContentView = expandedView;
|
||||
}
|
||||
|
||||
setListeners(simpleContentView);
|
||||
if (supportBigNotifications) {
|
||||
setListeners(expandedView);
|
||||
}
|
||||
|
||||
Bitmap albumArt = audioInfo != null ? audioInfo.getSmallCover() : null;
|
||||
if (albumArt != null) {
|
||||
notification.contentView.setImageViewBitmap(R.id.player_album_art, albumArt);
|
||||
if (supportBigNotifications) {
|
||||
notification.bigContentView.setImageViewBitmap(R.id.player_album_art, albumArt);
|
||||
}
|
||||
notification.contentView.setViewVisibility(R.id.player_album_art, View.VISIBLE);
|
||||
} else {
|
||||
notification.contentView.setImageViewResource(R.id.player_album_art, R.drawable.nocover_small);
|
||||
if (supportBigNotifications) {
|
||||
notification.bigContentView.setImageViewResource(R.id.player_album_art, R.drawable.nocover_big);
|
||||
}
|
||||
notification.contentView.setViewVisibility(R.id.player_album_art, View.GONE);
|
||||
}
|
||||
if (MediaController.getInstance().isDownloadingCurrentMessage()) {
|
||||
notification.contentView.setViewVisibility(R.id.player_pause, View.GONE);
|
||||
notification.contentView.setViewVisibility(R.id.player_play, View.GONE);
|
||||
notification.contentView.setViewVisibility(R.id.player_next, View.GONE);
|
||||
notification.contentView.setViewVisibility(R.id.player_previous, View.GONE);
|
||||
notification.contentView.setViewVisibility(R.id.player_progress_bar, View.VISIBLE);
|
||||
if (supportBigNotifications) {
|
||||
notification.bigContentView.setViewVisibility(R.id.player_pause, View.GONE);
|
||||
notification.bigContentView.setViewVisibility(R.id.player_play, View.GONE);
|
||||
notification.bigContentView.setViewVisibility(R.id.player_next, View.GONE);
|
||||
notification.bigContentView.setViewVisibility(R.id.player_previous, View.GONE);
|
||||
notification.bigContentView.setViewVisibility(R.id.player_progress_bar, View.VISIBLE);
|
||||
}
|
||||
} else {
|
||||
notification.contentView.setViewVisibility(R.id.player_progress_bar, View.GONE);
|
||||
|
||||
{
|
||||
notification.contentView.setViewVisibility(R.id.player_next, View.VISIBLE);
|
||||
notification.contentView.setViewVisibility(R.id.player_previous, View.VISIBLE);
|
||||
if (supportBigNotifications) {
|
||||
notification.bigContentView.setViewVisibility(R.id.player_next, View.VISIBLE);
|
||||
notification.bigContentView.setViewVisibility(R.id.player_previous, View.VISIBLE);
|
||||
notification.bigContentView.setViewVisibility(R.id.player_progress_bar, View.GONE);
|
||||
}
|
||||
|
||||
if (MediaController.getInstance().isAudioPaused()) {
|
||||
notification.contentView.setViewVisibility(R.id.player_pause, View.GONE);
|
||||
notification.contentView.setViewVisibility(R.id.player_play, View.VISIBLE);
|
||||
if (supportBigNotifications) {
|
||||
notification.bigContentView.setViewVisibility(R.id.player_pause, View.GONE);
|
||||
notification.bigContentView.setViewVisibility(R.id.player_play, View.VISIBLE);
|
||||
}
|
||||
} else {
|
||||
notification.contentView.setViewVisibility(R.id.player_pause, View.VISIBLE);
|
||||
notification.contentView.setViewVisibility(R.id.player_play, View.GONE);
|
||||
if (supportBigNotifications) {
|
||||
notification.bigContentView.setViewVisibility(R.id.player_pause, View.VISIBLE);
|
||||
notification.bigContentView.setViewVisibility(R.id.player_play, View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
notification.contentView.setTextViewText(R.id.player_song_name, songName);
|
||||
notification.contentView.setTextViewText(R.id.player_author_name, authorName);
|
||||
if (supportBigNotifications) {
|
||||
notification.bigContentView.setTextViewText(R.id.player_song_name, songName);
|
||||
notification.bigContentView.setTextViewText(R.id.player_author_name, authorName);
|
||||
}
|
||||
notification.flags |= Notification.FLAG_ONGOING_EVENT;
|
||||
startForeground(5, notification);
|
||||
|
||||
@@ -203,12 +192,16 @@ public class MusicPlayerService extends Service implements NotificationCenter.No
|
||||
public void setListeners(RemoteViews view) {
|
||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, new Intent(NOTIFY_PREVIOUS), PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
view.setOnClickPendingIntent(R.id.player_previous, pendingIntent);
|
||||
|
||||
pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, new Intent(NOTIFY_CLOSE), PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
view.setOnClickPendingIntent(R.id.player_close, pendingIntent);
|
||||
|
||||
pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, new Intent(NOTIFY_PAUSE), PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
view.setOnClickPendingIntent(R.id.player_pause, pendingIntent);
|
||||
|
||||
pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, new Intent(NOTIFY_NEXT), PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
view.setOnClickPendingIntent(R.id.player_next, pendingIntent);
|
||||
|
||||
pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, new Intent(NOTIFY_PLAY), PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
view.setOnClickPendingIntent(R.id.player_play, pendingIntent);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -16,71 +31,35 @@ public class NotificationCenter {
|
||||
|
||||
private static int totalEvents = 1;
|
||||
|
||||
public static final int connectionStateChanged = totalEvents++;
|
||||
public static final int configureEnded = totalEvents++;
|
||||
public static final int configureProgress = totalEvents++;
|
||||
public static final int didReceivedNewMessages = totalEvents++;
|
||||
public static final int updateInterfaces = totalEvents++;
|
||||
public static final int dialogsNeedReload = totalEvents++;
|
||||
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 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 waveformCalculated = 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++;
|
||||
|
||||
public static final int messageThumbGenerated = totalEvents++;
|
||||
|
||||
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++;
|
||||
public static final int FileUploadProgressChanged = totalEvents++;
|
||||
public static final int FileLoadProgressChanged = totalEvents++;
|
||||
public static final int FileDidLoaded = totalEvents++;
|
||||
public static final int FileDidFailedLoad = totalEvents++;
|
||||
@@ -95,7 +74,6 @@ public class NotificationCenter {
|
||||
public static final int recordStarted = totalEvents++;
|
||||
public static final int recordStartError = totalEvents++;
|
||||
public static final int recordStopped = totalEvents++;
|
||||
public static final int screenshotTook = totalEvents++;
|
||||
public static final int albumsDidLoaded = totalEvents++;
|
||||
public static final int audioDidSent = totalEvents++;
|
||||
public static final int audioDidStarted = totalEvents++;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -18,6 +33,6 @@ public class NotificationDismissReceiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Context.MODE_PRIVATE);
|
||||
preferences.edit().putInt("dismissDate", intent.getIntExtra("messageDate", 0)).commit();
|
||||
preferences.edit().putInt("dismissDate", intent.getIntExtra("messageDate", 0)).apply();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,29 +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;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
public class ShareBroadcastReceiver extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String url = intent.getDataString();
|
||||
if (url != null) {
|
||||
Intent shareIntent = new Intent(Intent.ACTION_SEND);
|
||||
shareIntent.setType("text/plain");
|
||||
shareIntent.putExtra(Intent.EXTRA_TEXT, url);
|
||||
Intent chooserIntent = Intent.createChooser(shareIntent, LocaleController.getString("ShareLink", R.string.ShareLink));
|
||||
chooserIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(chooserIntent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,19 +32,15 @@ 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;
|
||||
}
|
||||
|
||||
public static class ChatPhoto extends TLObject {
|
||||
public FileLocation photo_small;
|
||||
public FileLocation photo_big;
|
||||
}
|
||||
|
||||
@@ -39,7 +50,6 @@ public class TLRPC {
|
||||
public int duration;
|
||||
public String alt;
|
||||
public InputStickerSet stickerset;
|
||||
public int flags;
|
||||
public boolean voice;
|
||||
public String title;
|
||||
public String performer;
|
||||
@@ -65,180 +75,43 @@ public class TLRPC {
|
||||
public static class TL_documentAttributeFilename extends DocumentAttribute {
|
||||
}
|
||||
|
||||
public static class messages_Messages extends TLObject {
|
||||
public ArrayList<Message> messages = new ArrayList<>();
|
||||
public ArrayList<Chat> chats = new ArrayList<>();
|
||||
public ArrayList<User> users = new ArrayList<>();
|
||||
public int flags;
|
||||
public int pts;
|
||||
public int count;
|
||||
}
|
||||
|
||||
public static class TL_messages_messages extends messages_Messages {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 {
|
||||
}
|
||||
|
||||
public static class TL_messageMediaVenue extends MessageMedia {
|
||||
}
|
||||
|
||||
public static class TL_messageMediaDocument extends MessageMedia {
|
||||
}
|
||||
|
||||
public static class TL_messageMediaContact extends MessageMedia {
|
||||
}
|
||||
|
||||
public static class TL_messageMediaPhoto extends MessageMedia {
|
||||
}
|
||||
|
||||
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;
|
||||
public int mute_until;
|
||||
public String sound;
|
||||
}
|
||||
|
||||
public static class TL_peerNotifySettings extends PeerNotifySettings {
|
||||
}
|
||||
|
||||
public static class TL_messages_stickerSet extends TLObject {
|
||||
public StickerSet set;
|
||||
public ArrayList<TL_stickerPack> packs = new ArrayList<>();
|
||||
public ArrayList<Document> documents = new ArrayList<>();
|
||||
}
|
||||
|
||||
public static class InputGeoPoint extends TLObject {
|
||||
public double lat;
|
||||
public double _long;
|
||||
}
|
||||
|
||||
public static class TL_inputGeoPoint extends InputGeoPoint {
|
||||
}
|
||||
|
||||
public static class Audio extends TLObject {
|
||||
public long id;
|
||||
public int date;
|
||||
public int duration;
|
||||
public String mime_type;
|
||||
public int size;
|
||||
public int dc_id;
|
||||
public final int dc_id = 0;
|
||||
public int user_id;
|
||||
public byte[] key;
|
||||
public byte[] iv;
|
||||
}
|
||||
|
||||
public static class ChatFull extends TLObject {
|
||||
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;
|
||||
public long volume_id;
|
||||
public int local_id;
|
||||
public long secret;
|
||||
}
|
||||
|
||||
public static class TL_inputDocumentFileLocation extends InputFileLocation {
|
||||
@@ -252,62 +125,10 @@ 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;
|
||||
@@ -320,19 +141,6 @@ public class TLRPC {
|
||||
public int h;
|
||||
public String mime_type;
|
||||
public String caption;
|
||||
public byte[] key;
|
||||
public byte[] iv;
|
||||
}
|
||||
|
||||
public static class TopPeerCategory extends TLObject {
|
||||
}
|
||||
|
||||
public static class InputDocument extends TLObject {
|
||||
public long id;
|
||||
public long access_hash;
|
||||
}
|
||||
|
||||
public static class TL_inputDocument extends InputDocument {
|
||||
}
|
||||
|
||||
public static class Document extends TLObject {
|
||||
@@ -355,169 +163,21 @@ public class TLRPC {
|
||||
public static class TL_document extends Document {
|
||||
}
|
||||
|
||||
public static class InputMedia extends TLObject {
|
||||
public InputFile file;
|
||||
public InputFile thumb;
|
||||
public String mime_type;
|
||||
public ArrayList<DocumentAttribute> attributes = new ArrayList<>();
|
||||
public String caption;
|
||||
public InputGeoPoint geo_point;
|
||||
public String title;
|
||||
public String address;
|
||||
public String provider;
|
||||
public String venue_id;
|
||||
public String phone_number;
|
||||
public String first_name;
|
||||
public String last_name;
|
||||
public String url;
|
||||
public String q;
|
||||
}
|
||||
|
||||
public static class TL_inputMediaContact extends InputMedia {
|
||||
}
|
||||
|
||||
public static class TL_inputMediaUploadedThumbDocument extends InputMedia {
|
||||
}
|
||||
|
||||
public static class TL_inputMediaDocument extends InputMedia {
|
||||
public InputDocument id;
|
||||
}
|
||||
|
||||
public static class TL_inputMediaGifExternal extends InputMedia {
|
||||
}
|
||||
|
||||
public static class TL_inputMediaGeoPoint extends InputMedia {
|
||||
}
|
||||
|
||||
public static class TL_inputMediaUploadedPhoto extends InputMedia {
|
||||
}
|
||||
|
||||
public static class TL_inputMediaVenue extends InputMedia {
|
||||
}
|
||||
|
||||
public static class TL_inputMediaUploadedDocument extends InputMedia {
|
||||
}
|
||||
|
||||
public static class TL_inputMediaPhoto extends InputMedia {
|
||||
public InputPhoto id;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public static class UserProfilePhoto extends TLObject {
|
||||
public FileLocation photo_small;
|
||||
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;
|
||||
public int user_id;
|
||||
public int date;
|
||||
public String caption;
|
||||
@@ -530,49 +190,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 final int version = 0;
|
||||
public final boolean editor = false;
|
||||
public String username;
|
||||
public boolean restricted;
|
||||
public boolean signatures;
|
||||
public String restriction_reason;
|
||||
public boolean min;
|
||||
public String address;
|
||||
public final boolean signatures = false;
|
||||
public final boolean min = false;
|
||||
public final String address = null;
|
||||
}
|
||||
|
||||
public static class StickerSet extends TLObject {
|
||||
public long id;
|
||||
public long access_hash;
|
||||
public String title;
|
||||
public int flags;
|
||||
public boolean installed;
|
||||
@@ -582,33 +216,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 +236,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 +260,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,140 +274,51 @@ 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;
|
||||
}
|
||||
|
||||
public static class TL_inputPhoto extends InputPhoto {
|
||||
}
|
||||
|
||||
public static class InputPeer extends TLObject {
|
||||
public int user_id;
|
||||
public long access_hash;
|
||||
public int chat_id;
|
||||
public int channel_id;
|
||||
}
|
||||
|
||||
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;
|
||||
public GeoPoint geo;
|
||||
public String title;
|
||||
public String address;
|
||||
public String provider;
|
||||
public String venue_id;
|
||||
public Document document;
|
||||
public String caption;
|
||||
public String phone_number;
|
||||
public String first_name;
|
||||
public String last_name;
|
||||
public int user_id;
|
||||
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 final int reply_to_msg_id = 0;
|
||||
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 final int views = 0;
|
||||
public final boolean silent = false;
|
||||
public final boolean post = false;// ? true=avatar wird in gruppen nicht angezeigt, wird aber in isFromUser() auch überprüft...
|
||||
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 final int layer = 0; //custom
|
||||
public boolean created_by_mr;
|
||||
}
|
||||
|
||||
public static class TL_messageEmpty extends Message {
|
||||
}
|
||||
|
||||
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;
|
||||
public int top_message;
|
||||
public int unread_count;
|
||||
public PeerNotifySettings notify_settings;
|
||||
public int pts;
|
||||
public final int top_message = 0;
|
||||
public final int unread_count = 0;
|
||||
public final int pts = 0;
|
||||
public DraftMessage draft;
|
||||
public int last_message_date; //custom
|
||||
public long id; //custom
|
||||
}
|
||||
|
||||
public static class TL_chatEmpty extends Chat {
|
||||
}
|
||||
public static class Vector extends TLObject {
|
||||
public ArrayList<Object> objects = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,172 +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;
|
||||
|
||||
// ChooserTargetService, see https://developer.android.com/reference/android/service/chooser/ChooserTargetService.html
|
||||
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Build;
|
||||
import android.service.chooser.ChooserTarget;
|
||||
import android.service.chooser.ChooserTargetService;
|
||||
|
||||
import com.b44t.ui.LaunchActivity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.M)
|
||||
public class TgChooserTargetService extends ChooserTargetService {
|
||||
|
||||
@Override
|
||||
public List<ChooserTarget> onGetChooserTargets(ComponentName targetActivityName, IntentFilter matchedFilter) {
|
||||
final List<ChooserTarget> targets = new ArrayList<>();
|
||||
if (!UserConfig.isClientActivated()) {
|
||||
return targets;
|
||||
}
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
|
||||
if (!preferences.getBoolean("direct_share", true)) {
|
||||
return targets;
|
||||
}
|
||||
|
||||
ImageLoader imageLoader = ImageLoader.getInstance();
|
||||
final Semaphore semaphore = new Semaphore(0);
|
||||
final ComponentName componentName = new ComponentName(getPackageName(), LaunchActivity.class.getCanonicalName());
|
||||
/*
|
||||
MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ArrayList<Integer> dialogs = new ArrayList<>();
|
||||
ArrayList<TLRPC.Chat> chats = new ArrayList<>();
|
||||
ArrayList<TLRPC.User> users = new ArrayList<>();
|
||||
try {
|
||||
ArrayList<Integer> usersToLoad = new ArrayList<>();
|
||||
usersToLoad.add(UserConfig.getClientUserId());
|
||||
ArrayList<Integer> chatsToLoad = new ArrayList<>();
|
||||
SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT did FROM dialogs ORDER BY date DESC LIMIT %d,%d", 0, 30));
|
||||
while (cursor.next()) {
|
||||
long id = cursor.longValue(0);
|
||||
|
||||
int lower_id = (int) id;
|
||||
int high_id = (int) (id >> 32);
|
||||
if (lower_id != 0) {
|
||||
if (high_id == 1) {
|
||||
continue;
|
||||
} else {
|
||||
if (lower_id > 0) {
|
||||
if (!usersToLoad.contains(lower_id)) {
|
||||
usersToLoad.add(lower_id);
|
||||
}
|
||||
} else {
|
||||
if (!chatsToLoad.contains(-lower_id)) {
|
||||
chatsToLoad.add(-lower_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
dialogs.add(lower_id);
|
||||
if (dialogs.size() == 8) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
cursor.dispose();
|
||||
if (!chatsToLoad.isEmpty()) {
|
||||
//MessagesStorage.getInstance().getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
||||
}
|
||||
if (!usersToLoad.isEmpty()) {
|
||||
//MessagesStorage.getInstance().getUsersInternal(TextUtils.join(",", usersToLoad), users);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
for (int a = 0; a < dialogs.size(); a++) {
|
||||
Bundle extras = new Bundle();
|
||||
Icon icon = null;
|
||||
String name = null;
|
||||
int id = dialogs.get(a);
|
||||
if (id > 0) {
|
||||
for (int b = 0; b < users.size(); b++) {
|
||||
TLRPC.User user = users.get(b);
|
||||
if (user.id == id) {
|
||||
if (!user.bot) {
|
||||
extras.putLong("dialogId", (long) id);
|
||||
if (user.photo != null && user.photo.photo_small != null) {
|
||||
icon = createRoundBitmap(FileLoader.getPathToAttach(user.photo.photo_small, true));
|
||||
}
|
||||
name = ContactsController.formatName(user.first_name, user.last_name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int b = 0; b < chats.size(); b++) {
|
||||
TLRPC.Chat chat = chats.get(b);
|
||||
if (chat.id == -id) {
|
||||
if (!ChatObject.isNotInChat(chat) && (!ChatObject.isChannel(chat) || chat.megagroup)) {
|
||||
extras.putLong("dialogId", (long) id);
|
||||
if (chat.photo != null && chat.photo.photo_small != null) {
|
||||
icon = createRoundBitmap(FileLoader.getPathToAttach(chat.photo.photo_small, true));
|
||||
}
|
||||
name = chat.title;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (name != null) {
|
||||
if (icon == null) {
|
||||
icon = Icon.createWithResource(ApplicationLoader.applicationContext, R.drawable.logo_avatar);
|
||||
}
|
||||
targets.add(new ChooserTarget(name, icon, 1.0f, componentName, extras));
|
||||
}
|
||||
}
|
||||
semaphore.release();
|
||||
}
|
||||
});
|
||||
*/
|
||||
try {
|
||||
semaphore.acquire();
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
return targets;
|
||||
}
|
||||
|
||||
/*
|
||||
private Icon createRoundBitmap(File path) {
|
||||
try {
|
||||
Bitmap bitmap = BitmapFactory.decodeFile(path.toString());
|
||||
if (bitmap != null) {
|
||||
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 Icon.createWithBitmap(result);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
FileLog.e("messenger", 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;
|
||||
|
||||
@@ -17,15 +32,8 @@ import java.io.File;
|
||||
public class UserConfig {
|
||||
|
||||
private static TLRPC.User currentUser;
|
||||
public static boolean registeredForPush;
|
||||
public static String pushString = "";
|
||||
public static int lastSendMessageId = -210000;
|
||||
public static int lastLocalId = -210000;
|
||||
public static int lastBroadcastId = -1;
|
||||
public static String contactsHash = "";
|
||||
public static boolean blockedUsersLoaded;
|
||||
private final static Object sync = new Object();
|
||||
public static boolean saveIncomingPhotos;
|
||||
public static String passcodeHash = "";
|
||||
public static byte[] passcodeSalt = new byte[0];
|
||||
public static boolean appLocked;
|
||||
@@ -34,26 +42,6 @@ public class UserConfig {
|
||||
public static int lastPauseTime;
|
||||
public static boolean isWaitingForPasscodeEnter;
|
||||
public static boolean useFingerprint = true;
|
||||
public static String lastUpdateVersion;
|
||||
public static int lastContactsSyncTime;
|
||||
public static int lastHintsSyncTime;
|
||||
public static boolean draftsLoaded;
|
||||
|
||||
public static int migrateOffsetId = -1;
|
||||
public static int migrateOffsetDate = -1;
|
||||
public static int migrateOffsetUserId = -1;
|
||||
public static int migrateOffsetChatId = -1;
|
||||
public static int migrateOffsetChannelId = -1;
|
||||
public static long migrateOffsetAccess = -1;
|
||||
|
||||
public static int getNewMessageId() {
|
||||
int id;
|
||||
synchronized (sync) {
|
||||
id = lastSendMessageId;
|
||||
lastSendMessageId--;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
public static void saveConfig(boolean withFile) {
|
||||
saveConfig(withFile, null);
|
||||
@@ -64,34 +52,14 @@ public class UserConfig {
|
||||
try {
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("userconfing", Context.MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putBoolean("registeredForPush", registeredForPush);
|
||||
editor.putString("pushString2", pushString);
|
||||
editor.putInt("lastSendMessageId", lastSendMessageId);
|
||||
editor.putInt("lastLocalId", lastLocalId);
|
||||
editor.putString("contactsHash", contactsHash);
|
||||
editor.putBoolean("saveIncomingPhotos", saveIncomingPhotos);
|
||||
editor.putInt("lastBroadcastId", lastBroadcastId);
|
||||
editor.putBoolean("blockedUsersLoaded", blockedUsersLoaded);
|
||||
editor.putString("passcodeHash1", passcodeHash);
|
||||
editor.putString("passcodeSalt", passcodeSalt.length > 0 ? Base64.encodeToString(passcodeSalt, Base64.DEFAULT) : "");
|
||||
editor.putBoolean("appLocked", appLocked);
|
||||
editor.putInt("passcodeType", passcodeType);
|
||||
editor.putInt("autoLockIn", autoLockIn);
|
||||
editor.putInt("lastPauseTime", lastPauseTime);
|
||||
editor.putString("lastUpdateVersion2", lastUpdateVersion);
|
||||
editor.putInt("lastContactsSyncTime", lastContactsSyncTime);
|
||||
editor.putBoolean("useFingerprint", useFingerprint);
|
||||
editor.putInt("lastHintsSyncTime", lastHintsSyncTime);
|
||||
editor.putBoolean("draftsLoaded", draftsLoaded);
|
||||
|
||||
editor.putInt("migrateOffsetId", migrateOffsetId);
|
||||
if (migrateOffsetId != -1) {
|
||||
editor.putInt("migrateOffsetDate", migrateOffsetDate);
|
||||
editor.putInt("migrateOffsetUserId", migrateOffsetUserId);
|
||||
editor.putInt("migrateOffsetChatId", migrateOffsetChatId);
|
||||
editor.putInt("migrateOffsetChannelId", migrateOffsetChannelId);
|
||||
editor.putLong("migrateOffsetAccess", migrateOffsetAccess);
|
||||
}
|
||||
|
||||
/*
|
||||
if (currentUser != null) {
|
||||
@@ -107,7 +75,7 @@ public class UserConfig {
|
||||
}
|
||||
*/
|
||||
|
||||
editor.commit();
|
||||
editor.apply();
|
||||
if (oldFile != null) {
|
||||
oldFile.delete();
|
||||
}
|
||||
@@ -216,33 +184,13 @@ public class UserConfig {
|
||||
*/
|
||||
{
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("userconfing", Context.MODE_PRIVATE);
|
||||
registeredForPush = preferences.getBoolean("registeredForPush", false);
|
||||
pushString = preferences.getString("pushString2", "");
|
||||
lastSendMessageId = preferences.getInt("lastSendMessageId", -210000);
|
||||
lastLocalId = preferences.getInt("lastLocalId", -210000);
|
||||
contactsHash = preferences.getString("contactsHash", "");
|
||||
saveIncomingPhotos = preferences.getBoolean("saveIncomingPhotos", false);
|
||||
lastBroadcastId = preferences.getInt("lastBroadcastId", -1);
|
||||
blockedUsersLoaded = preferences.getBoolean("blockedUsersLoaded", false);
|
||||
passcodeHash = preferences.getString("passcodeHash1", "");
|
||||
appLocked = preferences.getBoolean("appLocked", false);
|
||||
passcodeType = preferences.getInt("passcodeType", 0);
|
||||
autoLockIn = preferences.getInt("autoLockIn", 60 * 60);
|
||||
lastPauseTime = preferences.getInt("lastPauseTime", 0);
|
||||
useFingerprint = preferences.getBoolean("useFingerprint", true);
|
||||
lastUpdateVersion = preferences.getString("lastUpdateVersion2", "3.5");
|
||||
lastContactsSyncTime = preferences.getInt("lastContactsSyncTime", (int) (System.currentTimeMillis() / 1000) - 23 * 60 * 60);
|
||||
lastHintsSyncTime = preferences.getInt("lastHintsSyncTime", (int) (System.currentTimeMillis() / 1000) - 25 * 60 * 60);
|
||||
draftsLoaded = preferences.getBoolean("draftsLoaded", false);
|
||||
|
||||
migrateOffsetId = preferences.getInt("migrateOffsetId", 0);
|
||||
if (migrateOffsetId != -1) {
|
||||
migrateOffsetDate = preferences.getInt("migrateOffsetDate", 0);
|
||||
migrateOffsetUserId = preferences.getInt("migrateOffsetUserId", 0);
|
||||
migrateOffsetChatId = preferences.getInt("migrateOffsetChatId", 0);
|
||||
migrateOffsetChannelId = preferences.getInt("migrateOffsetChannelId", 0);
|
||||
migrateOffsetAccess = preferences.getLong("migrateOffsetAccess", 0);
|
||||
}
|
||||
|
||||
/*
|
||||
String user = preferences.getString("user", null);
|
||||
|
||||
@@ -1,39 +1,31 @@
|
||||
/*
|
||||
* 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,57 +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 java.util.Locale;
|
||||
|
||||
public class VideoEditedInfo {
|
||||
public long startTime;
|
||||
public long endTime;
|
||||
public int rotationValue;
|
||||
public int originalWidth;
|
||||
public int originalHeight;
|
||||
public int originalBitrate;
|
||||
public int resultWidth;
|
||||
public int resultHeight;
|
||||
public int bitrate;
|
||||
public int resultBitrate;
|
||||
public String originalPath;
|
||||
|
||||
public String getString() {
|
||||
return String.format(Locale.US, "-1_%d_%d_%d_%d_%d_%d_%d_%d_%s", startTime, endTime, rotationValue, originalWidth, originalHeight, bitrate, resultWidth, resultHeight, originalPath);
|
||||
}
|
||||
|
||||
public boolean parseString(String string) {
|
||||
if (string.length() < 6) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
String args[] = string.split("_");
|
||||
if (args.length >= 10) {
|
||||
startTime = Long.parseLong(args[1]);
|
||||
endTime = Long.parseLong(args[2]);
|
||||
rotationValue = Integer.parseInt(args[3]);
|
||||
originalWidth = Integer.parseInt(args[4]);
|
||||
originalHeight = Integer.parseInt(args[5]);
|
||||
bitrate = Integer.parseInt(args[6]);
|
||||
resultWidth = Integer.parseInt(args[7]);
|
||||
resultHeight = Integer.parseInt(args[8]);
|
||||
for (int a = 9; a < args.length; a++) {
|
||||
if (originalPath == null) {
|
||||
originalPath = args[a];
|
||||
} else {
|
||||
originalPath += "_" + args[a];
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
FileLog.e("messenger", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,80 +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;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.app.NotificationManagerCompat;
|
||||
|
||||
public class VideoEncodingService extends Service implements NotificationCenter.NotificationCenterDelegate {
|
||||
|
||||
private NotificationCompat.Builder builder = null;
|
||||
private String path = null;
|
||||
private int currentProgress = 0;
|
||||
|
||||
public VideoEncodingService() {
|
||||
super();
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileUploadProgressChanged);
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.stopEncodingService);
|
||||
}
|
||||
|
||||
public IBinder onBind(Intent arg2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void onDestroy() {
|
||||
stopForeground(true);
|
||||
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.FileUploadProgressChanged);
|
||||
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.stopEncodingService);
|
||||
FileLog.e("messenger", "destroy video service");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void didReceivedNotification(int id, Object... args) {
|
||||
if (id == NotificationCenter.FileUploadProgressChanged) {
|
||||
String fileName = (String)args[0];
|
||||
if (path != null && path.equals(fileName)) {
|
||||
Float progress = (Float) args[1];
|
||||
Boolean enc = (Boolean) args[2];
|
||||
currentProgress = (int)(progress * 100);
|
||||
builder.setProgress(100, currentProgress, currentProgress == 0);
|
||||
NotificationManagerCompat.from(ApplicationLoader.applicationContext).notify(4, builder.build());
|
||||
}
|
||||
} else if (id == NotificationCenter.stopEncodingService) {
|
||||
String filepath = (String)args[0];
|
||||
if (filepath == null || filepath.equals(path)) {
|
||||
stopSelf();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
path = intent.getStringExtra("path");
|
||||
if (path == null) {
|
||||
stopSelf();
|
||||
return Service.START_NOT_STICKY;
|
||||
}
|
||||
FileLog.e("messenger", "start video service");
|
||||
if (builder == null) {
|
||||
builder = new NotificationCompat.Builder(ApplicationLoader.applicationContext);
|
||||
builder.setSmallIcon(android.R.drawable.stat_sys_upload);
|
||||
builder.setWhen(System.currentTimeMillis());
|
||||
builder.setContentTitle(LocaleController.getString("AppName", R.string.AppName));
|
||||
builder.setTicker(LocaleController.getString("SendingVideo", R.string.SendingVideo));
|
||||
builder.setContentText(LocaleController.getString("SendingVideo", R.string.SendingVideo));
|
||||
}
|
||||
currentProgress = 0;
|
||||
builder.setProgress(100, currentProgress, currentProgress == 0);
|
||||
startForeground(4, builder.build());
|
||||
NotificationManagerCompat.from(ApplicationLoader.applicationContext).notify(4, builder.build());
|
||||
return Service.START_NOT_STICKY;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
-3040
File diff suppressed because it is too large
Load Diff
-59
@@ -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;
|
||||
|
||||
|
||||
-107
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011 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.volley.toolbox;
|
||||
|
||||
import com.b44t.messenger.volley.AuthFailureError;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.accounts.AccountManagerFuture;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
/**
|
||||
* An Authenticator that uses {@link AccountManager} to get auth
|
||||
* tokens of a specified type for a specified account.
|
||||
*/
|
||||
public class AndroidAuthenticator implements Authenticator {
|
||||
private final AccountManager mAccountManager;
|
||||
private final Account mAccount;
|
||||
private final String mAuthTokenType;
|
||||
private final boolean mNotifyAuthFailure;
|
||||
|
||||
/**
|
||||
* Creates a new authenticator.
|
||||
* @param context Context for accessing AccountManager
|
||||
* @param account Account to authenticate as
|
||||
* @param authTokenType Auth token type passed to AccountManager
|
||||
*/
|
||||
public AndroidAuthenticator(Context context, Account account, String authTokenType) {
|
||||
this(context, account, authTokenType, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new authenticator.
|
||||
* @param context Context for accessing AccountManager
|
||||
* @param account Account to authenticate as
|
||||
* @param authTokenType Auth token type passed to AccountManager
|
||||
* @param notifyAuthFailure Whether to raise a notification upon auth failure
|
||||
*/
|
||||
public AndroidAuthenticator(Context context, Account account, String authTokenType,
|
||||
boolean notifyAuthFailure) {
|
||||
this(AccountManager.get(context), account, authTokenType, notifyAuthFailure);
|
||||
}
|
||||
|
||||
// Visible for testing. Allows injection of a mock AccountManager.
|
||||
AndroidAuthenticator(AccountManager accountManager, Account account,
|
||||
String authTokenType, boolean notifyAuthFailure) {
|
||||
mAccountManager = accountManager;
|
||||
mAccount = account;
|
||||
mAuthTokenType = authTokenType;
|
||||
mNotifyAuthFailure = notifyAuthFailure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Account being used by this authenticator.
|
||||
*/
|
||||
public Account getAccount() {
|
||||
return mAccount;
|
||||
}
|
||||
|
||||
// TODO: Figure out what to do about notifyAuthFailure
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public String getAuthToken() throws AuthFailureError {
|
||||
AccountManagerFuture<Bundle> future = mAccountManager.getAuthToken(mAccount,
|
||||
mAuthTokenType, mNotifyAuthFailure, null, null);
|
||||
Bundle result;
|
||||
try {
|
||||
result = future.getResult();
|
||||
} catch (Exception e) {
|
||||
throw new AuthFailureError("Error while retrieving auth token", e);
|
||||
}
|
||||
String authToken = null;
|
||||
if (future.isDone() && !future.isCancelled()) {
|
||||
if (result.containsKey(AccountManager.KEY_INTENT)) {
|
||||
Intent intent = result.getParcelable(AccountManager.KEY_INTENT);
|
||||
throw new AuthFailureError(intent);
|
||||
}
|
||||
authToken = result.getString(AccountManager.KEY_AUTHTOKEN);
|
||||
}
|
||||
if (authToken == null) {
|
||||
throw new AuthFailureError("Got null auth token for type: " + mAuthTokenType);
|
||||
}
|
||||
|
||||
return authToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateAuthToken(String authToken) {
|
||||
mAccountManager.invalidateAuthToken(mAccount.type, authToken);
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011 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.volley.toolbox;
|
||||
|
||||
import com.b44t.messenger.volley.AuthFailureError;
|
||||
|
||||
/**
|
||||
* An interface for interacting with auth tokens.
|
||||
*/
|
||||
public interface Authenticator {
|
||||
/**
|
||||
* Synchronously retrieves an auth token.
|
||||
*
|
||||
* @throws AuthFailureError If authentication did not succeed
|
||||
*/
|
||||
public String getAuthToken() throws AuthFailureError;
|
||||
|
||||
/**
|
||||
* Invalidates the provided auth token.
|
||||
*/
|
||||
public void invalidateAuthToken(String authToken);
|
||||
}
|
||||
@@ -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
|
||||
*
|
||||
******************************************************************************/
|
||||
@@ -38,71 +37,85 @@ import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ListView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.b44t.messenger.AndroidUtilities;
|
||||
import com.b44t.messenger.ContactsController;
|
||||
import com.b44t.messenger.ApplicationLoader;
|
||||
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;
|
||||
import com.b44t.messenger.Utilities;
|
||||
import com.b44t.ui.ActionBar.ActionBar;
|
||||
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.Cells.TextInfoCell;
|
||||
import com.b44t.ui.Cells.TextSettingsCell;
|
||||
import com.b44t.ui.Components.LayoutHelper;
|
||||
|
||||
import static android.app.ProgressDialog.STYLE_HORIZONTAL;
|
||||
|
||||
|
||||
public class AccountSettingsActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate {
|
||||
|
||||
// the list
|
||||
private ListView listView;
|
||||
private ListAdapter listAdapter;
|
||||
|
||||
private int rowSectionBasic;
|
||||
private int rowAddrHeadline;
|
||||
private int rowAddr;
|
||||
private int rowMailPwHeadline;
|
||||
private int rowMailPw;
|
||||
private int rowInfoBelowMailPw2;
|
||||
private int rowOpenAdvOpions;
|
||||
|
||||
private int rowSectionMail;
|
||||
private int rowMailHeadline;
|
||||
private int rowMailServer;
|
||||
private int rowMailPort;
|
||||
private int rowMailUser;
|
||||
private int rowBreak2;
|
||||
private int rowMailSecurity;
|
||||
private int rowBreak1;
|
||||
|
||||
private int rowSectionSend;
|
||||
private int rowSendHeadline;
|
||||
private int rowSendServer;
|
||||
private int rowSendPort;
|
||||
private int rowSendUser;
|
||||
private int rowSendPw;
|
||||
private int rowSendSecurity;
|
||||
|
||||
private int rowInfoBelowSendPw;
|
||||
private int rowCount;
|
||||
|
||||
private final int typeInfo = 0; // no gaps here!
|
||||
private final int typeTextEntry = 1;
|
||||
private final int typeShadowSection = 2;
|
||||
private final int typeSection = 3;
|
||||
private final int ROWTYPE_INFO = 0; // no gaps here!
|
||||
private final int ROWTYPE_TEXT_ENTRY = 1;
|
||||
private final int ROWTYPE_SHADOW_BREAK = 2;
|
||||
private final int ROWTYPE_HEADLINE = 3;
|
||||
private final int ROWTYPE_TEXT_FLAGS = 4;
|
||||
|
||||
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;
|
||||
private EditTextCell addrCell; // warning all these objects may be null!
|
||||
private EditTextCell mailPwCell;
|
||||
private EditTextCell mailServerCell;
|
||||
private EditTextCell mailPortCell;
|
||||
private EditTextCell mailUserCell;
|
||||
private EditTextCell sendPwCell;
|
||||
private EditTextCell sendServerCell;
|
||||
private EditTextCell sendPortCell;
|
||||
private EditTextCell sendUserCell;
|
||||
|
||||
private final int MR_IMAP_SOCKET_STARTTLS = 0x100;
|
||||
private final int MR_IMAP_SOCKET_SSL = 0x200;
|
||||
private final int MR_IMAP_SOCKET_PLAIN = 0x400;
|
||||
private final int MR_SMTP_SOCKET_STARTTLS = 0x10000;
|
||||
private final int MR_SMTP_SOCKET_SSL = 0x20000;
|
||||
private final int MR_SMTP_SOCKET_PLAIN = 0x40000;
|
||||
private int m_serverFlags;
|
||||
|
||||
// misc.
|
||||
private View doneButton;
|
||||
private final static int done_button = 1;
|
||||
private final int ID_DONE_BUTTON = 1;
|
||||
private ProgressDialog progressDialog = null;
|
||||
boolean fromIntro;
|
||||
private boolean fromIntro;
|
||||
private boolean m_expanded = false;
|
||||
|
||||
public AccountSettingsActivity(Bundle args) {
|
||||
super();
|
||||
@@ -115,34 +128,77 @@ public class AccountSettingsActivity extends BaseFragment implements Notificatio
|
||||
public boolean onFragmentCreate() {
|
||||
super.onFragmentCreate();
|
||||
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.connectionStateChanged);
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.configureEnded);
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.configureProgress);
|
||||
|
||||
rowCount = 0;
|
||||
rowSectionBasic = rowCount++;
|
||||
rowAddr = rowCount++;
|
||||
rowMailPw = rowCount++;
|
||||
rowInfoBelowMailPw2 = rowCount++;
|
||||
m_serverFlags = MrMailbox.getConfigInt("server_flags", 0);
|
||||
|
||||
rowSectionMail = rowCount++;
|
||||
rowMailServer = rowCount++;
|
||||
rowMailUser = rowCount++;
|
||||
rowMailPort = rowCount++;
|
||||
rowBreak2 = rowCount++;
|
||||
m_expanded = false;
|
||||
if( !MrMailbox.getConfig("mail_user", "").isEmpty()
|
||||
|| !MrMailbox.getConfig("mail_server", "").isEmpty()
|
||||
|| !MrMailbox.getConfig("mail_port", "").isEmpty()
|
||||
|| !MrMailbox.getConfig("send_user", "").isEmpty()
|
||||
|| !MrMailbox.getConfig("send_pw", "").isEmpty()
|
||||
|| !MrMailbox.getConfig("send_server", "").isEmpty()
|
||||
|| !MrMailbox.getConfig("send_port", "").isEmpty()
|
||||
|| (m_serverFlags!=0) ) {
|
||||
m_expanded = true;
|
||||
}
|
||||
|
||||
rowSectionSend = rowCount++;
|
||||
rowSendServer = rowCount++;
|
||||
rowSendUser = rowCount++;
|
||||
rowSendPw = rowCount++;
|
||||
rowSendPort = rowCount++;
|
||||
rowInfoBelowSendPw = rowCount++;
|
||||
calculateRows();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void calculateRows()
|
||||
{
|
||||
rowCount = 0;
|
||||
|
||||
rowAddrHeadline = rowCount++;
|
||||
rowAddr = rowCount++;
|
||||
rowMailPwHeadline= rowCount++;
|
||||
rowMailPw = rowCount++;
|
||||
rowOpenAdvOpions = rowCount++;
|
||||
|
||||
if( m_expanded ) {
|
||||
rowMailHeadline = rowCount++;
|
||||
rowMailUser = rowCount++; // should be the first additional option, the loginname is the component, that cannot be configured automatically (if not derivable from the address)
|
||||
rowMailServer = rowCount++;
|
||||
rowMailPort = rowCount++;
|
||||
rowMailSecurity = rowCount++;
|
||||
rowBreak1 = rowCount++;
|
||||
|
||||
rowSendHeadline = rowCount++;
|
||||
rowSendUser = rowCount++;
|
||||
rowSendPw = rowCount++;
|
||||
rowSendServer = rowCount++;
|
||||
rowSendPort = rowCount++;
|
||||
rowSendSecurity = rowCount++;
|
||||
}
|
||||
else {
|
||||
rowMailHeadline = -1;
|
||||
rowMailUser = -1;
|
||||
rowMailServer = -1;
|
||||
rowMailPort = -1;
|
||||
rowMailSecurity = -1;
|
||||
rowBreak1 = -1;
|
||||
|
||||
rowSendHeadline = -1;
|
||||
rowSendUser = -1;
|
||||
rowSendPw = -1;
|
||||
rowSendServer = -1;
|
||||
rowSendPort = -1;
|
||||
rowSendSecurity = -1;
|
||||
}
|
||||
|
||||
rowInfoBelowSendPw = rowCount++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFragmentDestroy() {
|
||||
super.onFragmentDestroy();
|
||||
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.connectionStateChanged);
|
||||
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.configureEnded);
|
||||
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.configureProgress);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -150,7 +206,7 @@ public class AccountSettingsActivity extends BaseFragment implements Notificatio
|
||||
|
||||
// create action bar
|
||||
if( !fromIntro ) {
|
||||
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
|
||||
actionBar.setBackButtonImage(R.drawable.ic_close_white);
|
||||
}
|
||||
|
||||
actionBar.setAllowOverlayTitle(true);
|
||||
@@ -158,30 +214,16 @@ public class AccountSettingsActivity extends BaseFragment implements Notificatio
|
||||
actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() {
|
||||
@Override
|
||||
public void onItemClick(int id) {
|
||||
if (id == -1 && !fromIntro ) {
|
||||
if( isModified() ) { // TODO: maybe we should also ask if the user presses the "back" button
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity());
|
||||
builder.setMessage(LocaleController.getString("DiscardChanges", R.string.DiscardChanges));
|
||||
builder.setPositiveButton(LocaleController.getString("Yes", R.string.Yes), new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
finishFragment();
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(LocaleController.getString("No", R.string.No), null);
|
||||
showDialog(builder.create());
|
||||
}
|
||||
else {
|
||||
finishFragment();
|
||||
}
|
||||
} else if (id == done_button) {
|
||||
if (id == -1 && !fromIntro ) { // no "is modified" check: as we use "close/ok" buttons instead of a "back" button it is more clear what happens. moreover, the user may have done a failed "OK" in between, so a question "discard changes?" would be ambiguously
|
||||
finishFragment();
|
||||
} else if (id == ID_DONE_BUTTON) {
|
||||
saveData();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ActionBarMenu menu = actionBar.createMenu();
|
||||
doneButton = menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56));
|
||||
menu.addItemWithWidth(ID_DONE_BUTTON, R.drawable.ic_done, AndroidUtilities.dp(56));
|
||||
|
||||
// create object to hold the whole view
|
||||
fragmentView = new FrameLayout(context);
|
||||
@@ -191,7 +233,7 @@ public class AccountSettingsActivity extends BaseFragment implements Notificatio
|
||||
// create the main layout list
|
||||
listAdapter = new ListAdapter(context);
|
||||
|
||||
ListView listView = new ListView(context);
|
||||
listView = new ListView(context);
|
||||
listView.setDivider(null);
|
||||
listView.setDividerHeight(0);
|
||||
listView.setVerticalScrollBarEnabled(false);
|
||||
@@ -201,6 +243,47 @@ public class AccountSettingsActivity extends BaseFragment implements Notificatio
|
||||
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(final AdapterView<?> adapterView, View view, final int i, long l) {
|
||||
if( i==rowOpenAdvOpions )
|
||||
{
|
||||
m_expanded = !m_expanded;
|
||||
calculateRows();
|
||||
listAdapter.notifyDataSetChanged();
|
||||
}
|
||||
else if( i==rowMailSecurity || i==rowSendSecurity )
|
||||
{
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity());
|
||||
builder.setTitle(ApplicationLoader.applicationContext.getString(R.string.SecurityTitle));
|
||||
builder.setItems(new CharSequence[]{
|
||||
ApplicationLoader.applicationContext.getString(R.string.Automatic),
|
||||
"SSL/TLS", /*1*/
|
||||
"STARTTLS", /*2*/
|
||||
ApplicationLoader.applicationContext.getString(R.string.Disabled) /*3*/
|
||||
}, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if( i==rowMailSecurity ) {
|
||||
m_serverFlags &= ~(MR_IMAP_SOCKET_SSL | MR_IMAP_SOCKET_STARTTLS | MR_IMAP_SOCKET_PLAIN);
|
||||
switch( which ) {
|
||||
case 1: m_serverFlags |= MR_IMAP_SOCKET_SSL; break;
|
||||
case 2: m_serverFlags |= MR_IMAP_SOCKET_STARTTLS; break;
|
||||
case 3: m_serverFlags |= MR_IMAP_SOCKET_PLAIN; break;
|
||||
}
|
||||
}
|
||||
else if( i==rowSendSecurity ) {
|
||||
m_serverFlags &= ~(MR_SMTP_SOCKET_SSL | MR_SMTP_SOCKET_STARTTLS | MR_SMTP_SOCKET_PLAIN);
|
||||
switch( which ) {
|
||||
case 1: m_serverFlags |= MR_SMTP_SOCKET_SSL; break;
|
||||
case 2: m_serverFlags |= MR_SMTP_SOCKET_STARTTLS; break;
|
||||
case 3: m_serverFlags |= MR_SMTP_SOCKET_PLAIN; break;
|
||||
}
|
||||
}
|
||||
listView.invalidateViews();
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
|
||||
showDialog(builder.create());
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -211,13 +294,6 @@ public class AccountSettingsActivity extends BaseFragment implements Notificatio
|
||||
// Warning: the widgets are created as needed and may not be present!
|
||||
String v;
|
||||
|
||||
/*
|
||||
if( !isModified() && MrMailbox.MrMailboxIsConfigured(MrMailbox.hMailbox)!=0 ) {
|
||||
finishFragment();
|
||||
return; // nothing to do
|
||||
}
|
||||
*/
|
||||
|
||||
if( addrCell!=null) {
|
||||
v = addrCell.getValue().trim();
|
||||
MrMailbox.setConfig("addr", v.isEmpty() ? null : v);
|
||||
@@ -263,6 +339,8 @@ public class AccountSettingsActivity extends BaseFragment implements Notificatio
|
||||
MrMailbox.setConfig("send_pw", v.isEmpty() ? null : v);
|
||||
}
|
||||
|
||||
MrMailbox.setConfigInt("server_flags", m_serverFlags);
|
||||
|
||||
// show dialog
|
||||
if( progressDialog!=null ) {
|
||||
progressDialog.dismiss();
|
||||
@@ -270,70 +348,77 @@ public class AccountSettingsActivity extends BaseFragment implements Notificatio
|
||||
}
|
||||
|
||||
progressDialog = new ProgressDialog(getParentActivity());
|
||||
progressDialog.setMessage(LocaleController.getString("ConfiguringAccount", R.string.ConfiguringAccount));
|
||||
progressDialog.setMessage(ApplicationLoader.applicationContext.getString(R.string.OneMoment));
|
||||
progressDialog.setCanceledOnTouchOutside(false);
|
||||
progressDialog.setCancelable(false);
|
||||
progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, LocaleController.getString("Cancel", R.string.Cancel), new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
progressDialog = null;
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
MrMailbox.configureCancel();
|
||||
}
|
||||
});
|
||||
progressDialog.show();
|
||||
|
||||
// try to connect
|
||||
// (for the future, we may put all this togehter in a single command, that is executed
|
||||
// asynchronously by the backend; then we can skip creating a runnable here)
|
||||
Utilities.searchQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
MrMailbox.disconnect();
|
||||
MrMailbox.configure();
|
||||
MrMailbox.connect();
|
||||
}
|
||||
});
|
||||
synchronized (MrMailbox.m_lastErrorLock) {
|
||||
MrMailbox.m_showNextErrorAsToast = false;
|
||||
MrMailbox.m_lastErrorString = "";
|
||||
}
|
||||
|
||||
// try to connect, this results in an MR_EVENT_CONFIGURE_ENDED resp. NotificationCenter.configureEnded event
|
||||
MrMailbox.configureAndConnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void didReceivedNotification(int id, Object... args) {
|
||||
if (id == NotificationCenter.connectionStateChanged ) {
|
||||
if( id == NotificationCenter.configureProgress )
|
||||
{
|
||||
if( progressDialog!=null ) {
|
||||
// we want the spinner together with a progress info
|
||||
int percent = (Integer)args[0];
|
||||
progressDialog.setMessage(ApplicationLoader.applicationContext.getString(R.string.OneMoment)+String.format(" %d%%", percent));
|
||||
}
|
||||
}
|
||||
else if (id == NotificationCenter.configureEnded )
|
||||
{
|
||||
final String errorString;
|
||||
|
||||
synchronized (MrMailbox.m_lastErrorLock) {
|
||||
MrMailbox.m_showNextErrorAsToast = true;
|
||||
errorString = MrMailbox.m_lastErrorString;
|
||||
}
|
||||
|
||||
if( progressDialog!=null ) {
|
||||
progressDialog.dismiss();
|
||||
progressDialog = null;
|
||||
}
|
||||
|
||||
if( (int)args[0]==1 ) {
|
||||
if( fromIntro ) {
|
||||
if (fromIntro) {
|
||||
presentFragment(new DialogsActivity(null), true);
|
||||
((LaunchActivity)getParentActivity()).drawerLayoutContainer.setAllowOpenDrawer(true, false);
|
||||
}
|
||||
else {
|
||||
LaunchActivity la = ((LaunchActivity) getParentActivity());
|
||||
if (la != null) {
|
||||
la.drawerLayoutContainer.setAllowOpenDrawer(true, false);
|
||||
}
|
||||
} else {
|
||||
finishFragment();
|
||||
}
|
||||
AndroidUtilities.showDoneHint(ApplicationLoader.applicationContext);
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.mainUserInfoChanged);
|
||||
}
|
||||
else {
|
||||
Toast.makeText(getParentActivity(), LocaleController.getString("CannotConnect", R.string.CannotConnect), Toast.LENGTH_LONG).show();
|
||||
else if( ! MrMailbox.m_lastErrorString.isEmpty() ){
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity());
|
||||
builder.setMessage(errorString);
|
||||
builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
;
|
||||
}
|
||||
});
|
||||
showDialog(builder.create());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isModified(){
|
||||
// Warning: the widgets are created as needed and may not be present!
|
||||
if( addrCell!=null && addrCell.isModified()) { return true; }
|
||||
if( mailPwCell!=null && mailPwCell.isModified()) { return true; }
|
||||
|
||||
if( mailServerCell!=null && mailServerCell.isModified()) { return true; }
|
||||
if( mailPortCell!=null && mailPortCell.isModified()) { return true; }
|
||||
if( mailUserCell!=null && mailUserCell.isModified()) { return true; }
|
||||
|
||||
if( sendServerCell!=null && sendServerCell.isModified()) { return true; }
|
||||
if( sendPortCell!=null && sendPortCell.isModified()) { return true; }
|
||||
if( sendUserCell!=null && sendUserCell.isModified()) { return true; }
|
||||
if( sendPwCell!=null && sendPwCell.isModified()) { return true; }
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransitionAnimationEnd(boolean isOpen, boolean backward) {
|
||||
if (isOpen && addrCell!=null) {
|
||||
@@ -358,8 +443,7 @@ public class AccountSettingsActivity extends BaseFragment implements Notificatio
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int i) {
|
||||
return (i == rowAddr || i==rowMailPw || i==rowMailServer || i==rowMailPort|| i==rowMailUser
|
||||
|| i==rowSendServer || i==rowSendPort || i==rowSendUser || i== rowSendPw);
|
||||
return !(i==rowAddrHeadline || i==rowMailPwHeadline || i== rowMailHeadline || i== rowBreak1 || i== rowSendHeadline || i==rowInfoBelowSendPw);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -385,76 +469,80 @@ public class AccountSettingsActivity extends BaseFragment implements Notificatio
|
||||
@Override
|
||||
public View getView(int i, View view, ViewGroup viewGroup) {
|
||||
int type = getItemViewType__(i);
|
||||
if (type == typeTextEntry) {
|
||||
if (type == ROWTYPE_TEXT_ENTRY) {
|
||||
if (i == rowAddr) {
|
||||
if( addrCell==null) {
|
||||
addrCell = new MrEditTextCell(mContext);
|
||||
addrCell = new EditTextCell(mContext, false);
|
||||
addrCell.setValueHintAndLabel(MrMailbox.getConfig("addr", ""),
|
||||
"", LocaleController.getString("MyEmailAddress", R.string.MyEmailAddress), false);
|
||||
"", "", false);
|
||||
addrCell.getEditTextView().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
|
||||
}
|
||||
view = addrCell;
|
||||
}
|
||||
else if (i == rowMailPw) {
|
||||
if( mailPwCell==null) {
|
||||
mailPwCell = new MrEditTextCell(mContext);
|
||||
mailPwCell = new EditTextCell(mContext, false);
|
||||
mailPwCell.setValueHintAndLabel(MrMailbox.getConfig("mail_pw", ""),
|
||||
"", LocaleController.getString("Password", R.string.Password), false);
|
||||
"", "", false);
|
||||
mailPwCell.getEditTextView().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
||||
}
|
||||
view = mailPwCell;
|
||||
}
|
||||
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);
|
||||
ApplicationLoader.applicationContext.getString(R.string.Automatic), LocaleController.getString("ImapServer", R.string.ImapServer), false);
|
||||
mailServerCell.getEditTextView().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI);
|
||||
}
|
||||
view = mailServerCell;
|
||||
}
|
||||
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);
|
||||
ApplicationLoader.applicationContext.getString(R.string.Automatic), LocaleController.getString("ImapPort", R.string.ImapPort), false);
|
||||
mailPortCell.getEditTextView().setInputType(InputType.TYPE_CLASS_NUMBER);
|
||||
}
|
||||
view = mailPortCell;
|
||||
}
|
||||
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);
|
||||
ApplicationLoader.applicationContext.getString(R.string.Automatic), LocaleController.getString("ImapLoginname", R.string.ImapLoginname), false);
|
||||
}
|
||||
view = mailUserCell;
|
||||
}
|
||||
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);
|
||||
ApplicationLoader.applicationContext.getString(R.string.Automatic), LocaleController.getString("SmtpServer", R.string.SmtpServer), false);
|
||||
sendServerCell.getEditTextView().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI);
|
||||
}
|
||||
view = sendServerCell;
|
||||
}
|
||||
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);
|
||||
ApplicationLoader.applicationContext.getString(R.string.Automatic), LocaleController.getString("SmtpPort", R.string.SmtpPort), false);
|
||||
sendPortCell.getEditTextView().setInputType(InputType.TYPE_CLASS_NUMBER);
|
||||
}
|
||||
view = sendPortCell;
|
||||
}
|
||||
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);
|
||||
ApplicationLoader.applicationContext.getString(R.string.Automatic), LocaleController.getString("SmtpLoginname", R.string.SmtpLoginname), false);
|
||||
}
|
||||
view = sendUserCell;
|
||||
}
|
||||
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);
|
||||
@@ -462,35 +550,59 @@ public class AccountSettingsActivity extends BaseFragment implements Notificatio
|
||||
view = sendPwCell;
|
||||
}
|
||||
}
|
||||
else if (type == typeSection) {
|
||||
else if (type ==ROWTYPE_TEXT_FLAGS) {
|
||||
if (view == null) {
|
||||
view = new TextSettingsCell(mContext);
|
||||
view.setBackgroundColor(0xffffffff);
|
||||
}
|
||||
TextSettingsCell textCell = (TextSettingsCell) view;
|
||||
String value = ApplicationLoader.applicationContext.getString(R.string.Automatic);
|
||||
if( i == rowMailSecurity ) {
|
||||
if( (m_serverFlags&MR_IMAP_SOCKET_SSL)!=0 ) { value = "SSL/TLS"; }
|
||||
if( (m_serverFlags&MR_IMAP_SOCKET_STARTTLS)!=0 ) { value = "STARTTLS"; }
|
||||
if( (m_serverFlags&MR_IMAP_SOCKET_PLAIN)!=0 ) { value = ApplicationLoader.applicationContext.getString(R.string.Disabled); }
|
||||
}
|
||||
else if( i == rowSendSecurity ) {
|
||||
if( (m_serverFlags&MR_SMTP_SOCKET_SSL)!=0 ) { value = "SSL/TLS"; }
|
||||
if( (m_serverFlags&MR_SMTP_SOCKET_STARTTLS)!=0 ) { value = "STARTTLS"; }
|
||||
if( (m_serverFlags&MR_SMTP_SOCKET_PLAIN)!=0 ) { value = ApplicationLoader.applicationContext.getString(R.string.Disabled); }
|
||||
}
|
||||
textCell.setTextAndValue(ApplicationLoader.applicationContext.getString(R.string.SecurityTitle), value, false);
|
||||
}
|
||||
else if (type == ROWTYPE_HEADLINE) {
|
||||
if (view == null) {
|
||||
view = new HeaderCell(mContext);
|
||||
view.setBackgroundColor(0xffffffff);
|
||||
}
|
||||
if (i == rowSectionBasic) {
|
||||
((HeaderCell) view).setText(LocaleController.getString("BasicSettings", R.string.BasicSettings));
|
||||
} else if (i == rowSectionMail) {
|
||||
if (i == rowAddrHeadline) {
|
||||
((HeaderCell) view).setText(ApplicationLoader.applicationContext.getString(R.string.EmailAddress));
|
||||
} else if (i == rowMailPwHeadline) {
|
||||
((HeaderCell) view).setText(ApplicationLoader.applicationContext.getString(R.string.Password));
|
||||
} else if (i == rowMailHeadline) {
|
||||
((HeaderCell) view).setText(LocaleController.getString("InboxHeadline", R.string.InboxHeadline));
|
||||
} else if (i == rowSectionSend) {
|
||||
} else if (i == rowSendHeadline) {
|
||||
((HeaderCell) view).setText(LocaleController.getString("OutboxHeadline", R.string.OutboxHeadline));
|
||||
}
|
||||
}
|
||||
else if (type == typeShadowSection) {
|
||||
else if (type == ROWTYPE_SHADOW_BREAK) {
|
||||
if (view == null) {
|
||||
view = new ShadowSectionCell(mContext);
|
||||
}
|
||||
}
|
||||
else if (type == typeInfo) {
|
||||
else if (type == ROWTYPE_INFO) {
|
||||
if (view == null) {
|
||||
view = new TextInfoPrivacyCell(mContext);
|
||||
view = new TextInfoCell(mContext);
|
||||
}
|
||||
if( i==rowInfoBelowMailPw2) {
|
||||
((TextInfoPrivacyCell) view).setText(LocaleController.getString("MyAccoutExplain", R.string.MyAccountExplain)+"\n");
|
||||
view.setBackgroundResource(R.drawable.greydivider); // has shadow top+bottom
|
||||
if( i== rowOpenAdvOpions) {
|
||||
((TextInfoCell) view).setText(LocaleController.getString("MyAccoutExplain", R.string.MyAccountExplain),
|
||||
m_expanded? " \u2212" /*minus-sign*/ : "+", m_expanded /*draw bottom border?*/);
|
||||
view.setBackgroundResource(m_expanded? R.drawable.greydivider : R.drawable.greydivider_bottom); // has shadow top+bottom
|
||||
}
|
||||
else if( i==rowInfoBelowSendPw) {
|
||||
((TextInfoPrivacyCell) view).setText(LocaleController.getString("MyAccountExplain2", R.string.MyAccountExplain2));
|
||||
view.setBackgroundResource(R.drawable.greydivider_bottom);
|
||||
((TextInfoCell) view).setText(AndroidUtilities.replaceTags(LocaleController.getString("MyAccountExplain2", R.string.MyAccountExplain2)));
|
||||
if( m_expanded ) {
|
||||
view.setBackgroundResource(R.drawable.greydivider_bottom);
|
||||
}
|
||||
}
|
||||
}
|
||||
return view;
|
||||
@@ -504,15 +616,18 @@ public class AccountSettingsActivity extends BaseFragment implements Notificatio
|
||||
private int getItemViewType__(int i) {
|
||||
if (i == rowAddr || i==rowMailPw || i==rowMailServer || i==rowMailPort|| i==rowMailUser
|
||||
|| i==rowSendServer || i==rowSendPort || i==rowSendUser || i== rowSendPw ) {
|
||||
return typeTextEntry;
|
||||
return ROWTYPE_TEXT_ENTRY;
|
||||
}
|
||||
else if( i==rowSectionBasic || i==rowSectionMail || i==rowSectionSend ) {
|
||||
return typeSection;
|
||||
else if( i==rowAddrHeadline || i==rowMailPwHeadline || i== rowMailHeadline || i== rowSendHeadline ) {
|
||||
return ROWTYPE_HEADLINE;
|
||||
}
|
||||
else if( i== rowBreak2) {
|
||||
return typeShadowSection;
|
||||
else if( i== rowBreak1 ) {
|
||||
return ROWTYPE_SHADOW_BREAK;
|
||||
}
|
||||
return typeInfo;
|
||||
else if( i==rowMailSecurity || i==rowSendSecurity) {
|
||||
return ROWTYPE_TEXT_FLAGS;
|
||||
}
|
||||
return ROWTYPE_INFO;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -13,6 +28,7 @@ import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.view.Gravity;
|
||||
@@ -43,14 +59,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;
|
||||
@@ -146,7 +161,6 @@ public class ActionBar extends FrameLayout {
|
||||
titleTextView = new SimpleTextView(getContext());
|
||||
titleTextView.setGravity(Gravity.LEFT);
|
||||
titleTextView.setTextColor(0xffffffff);
|
||||
titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
||||
addView(titleTextView, 0, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -640,7 +655,7 @@ public class ActionBarLayout extends FrameLayout {
|
||||
if (parentActivity.getCurrentFocus() != null) {
|
||||
AndroidUtilities.hideKeyboard(parentActivity.getCurrentFocus());
|
||||
}
|
||||
boolean needAnimation = !forceWithoutAnimation && parentActivity.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE).getBoolean("view_animations", true);
|
||||
boolean needAnimation = !forceWithoutAnimation && parentActivity.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE).getBoolean("view_animations2", true);
|
||||
|
||||
final BaseFragment currentFragment = !fragmentsStack.isEmpty() ? fragmentsStack.get(fragmentsStack.size() - 1) : null;
|
||||
|
||||
@@ -848,7 +863,7 @@ public class ActionBarLayout extends FrameLayout {
|
||||
AndroidUtilities.hideKeyboard(parentActivity.getCurrentFocus());
|
||||
}
|
||||
setInnerTranslationX(0);
|
||||
boolean needAnimation = animated && parentActivity.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE).getBoolean("view_animations", true);
|
||||
boolean needAnimation = animated && parentActivity.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE).getBoolean("view_animations2", true);
|
||||
final BaseFragment currentFragment = fragmentsStack.get(fragmentsStack.size() - 1);
|
||||
BaseFragment previousFragment = null;
|
||||
if (fragmentsStack.size() > 1) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user