mirror of
https://github.com/oxen-io/session-android.git
synced 2025-04-16 22:11:26 +00:00
Update to glide 4.x
// FREEBIE
This commit is contained in:
parent
17dd681dc8
commit
10f224ede5
@ -105,9 +105,6 @@
|
|||||||
<meta-data android:name="com.google.android.gms.version"
|
<meta-data android:name="com.google.android.gms.version"
|
||||||
android:value="@integer/google_play_services_version" />
|
android:value="@integer/google_play_services_version" />
|
||||||
|
|
||||||
<meta-data android:name="org.thoughtcrime.securesms.mms.TextSecureGlideModule"
|
|
||||||
android:value="GlideModule" />
|
|
||||||
|
|
||||||
<meta-data android:name="com.google.android.gms.car.application"
|
<meta-data android:name="com.google.android.gms.car.application"
|
||||||
android:resource="@xml/automotive_app_desc" />
|
android:resource="@xml/automotive_app_desc" />
|
||||||
|
|
||||||
|
69
build.gradle
69
build.gradle
@ -45,14 +45,14 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile 'com.android.support:appcompat-v7:25.4.0'
|
compile 'com.android.support:appcompat-v7:26.1.0'
|
||||||
compile 'com.android.support:recyclerview-v7:25.4.0'
|
compile 'com.android.support:recyclerview-v7:26.1.0'
|
||||||
compile 'com.android.support:design:25.4.0'
|
compile 'com.android.support:design:26.1.0'
|
||||||
compile 'com.android.support:support-v13:25.4.0'
|
compile 'com.android.support:support-v13:26.1.0'
|
||||||
compile 'com.android.support:cardview-v7:25.4.0'
|
compile 'com.android.support:cardview-v7:26.1.0'
|
||||||
compile 'com.android.support:preference-v7:25.4.0'
|
compile 'com.android.support:preference-v7:26.1.0'
|
||||||
compile 'com.android.support:preference-v14:25.4.0'
|
compile 'com.android.support:preference-v14:26.1.0'
|
||||||
compile 'com.android.support:gridlayout-v7:25.4.0'
|
compile 'com.android.support:gridlayout-v7:26.1.0'
|
||||||
compile 'com.android.support:multidex:1.0.2'
|
compile 'com.android.support:multidex:1.0.2'
|
||||||
|
|
||||||
compile 'com.google.android.gms:play-services-gcm:9.6.1'
|
compile 'com.google.android.gms:play-services-gcm:9.6.1'
|
||||||
@ -70,8 +70,9 @@ dependencies {
|
|||||||
compile 'se.emilsjolander:stickylistheaders:2.7.0'
|
compile 'se.emilsjolander:stickylistheaders:2.7.0'
|
||||||
compile 'com.jpardogo.materialtabstrip:library:1.0.9'
|
compile 'com.jpardogo.materialtabstrip:library:1.0.9'
|
||||||
compile 'org.apache.httpcomponents:httpclient-android:4.3.5'
|
compile 'org.apache.httpcomponents:httpclient-android:4.3.5'
|
||||||
compile 'com.github.chrisbanes.photoview:library:1.3.1'
|
compile 'com.github.chrisbanes:PhotoView:2.1.3'
|
||||||
compile 'com.github.bumptech.glide:glide:3.7.0'
|
compile 'com.github.bumptech.glide:glide:4.2.0'
|
||||||
|
annotationProcessor 'com.github.bumptech.glide:compiler:4.2.0'
|
||||||
compile 'com.makeramen:roundedimageview:2.1.0'
|
compile 'com.makeramen:roundedimageview:2.1.0'
|
||||||
compile 'com.pnikosis:materialish-progress:1.5'
|
compile 'com.pnikosis:materialish-progress:1.5'
|
||||||
compile 'org.greenrobot:eventbus:3.0.0'
|
compile 'org.greenrobot:eventbus:3.0.0'
|
||||||
@ -131,14 +132,14 @@ dependencies {
|
|||||||
|
|
||||||
dependencyVerification {
|
dependencyVerification {
|
||||||
verify = [
|
verify = [
|
||||||
'com.android.support:appcompat-v7:70551e62660db15b790c5275f56b9de4dd9407d1494d07c8f3dd5698f3638677',
|
'com.android.support:appcompat-v7:9d44e7bf343dfd19a55e3e6f4c4e733b68d32509e0b0af5b32f2981f4f1dedd8',
|
||||||
'com.android.support:recyclerview-v7:a2fe121f9d01ed8980e97095b4a3fe9700a0aa0a7d4b0f8c594f765ad8455a0d',
|
'com.android.support:recyclerview-v7:389cb47a7dabca4fb8c23657ff7c85ebc651428580d3a5ea0349eeb43ddea94b',
|
||||||
'com.android.support:design:3f409bf2019967ffc344cfaf11e52131fac982468a1707aaeb25bf3c52838966',
|
'com.android.support:design:76f5fbb365bf2d622af5df8a4205904409250305685e38670bf654ac90c2494d',
|
||||||
'com.android.support:support-v13:f2dcf3eb3fe0271038dc78f6cff9cc3256a591f5c5198277b3887480e5b95e79',
|
'com.android.support:support-v13:fc7ba35b0502a6168b350342779c6943100ace19cd6dd573707bddfa8e9e78a2',
|
||||||
'com.android.support:cardview-v7:f3fbbe1fcfdbec7333c6a2c516c5fd511a909d1975271818e268d6fe297d8c70',
|
'com.android.support:cardview-v7:7ea56ed5560b629ee1c0f24af6693e32974fbc8b91b544052cd2c14b176c85e0',
|
||||||
'com.android.support:preference-v7:69bfa8e5527585dc51c02393b882c6b7e1e682995d5fbe45f57b7cb4e6970a7b',
|
'com.android.support:preference-v7:42672e51c06c6e26a40798d3379ede97ee42076c84592d670c4e5c96630c50f1',
|
||||||
'com.android.support:preference-v14:aac6e6cb89b70e27859d88cf75410a5feab1c7a9364d420de42ddb7c154a866b',
|
'com.android.support:preference-v14:f340c88589184fd53ad46aebbba1ae5b88b5919f92ed085bf0f687a58d0e0e17',
|
||||||
'com.android.support:gridlayout-v7:4c805b95e5b0a39c7244a0d1a14449cc54a9ab242b806f7379b38846f0539ce9',
|
'com.android.support:gridlayout-v7:6fe57dd164f2e1d99ad650a56f686ddecd02bfbfabbfbd451e81a23eada5e564',
|
||||||
'com.android.support:multidex:7cd48755c7cfdb6dd2d21cbb02236ec390f6ac91cde87eb62f475b259ab5301d',
|
'com.android.support:multidex:7cd48755c7cfdb6dd2d21cbb02236ec390f6ac91cde87eb62f475b259ab5301d',
|
||||||
'com.google.android.gms:play-services-gcm:312e61253a236f2d9b750b9c04fc92fd190d23b0b2755c99de6ce4a28b259dae',
|
'com.google.android.gms:play-services-gcm:312e61253a236f2d9b750b9c04fc92fd190d23b0b2755c99de6ce4a28b259dae',
|
||||||
'com.google.android.gms:play-services-maps:45e8021e7ddac4a44a82a0e9698991389ded3023d35c58f38dbd86d54211ec0e',
|
'com.google.android.gms:play-services-maps:45e8021e7ddac4a44a82a0e9698991389ded3023d35c58f38dbd86d54211ec0e',
|
||||||
@ -152,8 +153,8 @@ dependencyVerification {
|
|||||||
'se.emilsjolander:stickylistheaders:a08ca948aa6b220f09d82f16bbbac395f6b78897e9eeac6a9f0b0ba755928eeb',
|
'se.emilsjolander:stickylistheaders:a08ca948aa6b220f09d82f16bbbac395f6b78897e9eeac6a9f0b0ba755928eeb',
|
||||||
'com.jpardogo.materialtabstrip:library:c6ef812fba4f74be7dc4a905faa4c2908cba261a94c13d4f96d5e67e4aad4aaa',
|
'com.jpardogo.materialtabstrip:library:c6ef812fba4f74be7dc4a905faa4c2908cba261a94c13d4f96d5e67e4aad4aaa',
|
||||||
'org.apache.httpcomponents:httpclient-android:6f56466a9bd0d42934b90bfbfe9977a8b654c058bf44a12bdc2877c4e1f033f1',
|
'org.apache.httpcomponents:httpclient-android:6f56466a9bd0d42934b90bfbfe9977a8b654c058bf44a12bdc2877c4e1f033f1',
|
||||||
'com.github.chrisbanes.photoview:library:f152dd0a87aca891aa182e42863fa05e0e8b2842e3b9fc512d7a3a6243c38ac4',
|
'com.github.chrisbanes:PhotoView:ed06775308da260e1fd86d1d3288988fcd3d80db24ce0d7c9fcfedc39e622292',
|
||||||
'com.github.bumptech.glide:glide:76ef123957b5fbaebb05fcbe6606dd58c3bc3fcdadb257f99811d0ac9ea9b88b',
|
'com.github.bumptech.glide:glide:555350c4b9d163f1d3772a64a92119086073ed88340eb284391b1acc1bb5dd6c',
|
||||||
'com.makeramen:roundedimageview:1f5a1865796b308c6cdd114acc6e78408b110f0a62fc63553278fbeacd489cd1',
|
'com.makeramen:roundedimageview:1f5a1865796b308c6cdd114acc6e78408b110f0a62fc63553278fbeacd489cd1',
|
||||||
'com.pnikosis:materialish-progress:d71d80e00717a096784482aee21001a9d299fec3833e4ebd87739ed36cf77c54',
|
'com.pnikosis:materialish-progress:d71d80e00717a096784482aee21001a9d299fec3833e4ebd87739ed36cf77c54',
|
||||||
'org.greenrobot:eventbus:180d4212467df06f2fbc9c8d8a2984533ac79c87769ad883bc421612f0b4e17c',
|
'org.greenrobot:eventbus:180d4212467df06f2fbc9c8d8a2984533ac79c87769ad883bc421612f0b4e17c',
|
||||||
@ -173,22 +174,26 @@ dependencyVerification {
|
|||||||
'com.takisoft.fix:colorpicker:f5d0dbabe406a1800498ca9c1faf34db36e021d8488bf10360f29961fe3ab0d1',
|
'com.takisoft.fix:colorpicker:f5d0dbabe406a1800498ca9c1faf34db36e021d8488bf10360f29961fe3ab0d1',
|
||||||
'com.codewaves.stickyheadergrid:stickyheadergrid:5b4aa6a52a957cfd55f60f4220c11c0c371385a3cb9786cae03c260dcdef5794',
|
'com.codewaves.stickyheadergrid:stickyheadergrid:5b4aa6a52a957cfd55f60f4220c11c0c371385a3cb9786cae03c260dcdef5794',
|
||||||
'com.github.dmytrodanylyk.circular-progress-button:library:635882453475181d737719b2adef658d80f9f85c9bdaf022f06cd22f387cdb16',
|
'com.github.dmytrodanylyk.circular-progress-button:library:635882453475181d737719b2adef658d80f9f85c9bdaf022f06cd22f387cdb16',
|
||||||
'com.android.support:support-annotations:a774272036941b4e912eb426d70c848bde7f06a3bf5fb491f75a427dc6595270',
|
'com.android.support:support-annotations:99d6199ad5a09a0e5e8a49a4cc08f818483ddcfd7eedea2f9923412daf982309',
|
||||||
'com.android.support:support-v4:ee44c481a1f4d6978568e223e8125379b52b2ececdd53450e09ebae144bd377d',
|
'com.android.support:support-v4:36d8385de1be7791231acb933b757198f97cb53bc7d046e8c4bc403d214caaca',
|
||||||
'com.android.support:support-vector-drawable:077009d13882ee96f061e4bc2dbe7cce7ae1762d8297592a787ff741afbfb1f2',
|
'com.android.support:support-vector-drawable:1151b7f0ea29c9a9a8fee042a1dbe82f196632d801c438d08b279e131c767118',
|
||||||
'com.android.support:animated-vector-drawable:628ab1d56a6ee4cbedf32617af8b2a1fe02964ed0628e8f898cc09ddba6e1835',
|
'com.android.support:animated-vector-drawable:d5905aee3c8a4ac75e069a73b914c0a41b9b36b0e6b04126719fca22659d3cc8',
|
||||||
'com.android.support:support-compat:54019c63614ce08b02d7b9605490cd2b29ba5b2505f394a9517450b5f72b30ca',
|
'com.android.support:support-compat:7d6da01cf9766b1705c6c80cfc12274a895b406c4c287900b07a56145ca6c030',
|
||||||
'com.android.support:support-core-ui:e72ae29b823889686cff6fcb948d6745c2baf6d4c2af4fdffa1ec1e42e3833a3',
|
'com.android.support:support-core-ui:82f538051599335ea881ec264407547cab52be750f16ce099cfb27754fc755ff',
|
||||||
'com.android.support:transition:848270144fb180efd2bf928a00ed176dbbc5290badfd638390ffba90088df8b3',
|
'com.android.support:transition:c5d3d1204997f80af1f4a3a315a54b1a23543c554963cef831da726aac34b56f',
|
||||||
'com.google.android.gms:play-services-base:0ca636a8fc9a5af45e607cdcd61783bf5d561cbbb0f862021ce69606eee5ad49',
|
'com.google.android.gms:play-services-base:0ca636a8fc9a5af45e607cdcd61783bf5d561cbbb0f862021ce69606eee5ad49',
|
||||||
'com.google.android.gms:play-services-basement:95dd882c5ffba15b9a99de3fefb05d3a01946623af67454ca00055d222f85a8d',
|
'com.google.android.gms:play-services-basement:95dd882c5ffba15b9a99de3fefb05d3a01946623af67454ca00055d222f85a8d',
|
||||||
'com.google.android.gms:play-services-iid:54e919f9957b8b7820da7ee9b83471d00d0cac1cf08ddea8b5b41aea80bb1a70',
|
'com.google.android.gms:play-services-iid:54e919f9957b8b7820da7ee9b83471d00d0cac1cf08ddea8b5b41aea80bb1a70',
|
||||||
'org.whispersystems:signal-protocol-android:5b8acded7f2a40178eb90ab8e8cbfec89d170d91b3ff5e78487d1098df6185a1',
|
'org.whispersystems:signal-protocol-android:5b8acded7f2a40178eb90ab8e8cbfec89d170d91b3ff5e78487d1098df6185a1',
|
||||||
'org.whispersystems:signal-service-java:308d9e61b753760d0f3828eb3181db58469e75c763bdce5a8335df6c4af47695',
|
'org.whispersystems:signal-service-java:308d9e61b753760d0f3828eb3181db58469e75c763bdce5a8335df6c4af47695',
|
||||||
|
'com.github.bumptech.glide:gifdecoder:217da4520c568a93aea9c7ce3b3cac2c61fabed5113b07ae38698054f6d2d8b6',
|
||||||
|
'com.github.bumptech.glide:disklrucache:795c13245498c0cd806c3af71ee57b3f179cbd1609440a3021c211c364ef74d3',
|
||||||
|
'com.github.bumptech.glide:annotations:057927a236f3229e72cfbac8bed0e9fb398473daf7d933390f59ea4cb79c137b',
|
||||||
'com.nineoldandroids:library:68025a14e3e7673d6ad2f95e4b46d78d7d068343aa99256b686fe59de1b3163a',
|
'com.nineoldandroids:library:68025a14e3e7673d6ad2f95e4b46d78d7d068343aa99256b686fe59de1b3163a',
|
||||||
'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
||||||
'com.klinkerapps:logger:177e325259a8b111ad6745ec10db5861723c99f402222b80629f576f49408541',
|
'com.klinkerapps:logger:177e325259a8b111ad6745ec10db5861723c99f402222b80629f576f49408541',
|
||||||
'com.google.android:flexbox:a9989fd13ae2ee42765dfc515fe362edf4f326e74925d02a10369df8092a4935',
|
'com.google.android:flexbox:a9989fd13ae2ee42765dfc515fe362edf4f326e74925d02a10369df8092a4935',
|
||||||
|
'android.arch.lifecycle:runtime:e4e34e5d02bd102e8d39ddbc29f9ead8a15a61e367993d02238196ac48509ad8',
|
||||||
'com.google.android.gms:play-services-tasks:69ec265168e601d0203d04cd42e34bb019b2f029aa1e16fabd38a5153eea2086',
|
'com.google.android.gms:play-services-tasks:69ec265168e601d0203d04cd42e34bb019b2f029aa1e16fabd38a5153eea2086',
|
||||||
'org.whispersystems:curve25519-android:82595394422b957d4a5b5f1b27b75ba25cf6dc4db4d312418ca38cd6fff279ca',
|
'org.whispersystems:curve25519-android:82595394422b957d4a5b5f1b27b75ba25cf6dc4db4d312418ca38cd6fff279ca',
|
||||||
'org.whispersystems:signal-protocol-java:5152c2b01a25147967d6bf82e540f947901bdfa79260be3eb3e96b03f787d6b5',
|
'org.whispersystems:signal-protocol-java:5152c2b01a25147967d6bf82e540f947901bdfa79260be3eb3e96b03f787d6b5',
|
||||||
@ -197,19 +202,21 @@ dependencyVerification {
|
|||||||
'com.fasterxml.jackson.core:jackson-databind:835097bcdd11f5bc8a08378c70d4c8054dfa4b911691cc2752063c75534d198d',
|
'com.fasterxml.jackson.core:jackson-databind:835097bcdd11f5bc8a08378c70d4c8054dfa4b911691cc2752063c75534d198d',
|
||||||
'com.squareup.okhttp3:okhttp:c1d57f913f74f61d424d4250a92723ba9a61affc12a0ab194d84cc179b472841',
|
'com.squareup.okhttp3:okhttp:c1d57f913f74f61d424d4250a92723ba9a61affc12a0ab194d84cc179b472841',
|
||||||
'com.madgag.spongycastle:prov:b8c3fec3a59aac1aa04ccf4dad7179351e54ef7672f53f508151b614c131398a',
|
'com.madgag.spongycastle:prov:b8c3fec3a59aac1aa04ccf4dad7179351e54ef7672f53f508151b614c131398a',
|
||||||
|
'android.arch.lifecycle:common:86bf301a20ad0cd0a391e22a52e6fbf90575c096ff83233fa9fd0d52b3219121',
|
||||||
|
'android.arch.core:common:5192934cd73df32e2c15722ed7fc488dde90baaec9ae030010dd1a80fb4e74e1',
|
||||||
'org.whispersystems:curve25519-java:7dd659d8822c06c3aea1a47f18fac9e5761e29cab8100030b877db445005f03e',
|
'org.whispersystems:curve25519-java:7dd659d8822c06c3aea1a47f18fac9e5761e29cab8100030b877db445005f03e',
|
||||||
'com.fasterxml.jackson.core:jackson-annotations:0ca408c24202a7626ec8b861e99d85eca5e38b73311dd6dd12e3e9deecc3fe94',
|
'com.fasterxml.jackson.core:jackson-annotations:0ca408c24202a7626ec8b861e99d85eca5e38b73311dd6dd12e3e9deecc3fe94',
|
||||||
'com.fasterxml.jackson.core:jackson-core:cbf4604784b4de226262845447a1ad3bb38a6728cebe86562e2c5afada8be2c0',
|
'com.fasterxml.jackson.core:jackson-core:cbf4604784b4de226262845447a1ad3bb38a6728cebe86562e2c5afada8be2c0',
|
||||||
'com.squareup.okio:okio:734269c3ebc5090e3b23566db558f421f0b4027277c79ad5d176b8ec168bb850',
|
'com.squareup.okio:okio:734269c3ebc5090e3b23566db558f421f0b4027277c79ad5d176b8ec168bb850',
|
||||||
'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f',
|
'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f',
|
||||||
'com.android.support:support-media-compat:566a161d9cb0083ef62a53e46b71ce5b3d455b8635b1a0a4ae28d96d4b583de8',
|
'com.android.support:support-media-compat:9d8cee7cd40eff22ebdeb90c8e70f5ee96c5bd25cb2c3e3b3940e27285a3e98a',
|
||||||
'com.android.support:support-core-utils:34b8437dfa95ff28d29cf57ffa3b1354a9fa9bfe4059f0fd5ce2f5e4326a1748',
|
'com.android.support:support-core-utils:4fda6d4eb430971e3b1dad7456988333f374b0f4ba15f99839ca1a0ab5155c8a',
|
||||||
'com.android.support:support-fragment:316d35d4d2d2902057efad104a73e4bdb50bee260a7075678185b8cd71170945',
|
'com.android.support:support-fragment:a0ab3369ef40fe199160692f0463a5f63f1277ebfb64dd587c76fdb128d76b32',
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 25
|
compileSdkVersion 26
|
||||||
buildToolsVersion '25.0.2'
|
buildToolsVersion '25.0.2'
|
||||||
useLibrary 'org.apache.http.legacy'
|
useLibrary 'org.apache.http.legacy'
|
||||||
|
|
||||||
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
|||||||
#Thu Mar 09 11:46:40 PST 2017
|
#Wed Oct 11 12:30:44 PDT 2017
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-3.5.1-all.zip
|
||||||
|
74
gradlew
vendored
74
gradlew
vendored
@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
##
|
##
|
||||||
@ -6,12 +6,30 @@
|
|||||||
##
|
##
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
# Attempt to set APP_HOME
|
||||||
DEFAULT_JVM_OPTS=""
|
# Resolve links: $0 may be a link
|
||||||
|
PRG="$0"
|
||||||
|
# Need this for relative symlinks.
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG=`dirname "$PRG"`"/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
SAVED="`pwd`"
|
||||||
|
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||||
|
APP_HOME="`pwd -P`"
|
||||||
|
cd "$SAVED" >/dev/null
|
||||||
|
|
||||||
APP_NAME="Gradle"
|
APP_NAME="Gradle"
|
||||||
APP_BASE_NAME=`basename "$0"`
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS=""
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD="maximum"
|
MAX_FD="maximum"
|
||||||
|
|
||||||
@ -30,6 +48,7 @@ die ( ) {
|
|||||||
cygwin=false
|
cygwin=false
|
||||||
msys=false
|
msys=false
|
||||||
darwin=false
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
case "`uname`" in
|
case "`uname`" in
|
||||||
CYGWIN* )
|
CYGWIN* )
|
||||||
cygwin=true
|
cygwin=true
|
||||||
@ -40,31 +59,11 @@ case "`uname`" in
|
|||||||
MINGW* )
|
MINGW* )
|
||||||
msys=true
|
msys=true
|
||||||
;;
|
;;
|
||||||
|
NONSTOP* )
|
||||||
|
nonstop=true
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# For Cygwin, ensure paths are in UNIX format before anything is touched.
|
|
||||||
if $cygwin ; then
|
|
||||||
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Attempt to set APP_HOME
|
|
||||||
# Resolve links: $0 may be a link
|
|
||||||
PRG="$0"
|
|
||||||
# Need this for relative symlinks.
|
|
||||||
while [ -h "$PRG" ] ; do
|
|
||||||
ls=`ls -ld "$PRG"`
|
|
||||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
|
||||||
if expr "$link" : '/.*' > /dev/null; then
|
|
||||||
PRG="$link"
|
|
||||||
else
|
|
||||||
PRG=`dirname "$PRG"`"/$link"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
SAVED="`pwd`"
|
|
||||||
cd "`dirname \"$PRG\"`/" >&-
|
|
||||||
APP_HOME="`pwd -P`"
|
|
||||||
cd "$SAVED" >&-
|
|
||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
# Determine the Java command to use to start the JVM.
|
# Determine the Java command to use to start the JVM.
|
||||||
@ -90,7 +89,7 @@ location of your Java installation."
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||||
MAX_FD_LIMIT=`ulimit -H -n`
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
if [ $? -eq 0 ] ; then
|
if [ $? -eq 0 ] ; then
|
||||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
@ -114,6 +113,7 @@ fi
|
|||||||
if $cygwin ; then
|
if $cygwin ; then
|
||||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
|
|
||||||
# We build the pattern for arguments to be converted via cygpath
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||||
@ -154,11 +154,19 @@ if $cygwin ; then
|
|||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
# Escape application args
|
||||||
function splitJvmOpts() {
|
save ( ) {
|
||||||
JVM_OPTS=("$@")
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
|
echo " "
|
||||||
}
|
}
|
||||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
APP_ARGS=$(save "$@")
|
||||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
|
||||||
|
|
||||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
|
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||||
|
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
||||||
|
14
gradlew.bat
vendored
14
gradlew.bat
vendored
@ -8,14 +8,14 @@
|
|||||||
@rem Set local scope for the variables with windows NT shell
|
@rem Set local scope for the variables with windows NT shell
|
||||||
if "%OS%"=="Windows_NT" setlocal
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
|
||||||
set DEFAULT_JVM_OPTS=
|
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
set DIRNAME=%~dp0
|
||||||
if "%DIRNAME%" == "" set DIRNAME=.
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS=
|
||||||
|
|
||||||
@rem Find java.exe
|
@rem Find java.exe
|
||||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
@ -46,10 +46,9 @@ echo location of your Java installation.
|
|||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
:init
|
:init
|
||||||
@rem Get command-line arguments, handling Windowz variants
|
@rem Get command-line arguments, handling Windows variants
|
||||||
|
|
||||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
|
||||||
|
|
||||||
:win9xME_args
|
:win9xME_args
|
||||||
@rem Slurp the command line arguments.
|
@rem Slurp the command line arguments.
|
||||||
@ -60,11 +59,6 @@ set _SKIP=2
|
|||||||
if "x%~1" == "x" goto execute
|
if "x%~1" == "x" goto execute
|
||||||
|
|
||||||
set CMD_LINE_ARGS=%*
|
set CMD_LINE_ARGS=%*
|
||||||
goto execute
|
|
||||||
|
|
||||||
:4NT_args
|
|
||||||
@rem Get arguments from the 4NT Shell from JP Software
|
|
||||||
set CMD_LINE_ARGS=%$
|
|
||||||
|
|
||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
-keep public class * implements com.bumptech.glide.module.GlideModule
|
||||||
|
-keep public class * extends com.bumptech.glide.AppGlideModule
|
||||||
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
|
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
|
||||||
**[] $VALUES;
|
**[] $VALUES;
|
||||||
public *;
|
public *;
|
||||||
|
@ -3,10 +3,10 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
tools:context="org.thoughtcrime.securesms.components.ZoomingImageView">
|
tools:context="org.thoughtcrime.securesms.components.ZoomingImageView">
|
||||||
|
|
||||||
<ImageView android:id="@+id/image_view"
|
<com.github.chrisbanes.photoview.PhotoView android:id="@+id/image_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:visibility="visible"/>
|
android:visibility="visible"/>
|
||||||
|
|
||||||
<com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
<com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
||||||
android:id="@+id/subsampling_image_view"
|
android:id="@+id/subsampling_image_view"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/**
|
/*
|
||||||
* Copyright (C) 2014 Open Whisper Systems
|
* Copyright (C) 2014 Open Whisper Systems
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
@ -40,8 +40,9 @@ import android.widget.Toast;
|
|||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
import com.bumptech.glide.Glide;
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||||
import com.bumptech.glide.request.animation.GlideAnimation;
|
import com.bumptech.glide.request.RequestOptions;
|
||||||
import com.bumptech.glide.request.target.SimpleTarget;
|
import com.bumptech.glide.request.target.SimpleTarget;
|
||||||
|
import com.bumptech.glide.request.transition.Transition;
|
||||||
import com.soundcloud.android.crop.Crop;
|
import com.soundcloud.android.crop.Crop;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.components.PushRecipientsPanel;
|
import org.thoughtcrime.securesms.components.PushRecipientsPanel;
|
||||||
@ -58,7 +59,7 @@ import org.thoughtcrime.securesms.database.RecipientDatabase;
|
|||||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||||
import org.thoughtcrime.securesms.groups.GroupManager;
|
import org.thoughtcrime.securesms.groups.GroupManager;
|
||||||
import org.thoughtcrime.securesms.groups.GroupManager.GroupActionResult;
|
import org.thoughtcrime.securesms.groups.GroupManager.GroupActionResult;
|
||||||
import org.thoughtcrime.securesms.mms.RoundedCorners;
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||||
@ -306,16 +307,19 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
|||||||
new Crop(data.getData()).output(outputFile).asSquare().start(this);
|
new Crop(data.getData()).output(outputFile).asSquare().start(this);
|
||||||
break;
|
break;
|
||||||
case Crop.REQUEST_CROP:
|
case Crop.REQUEST_CROP:
|
||||||
Glide.with(this).load(Crop.getOutput(data)).asBitmap()
|
GlideApp.with(this)
|
||||||
.skipMemoryCache(true)
|
.asBitmap()
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.load(Crop.getOutput(data))
|
||||||
.centerCrop().override(AVATAR_SIZE, AVATAR_SIZE)
|
.skipMemoryCache(true)
|
||||||
.into(new SimpleTarget<Bitmap>() {
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
@Override
|
.centerCrop()
|
||||||
public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
|
.override(AVATAR_SIZE, AVATAR_SIZE)
|
||||||
setAvatar(Crop.getOutput(data), resource);
|
.into(new SimpleTarget<Bitmap>() {
|
||||||
}
|
@Override
|
||||||
});
|
public void onResourceReady(Bitmap resource, Transition<? super Bitmap> transition) {
|
||||||
|
setAvatar(Crop.getOutput(data), resource);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -573,12 +577,12 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
|||||||
|
|
||||||
private <T> void setAvatar(T model, Bitmap bitmap) {
|
private <T> void setAvatar(T model, Bitmap bitmap) {
|
||||||
avatarBmp = bitmap;
|
avatarBmp = bitmap;
|
||||||
Glide.with(this)
|
GlideApp.with(this)
|
||||||
.load(model)
|
.load(model)
|
||||||
.skipMemoryCache(true)
|
.circleCrop()
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.skipMemoryCache(true)
|
||||||
.transform(new RoundedCorners(this, avatar.getWidth() / 2))
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
.into(avatar);
|
.into(avatar);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class GroupData {
|
private static class GroupData {
|
||||||
|
@ -4,7 +4,6 @@ import android.content.ActivityNotFoundException;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.FragmentTransaction;
|
import android.support.v4.app.FragmentTransaction;
|
||||||
import android.support.v7.app.ActionBarActivity;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
@ -20,7 +20,6 @@ import android.view.ViewGroup;
|
|||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
|
||||||
import com.bumptech.glide.load.Key;
|
import com.bumptech.glide.load.Key;
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||||
import com.bumptech.glide.signature.MediaStoreSignature;
|
import com.bumptech.glide.signature.MediaStoreSignature;
|
||||||
@ -28,6 +27,7 @@ import com.bumptech.glide.signature.MediaStoreSignature;
|
|||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
|
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
|
||||||
import org.thoughtcrime.securesms.database.loaders.RecentPhotosLoader;
|
import org.thoughtcrime.securesms.database.loaders.RecentPhotosLoader;
|
||||||
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||||
|
|
||||||
public class RecentPhotoViewRail extends FrameLayout implements LoaderManager.LoaderCallbacks<Cursor> {
|
public class RecentPhotoViewRail extends FrameLayout implements LoaderManager.LoaderCallbacks<Cursor> {
|
||||||
@ -111,12 +111,11 @@ public class RecentPhotoViewRail extends FrameLayout implements LoaderManager.Lo
|
|||||||
|
|
||||||
Key signature = new MediaStoreSignature(mimeType, dateModified, orientation);
|
Key signature = new MediaStoreSignature(mimeType, dateModified, orientation);
|
||||||
|
|
||||||
Glide.with(getContext())
|
GlideApp.with(getContext())
|
||||||
.fromMediaStore()
|
.load(uri)
|
||||||
.load(uri)
|
.signature(signature)
|
||||||
.signature(signature)
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.into(viewHolder.imageView);
|
||||||
.into(viewHolder.imageView);
|
|
||||||
|
|
||||||
viewHolder.imageView.setOnClickListener(new OnClickListener() {
|
viewHolder.imageView.setOnClickListener(new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -15,22 +15,25 @@ import android.view.View;
|
|||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
|
||||||
import com.bumptech.glide.DrawableRequestBuilder;
|
|
||||||
import com.bumptech.glide.GenericRequestBuilder;
|
|
||||||
import com.bumptech.glide.Glide;
|
import com.bumptech.glide.Glide;
|
||||||
|
import com.bumptech.glide.RequestBuilder;
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||||
|
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||||
|
import com.bumptech.glide.request.RequestOptions;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
||||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
|
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
|
||||||
import org.thoughtcrime.securesms.mms.RoundedCorners;
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||||
import org.thoughtcrime.securesms.mms.Slide;
|
import org.thoughtcrime.securesms.mms.Slide;
|
||||||
import org.thoughtcrime.securesms.mms.SlideClickListener;
|
import org.thoughtcrime.securesms.mms.SlideClickListener;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
|
|
||||||
|
import static com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withCrossFade;
|
||||||
|
|
||||||
public class ThumbnailView extends FrameLayout {
|
public class ThumbnailView extends FrameLayout {
|
||||||
|
|
||||||
private static final String TAG = ThumbnailView.class.getSimpleName();
|
private static final String TAG = ThumbnailView.class.getSimpleName();
|
||||||
@ -141,18 +144,18 @@ public class ThumbnailView extends FrameLayout {
|
|||||||
|
|
||||||
if (slide.getThumbnailUri() != null) buildThumbnailGlideRequest(slide, masterSecret).into(image);
|
if (slide.getThumbnailUri() != null) buildThumbnailGlideRequest(slide, masterSecret).into(image);
|
||||||
else if (slide.hasPlaceholder()) buildPlaceholderGlideRequest(slide).into(image);
|
else if (slide.hasPlaceholder()) buildPlaceholderGlideRequest(slide).into(image);
|
||||||
else Glide.clear(image);
|
else Glide.with(getContext()).clear(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setImageResource(@NonNull MasterSecret masterSecret, @NonNull Uri uri) {
|
public void setImageResource(@NonNull MasterSecret masterSecret, @NonNull Uri uri) {
|
||||||
if (transferControls.isPresent()) getTransferControls().setVisibility(View.GONE);
|
if (transferControls.isPresent()) getTransferControls().setVisibility(View.GONE);
|
||||||
|
|
||||||
Glide.with(getContext())
|
GlideApp.with(getContext())
|
||||||
.load(new DecryptableUri(masterSecret, uri))
|
.load(new DecryptableUri(masterSecret, uri))
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
.crossFade()
|
.transform(new RoundedCorners(radius))
|
||||||
.transform(new RoundedCorners(getContext(), true, radius, backgroundColorHint))
|
.transition(withCrossFade())
|
||||||
.into(image);
|
.into(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setThumbnailClickListener(SlideClickListener listener) {
|
public void setThumbnailClickListener(SlideClickListener listener) {
|
||||||
@ -164,7 +167,7 @@ public class ThumbnailView extends FrameLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
if (isContextValid()) Glide.clear(image);
|
if (isContextValid()) Glide.with(getContext()).clear(image);
|
||||||
if (transferControls.isPresent()) getTransferControls().clear();
|
if (transferControls.isPresent()) getTransferControls().clear();
|
||||||
|
|
||||||
slide = null;
|
slide = null;
|
||||||
@ -181,24 +184,23 @@ public class ThumbnailView extends FrameLayout {
|
|||||||
!((Activity)getContext()).isDestroyed();
|
!((Activity)getContext()).isDestroyed();
|
||||||
}
|
}
|
||||||
|
|
||||||
private GenericRequestBuilder buildThumbnailGlideRequest(@NonNull Slide slide, @NonNull MasterSecret masterSecret) {
|
private RequestBuilder buildThumbnailGlideRequest(@NonNull Slide slide, @NonNull MasterSecret masterSecret) {
|
||||||
@SuppressWarnings("ConstantConditions")
|
RequestBuilder builder = GlideApp.with(getContext())
|
||||||
DrawableRequestBuilder<DecryptableUri> builder = Glide.with(getContext())
|
.load(new DecryptableUri(masterSecret, slide.getThumbnailUri()))
|
||||||
.load(new DecryptableUri(masterSecret, slide.getThumbnailUri()))
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.transform(new RoundedCorners(radius))
|
||||||
.crossFade()
|
.transition(withCrossFade());
|
||||||
.transform(new RoundedCorners(getContext(), true, radius, backgroundColorHint));
|
|
||||||
|
|
||||||
if (slide.isInProgress()) return builder;
|
if (slide.isInProgress()) return builder;
|
||||||
else return builder.error(R.drawable.ic_missing_thumbnail_picture);
|
else return builder.apply(RequestOptions.errorOf(R.drawable.ic_missing_thumbnail_picture));
|
||||||
}
|
}
|
||||||
|
|
||||||
private GenericRequestBuilder buildPlaceholderGlideRequest(Slide slide) {
|
private RequestBuilder buildPlaceholderGlideRequest(Slide slide) {
|
||||||
return Glide.with(getContext())
|
return GlideApp.with(getContext())
|
||||||
.load(slide.getPlaceholderRes(getContext().getTheme()))
|
.asBitmap()
|
||||||
.asBitmap()
|
.load(slide.getPlaceholderRes(getContext().getTheme()))
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
.fitCenter();
|
.fitCenter();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ThumbnailClickDispatcher implements View.OnClickListener {
|
private class ThumbnailClickDispatcher implements View.OnClickListener {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package org.thoughtcrime.securesms.components;
|
package org.thoughtcrime.securesms.components;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Canvas;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
@ -10,37 +9,33 @@ import android.util.Log;
|
|||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.ImageView;
|
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||||
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
|
|
||||||
import com.bumptech.glide.request.RequestListener;
|
|
||||||
import com.bumptech.glide.request.target.GlideDrawableImageViewTarget;
|
|
||||||
import com.bumptech.glide.request.target.Target;
|
import com.bumptech.glide.request.target.Target;
|
||||||
import com.davemorrissey.labs.subscaleview.ImageSource;
|
import com.davemorrissey.labs.subscaleview.ImageSource;
|
||||||
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
|
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
|
||||||
|
import com.github.chrisbanes.photoview.PhotoView;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.components.subsampling.AttachmentBitmapDecoder;
|
import org.thoughtcrime.securesms.components.subsampling.AttachmentBitmapDecoder;
|
||||||
import org.thoughtcrime.securesms.components.subsampling.AttachmentRegionDecoder;
|
import org.thoughtcrime.securesms.components.subsampling.AttachmentRegionDecoder;
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
|
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
|
||||||
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||||
import org.thoughtcrime.securesms.mms.PartAuthority;
|
import org.thoughtcrime.securesms.mms.PartAuthority;
|
||||||
import org.thoughtcrime.securesms.util.BitmapDecodingException;
|
import org.thoughtcrime.securesms.util.BitmapDecodingException;
|
||||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||||
|
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
import uk.co.senab.photoview.PhotoViewAttacher;
|
|
||||||
|
|
||||||
public class ZoomingImageView extends FrameLayout {
|
public class ZoomingImageView extends FrameLayout {
|
||||||
|
|
||||||
private static final String TAG = ZoomingImageView.class.getName();
|
private static final String TAG = ZoomingImageView.class.getName();
|
||||||
|
|
||||||
private final ImageView imageView;
|
private final PhotoView photoView;
|
||||||
private final PhotoViewAttacher imageViewAttacher;
|
|
||||||
private final SubsamplingScaleImageView subsamplingImageView;
|
private final SubsamplingScaleImageView subsamplingImageView;
|
||||||
|
|
||||||
public ZoomingImageView(Context context) {
|
public ZoomingImageView(Context context) {
|
||||||
@ -56,9 +51,8 @@ public class ZoomingImageView extends FrameLayout {
|
|||||||
|
|
||||||
inflate(context, R.layout.zooming_image_view, this);
|
inflate(context, R.layout.zooming_image_view, this);
|
||||||
|
|
||||||
this.imageView = (ImageView) findViewById(R.id.image_view);
|
this.photoView = findViewById(R.id.image_view);
|
||||||
this.subsamplingImageView = (SubsamplingScaleImageView) findViewById(R.id.subsampling_image_view);
|
this.subsamplingImageView = findViewById(R.id.subsampling_image_view);
|
||||||
this.imageViewAttacher = new PhotoViewAttacher(imageView);
|
|
||||||
|
|
||||||
this.subsamplingImageView.setBitmapDecoderClass(AttachmentBitmapDecoder.class);
|
this.subsamplingImageView.setBitmapDecoderClass(AttachmentBitmapDecoder.class);
|
||||||
this.subsamplingImageView.setRegionDecoderClass(AttachmentRegionDecoder.class);
|
this.subsamplingImageView.setRegionDecoderClass(AttachmentRegionDecoder.class);
|
||||||
@ -74,7 +68,7 @@ public class ZoomingImageView extends FrameLayout {
|
|||||||
new AsyncTask<Void, Void, Pair<Integer, Integer>>() {
|
new AsyncTask<Void, Void, Pair<Integer, Integer>>() {
|
||||||
@Override
|
@Override
|
||||||
protected @Nullable Pair<Integer, Integer> doInBackground(Void... params) {
|
protected @Nullable Pair<Integer, Integer> doInBackground(Void... params) {
|
||||||
if (contentType.equals("image/gif")) return null;
|
if (MediaUtil.isGif(contentType)) return null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
InputStream inputStream = PartAuthority.getAttachmentStream(context, masterSecret, uri);
|
InputStream inputStream = PartAuthority.getAttachmentStream(context, masterSecret, uri);
|
||||||
@ -100,32 +94,26 @@ public class ZoomingImageView extends FrameLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setImageViewUri(MasterSecret masterSecret, Uri uri) {
|
private void setImageViewUri(MasterSecret masterSecret, Uri uri) {
|
||||||
|
photoView.setVisibility(View.VISIBLE);
|
||||||
subsamplingImageView.setVisibility(View.GONE);
|
subsamplingImageView.setVisibility(View.GONE);
|
||||||
imageView.setVisibility(View.VISIBLE);
|
|
||||||
|
|
||||||
Glide.with(getContext())
|
GlideApp.with(getContext())
|
||||||
.load(new DecryptableUri(masterSecret, uri))
|
.load(new DecryptableUri(masterSecret, uri))
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
.dontTransform()
|
.dontTransform()
|
||||||
.dontAnimate()
|
.override(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
|
||||||
.into(new GlideDrawableImageViewTarget(imageView) {
|
.into(photoView);
|
||||||
@Override protected void setResource(GlideDrawable resource) {
|
|
||||||
super.setResource(resource);
|
|
||||||
imageViewAttacher.update();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setSubsamplingImageViewUri(Uri uri) {
|
private void setSubsamplingImageViewUri(Uri uri) {
|
||||||
subsamplingImageView.setVisibility(View.VISIBLE);
|
subsamplingImageView.setVisibility(View.VISIBLE);
|
||||||
imageView.setVisibility(View.GONE);
|
photoView.setVisibility(View.GONE);
|
||||||
|
|
||||||
subsamplingImageView.setImage(ImageSource.uri(uri));
|
subsamplingImageView.setImage(ImageSource.uri(uri));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void cleanup() {
|
public void cleanup() {
|
||||||
imageView.setImageDrawable(null);
|
photoView.setImageDrawable(null);
|
||||||
subsamplingImageView.recycle();
|
subsamplingImageView.recycle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,13 +11,12 @@ import android.support.annotation.WorkerThread;
|
|||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.database.Address;
|
import org.thoughtcrime.securesms.database.Address;
|
||||||
import org.thoughtcrime.securesms.mms.ContactPhotoUriLoader.ContactPhotoUri;
|
import org.thoughtcrime.securesms.mms.ContactPhotoUriLoader.ContactPhotoUri;
|
||||||
import org.thoughtcrime.securesms.profiles.AvatarPhotoUriLoader;
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||||
import org.thoughtcrime.securesms.profiles.AvatarPhotoUriLoader.AvatarPhotoUri;
|
import org.thoughtcrime.securesms.profiles.AvatarPhotoUriLoader.AvatarPhotoUri;
|
||||||
|
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
@ -58,10 +57,13 @@ public class ContactPhotoFactory {
|
|||||||
if (uri == null) return getSignalAvatarContactPhoto(context, address, name, targetSize);
|
if (uri == null) return getSignalAvatarContactPhoto(context, address, name, targetSize);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Bitmap bitmap = Glide.with(context)
|
Bitmap bitmap = GlideApp.with(context)
|
||||||
.load(new ContactPhotoUri(uri)).asBitmap()
|
.asBitmap()
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.load(new ContactPhotoUri(uri))
|
||||||
.centerCrop().into(targetSize, targetSize).get();
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
|
.centerCrop()
|
||||||
|
.submit(targetSize, targetSize)
|
||||||
|
.get();
|
||||||
return new BitmapContactPhoto(bitmap);
|
return new BitmapContactPhoto(bitmap);
|
||||||
} catch (ExecutionException e) {
|
} catch (ExecutionException e) {
|
||||||
return getSignalAvatarContactPhoto(context, address, name, targetSize);
|
return getSignalAvatarContactPhoto(context, address, name, targetSize);
|
||||||
@ -83,14 +85,14 @@ public class ContactPhotoFactory {
|
|||||||
int targetSize)
|
int targetSize)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
Bitmap bitmap = Glide.with(context)
|
Bitmap bitmap = GlideApp.with(context)
|
||||||
.load(new AvatarPhotoUri(address))
|
.asBitmap()
|
||||||
.asBitmap()
|
.load(new AvatarPhotoUri(address))
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
.skipMemoryCache(true)
|
.skipMemoryCache(true)
|
||||||
.centerCrop()
|
.centerCrop()
|
||||||
.into(targetSize, targetSize)
|
.submit(targetSize, targetSize)
|
||||||
.get();
|
.get();
|
||||||
|
|
||||||
return new BitmapContactPhoto(bitmap);
|
return new BitmapContactPhoto(bitmap);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
|
@ -3,7 +3,9 @@ package org.thoughtcrime.securesms.giph.ui;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.drawable.ColorDrawable;
|
import android.graphics.drawable.ColorDrawable;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
@ -11,16 +13,18 @@ import android.view.View;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
|
|
||||||
import com.bumptech.glide.DrawableRequestBuilder;
|
|
||||||
import com.bumptech.glide.Glide;
|
import com.bumptech.glide.Glide;
|
||||||
|
import com.bumptech.glide.RequestBuilder;
|
||||||
|
import com.bumptech.glide.load.DataSource;
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||||
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
|
import com.bumptech.glide.load.engine.GlideException;
|
||||||
import com.bumptech.glide.request.RequestListener;
|
import com.bumptech.glide.request.RequestListener;
|
||||||
import com.bumptech.glide.request.target.Target;
|
import com.bumptech.glide.request.target.Target;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.color.MaterialColor;
|
import org.thoughtcrime.securesms.color.MaterialColor;
|
||||||
import org.thoughtcrime.securesms.giph.model.GiphyImage;
|
import org.thoughtcrime.securesms.giph.model.GiphyImage;
|
||||||
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||||
|
|
||||||
@ -37,7 +41,7 @@ public class GiphyAdapter extends RecyclerView.Adapter<GiphyAdapter.GiphyViewHol
|
|||||||
private Context context;
|
private Context context;
|
||||||
private OnItemClickListener listener;
|
private OnItemClickListener listener;
|
||||||
|
|
||||||
class GiphyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, RequestListener<String, GlideDrawable> {
|
class GiphyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, RequestListener<Drawable> {
|
||||||
|
|
||||||
public AspectRatioImageView thumbnail;
|
public AspectRatioImageView thumbnail;
|
||||||
public GiphyImage image;
|
public GiphyImage image;
|
||||||
@ -58,7 +62,7 @@ public class GiphyAdapter extends RecyclerView.Adapter<GiphyAdapter.GiphyViewHol
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
|
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
|
||||||
Log.w(TAG, e);
|
Log.w(TAG, e);
|
||||||
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
@ -69,10 +73,11 @@ public class GiphyAdapter extends RecyclerView.Adapter<GiphyAdapter.GiphyViewHol
|
|||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
|
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (image.getGifUrl().equals(model)) {
|
if (image.getGifUrl().equals(model)) {
|
||||||
this.modelReady = true;
|
this.modelReady = true;
|
||||||
@ -83,6 +88,7 @@ public class GiphyAdapter extends RecyclerView.Adapter<GiphyAdapter.GiphyViewHol
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public File getFile(boolean forMms) throws ExecutionException, InterruptedException {
|
public File getFile(boolean forMms) throws ExecutionException, InterruptedException {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
while (!modelReady) {
|
while (!modelReady) {
|
||||||
@ -103,7 +109,7 @@ public class GiphyAdapter extends RecyclerView.Adapter<GiphyAdapter.GiphyViewHol
|
|||||||
}
|
}
|
||||||
|
|
||||||
GiphyAdapter(Context context, List<GiphyImage> images) {
|
GiphyAdapter(Context context, List<GiphyImage> images) {
|
||||||
this.context = context;
|
this.context = context.getApplicationContext();
|
||||||
this.images = images;
|
this.images = images;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,32 +140,33 @@ public class GiphyAdapter extends RecyclerView.Adapter<GiphyAdapter.GiphyViewHol
|
|||||||
holder.thumbnail.setAspectRatio(image.getGifAspectRatio());
|
holder.thumbnail.setAspectRatio(image.getGifAspectRatio());
|
||||||
holder.gifProgress.setVisibility(View.GONE);
|
holder.gifProgress.setVisibility(View.GONE);
|
||||||
|
|
||||||
DrawableRequestBuilder<String> thumbnailRequest = Glide.with(context)
|
RequestBuilder<Drawable> thumbnailRequest = GlideApp.with(context)
|
||||||
.load(image.getStillUrl());
|
.load(image.getStillUrl())
|
||||||
|
.diskCacheStrategy(DiskCacheStrategy.ALL);
|
||||||
|
|
||||||
if (Util.isLowMemory(context)) {
|
if (Util.isLowMemory(context)) {
|
||||||
Glide.with(context)
|
GlideApp.with(context)
|
||||||
.load(image.getStillUrl())
|
.load(image.getStillUrl())
|
||||||
.placeholder(new ColorDrawable(Util.getRandomElement(MaterialColor.values()).toConversationColor(context)))
|
.placeholder(new ColorDrawable(Util.getRandomElement(MaterialColor.values()).toConversationColor(context)))
|
||||||
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||||
.into(holder.thumbnail);
|
.into(holder.thumbnail);
|
||||||
|
|
||||||
holder.setModelReady();
|
holder.setModelReady();
|
||||||
} else {
|
} else {
|
||||||
Glide.with(context)
|
GlideApp.with(context)
|
||||||
.load(image.getGifUrl())
|
.load(image.getGifUrl())
|
||||||
.thumbnail(thumbnailRequest)
|
.thumbnail(thumbnailRequest)
|
||||||
.placeholder(new ColorDrawable(Util.getRandomElement(MaterialColor.values()).toConversationColor(context)))
|
.placeholder(new ColorDrawable(Util.getRandomElement(MaterialColor.values()).toConversationColor(context)))
|
||||||
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||||
.listener(holder)
|
.listener(holder)
|
||||||
.into(holder.thumbnail);
|
.into(holder.thumbnail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onViewRecycled(GiphyViewHolder holder) {
|
public void onViewRecycled(GiphyViewHolder holder) {
|
||||||
super.onViewRecycled(holder);
|
super.onViewRecycled(holder);
|
||||||
Glide.clear(holder.thumbnail);
|
Glide.with(context).clear(holder.thumbnail);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package org.thoughtcrime.securesms.glide;
|
package org.thoughtcrime.securesms.glide;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
import com.bumptech.glide.Priority;
|
import com.bumptech.glide.Priority;
|
||||||
|
import com.bumptech.glide.load.DataSource;
|
||||||
import com.bumptech.glide.load.data.DataFetcher;
|
import com.bumptech.glide.load.data.DataFetcher;
|
||||||
import com.bumptech.glide.load.model.GlideUrl;
|
import com.bumptech.glide.load.model.GlideUrl;
|
||||||
import com.bumptech.glide.util.ContentLengthInputStream;
|
import com.bumptech.glide.util.ContentLengthInputStream;
|
||||||
@ -17,7 +20,7 @@ import okhttp3.ResponseBody;
|
|||||||
/**
|
/**
|
||||||
* Fetches an {@link InputStream} using the okhttp library.
|
* Fetches an {@link InputStream} using the okhttp library.
|
||||||
*/
|
*/
|
||||||
public class OkHttpStreamFetcher implements DataFetcher<InputStream> {
|
class OkHttpStreamFetcher implements DataFetcher<InputStream> {
|
||||||
|
|
||||||
private static final String TAG = OkHttpStreamFetcher.class.getName();
|
private static final String TAG = OkHttpStreamFetcher.class.getName();
|
||||||
|
|
||||||
@ -26,33 +29,38 @@ public class OkHttpStreamFetcher implements DataFetcher<InputStream> {
|
|||||||
private InputStream stream;
|
private InputStream stream;
|
||||||
private ResponseBody responseBody;
|
private ResponseBody responseBody;
|
||||||
|
|
||||||
public OkHttpStreamFetcher(OkHttpClient client, GlideUrl url) {
|
OkHttpStreamFetcher(OkHttpClient client, GlideUrl url) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.url = url;
|
this.url = url;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InputStream loadData(Priority priority) throws Exception {
|
public void loadData(Priority priority, DataCallback<? super InputStream> callback) {
|
||||||
Request.Builder requestBuilder = new Request.Builder()
|
try {
|
||||||
.url(url.toStringUrl());
|
Request.Builder requestBuilder = new Request.Builder()
|
||||||
|
.url(url.toStringUrl());
|
||||||
|
|
||||||
for (Map.Entry<String, String> headerEntry : url.getHeaders().entrySet()) {
|
for (Map.Entry<String, String> headerEntry : url.getHeaders().entrySet()) {
|
||||||
String key = headerEntry.getKey();
|
String key = headerEntry.getKey();
|
||||||
requestBuilder.addHeader(key, headerEntry.getValue());
|
requestBuilder.addHeader(key, headerEntry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
Request request = requestBuilder.build();
|
||||||
|
Response response = client.newCall(request).execute();
|
||||||
|
|
||||||
|
responseBody = response.body();
|
||||||
|
|
||||||
|
if (!response.isSuccessful()) {
|
||||||
|
throw new IOException("Request failed with code: " + response.code());
|
||||||
|
}
|
||||||
|
|
||||||
|
long contentLength = responseBody.contentLength();
|
||||||
|
stream = ContentLengthInputStream.obtain(responseBody.byteStream(), contentLength);
|
||||||
|
|
||||||
|
callback.onDataReady(stream);
|
||||||
|
} catch (IOException e) {
|
||||||
|
callback.onLoadFailed(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
Request request = requestBuilder.build();
|
|
||||||
Response response = client.newCall(request).execute();
|
|
||||||
|
|
||||||
responseBody = response.body();
|
|
||||||
|
|
||||||
if (!response.isSuccessful()) {
|
|
||||||
throw new IOException("Request failed with code: " + response.code());
|
|
||||||
}
|
|
||||||
|
|
||||||
long contentLength = responseBody.contentLength();
|
|
||||||
stream = ContentLengthInputStream.obtain(responseBody.byteStream(), contentLength);
|
|
||||||
return stream;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -69,13 +77,20 @@ public class OkHttpStreamFetcher implements DataFetcher<InputStream> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return url.getCacheKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cancel() {
|
public void cancel() {
|
||||||
// TODO: call cancel on the client when this method is called on a background thread. See #257
|
// TODO: call cancel on the client when this method is called on a background thread. See #257
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Class<InputStream> getDataClass() {
|
||||||
|
return InputStream.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public DataSource getDataSource() {
|
||||||
|
return DataSource.REMOTE;
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,12 +1,12 @@
|
|||||||
package org.thoughtcrime.securesms.glide;
|
package org.thoughtcrime.securesms.glide;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import com.bumptech.glide.load.data.DataFetcher;
|
import com.bumptech.glide.load.Options;
|
||||||
import com.bumptech.glide.load.model.GenericLoaderFactory;
|
|
||||||
import com.bumptech.glide.load.model.GlideUrl;
|
import com.bumptech.glide.load.model.GlideUrl;
|
||||||
import com.bumptech.glide.load.model.ModelLoader;
|
import com.bumptech.glide.load.model.ModelLoader;
|
||||||
import com.bumptech.glide.load.model.ModelLoaderFactory;
|
import com.bumptech.glide.load.model.ModelLoaderFactory;
|
||||||
|
import com.bumptech.glide.load.model.MultiModelLoaderFactory;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.giph.net.GiphyProxySelector;
|
import org.thoughtcrime.securesms.giph.net.GiphyProxySelector;
|
||||||
|
|
||||||
@ -19,9 +19,23 @@ import okhttp3.OkHttpClient;
|
|||||||
*/
|
*/
|
||||||
public class OkHttpUrlLoader implements ModelLoader<GlideUrl, InputStream> {
|
public class OkHttpUrlLoader implements ModelLoader<GlideUrl, InputStream> {
|
||||||
|
|
||||||
/**
|
private final OkHttpClient client;
|
||||||
* The default factory for {@link OkHttpUrlLoader}s.
|
|
||||||
*/
|
private OkHttpUrlLoader(OkHttpClient client) {
|
||||||
|
this.client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public LoadData<InputStream> buildLoadData(GlideUrl glideUrl, int width, int height, Options options) {
|
||||||
|
return new LoadData<>(glideUrl, new OkHttpStreamFetcher(client, glideUrl));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handles(GlideUrl glideUrl) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public static class Factory implements ModelLoaderFactory<GlideUrl, InputStream> {
|
public static class Factory implements ModelLoaderFactory<GlideUrl, InputStream> {
|
||||||
private static volatile OkHttpClient internalClient;
|
private static volatile OkHttpClient internalClient;
|
||||||
private OkHttpClient client;
|
private OkHttpClient client;
|
||||||
@ -39,22 +53,16 @@ public class OkHttpUrlLoader implements ModelLoader<GlideUrl, InputStream> {
|
|||||||
return internalClient;
|
return internalClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for a new Factory that runs requests using a static singleton client.
|
|
||||||
*/
|
|
||||||
public Factory() {
|
public Factory() {
|
||||||
this(getInternalClient());
|
this(getInternalClient());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for a new Factory that runs requests using given client.
|
|
||||||
*/
|
|
||||||
private Factory(OkHttpClient client) {
|
private Factory(OkHttpClient client) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ModelLoader<GlideUrl, InputStream> build(Context context, GenericLoaderFactory factories) {
|
public ModelLoader<GlideUrl, InputStream> build(MultiModelLoaderFactory multiFactory) {
|
||||||
return new OkHttpUrlLoader(client);
|
return new OkHttpUrlLoader(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,15 +71,4 @@ public class OkHttpUrlLoader implements ModelLoader<GlideUrl, InputStream> {
|
|||||||
// Do nothing, this instance doesn't own the client.
|
// Do nothing, this instance doesn't own the client.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final OkHttpClient client;
|
|
||||||
|
|
||||||
private OkHttpUrlLoader(OkHttpClient client) {
|
|
||||||
this.client = client;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DataFetcher<InputStream> getResourceFetcher(GlideUrl model, int width, int height) {
|
|
||||||
return new OkHttpStreamFetcher(client, model);
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,40 +1,45 @@
|
|||||||
package org.thoughtcrime.securesms.mms;
|
package org.thoughtcrime.securesms.mms;
|
||||||
|
|
||||||
import android.content.ContentResolver;
|
import android.support.annotation.NonNull;
|
||||||
import android.content.Context;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.bumptech.glide.Priority;
|
import com.bumptech.glide.Priority;
|
||||||
|
import com.bumptech.glide.load.DataSource;
|
||||||
import com.bumptech.glide.load.data.DataFetcher;
|
import com.bumptech.glide.load.data.DataFetcher;
|
||||||
import com.bumptech.glide.load.data.StreamLocalUriFetcher;
|
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
import org.whispersystems.libsignal.InvalidMessageException;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
import org.whispersystems.signalservice.api.crypto.AttachmentCipherInputStream;
|
import org.whispersystems.signalservice.api.crypto.AttachmentCipherInputStream;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
public class AttachmentStreamLocalUriFetcher implements DataFetcher<InputStream> {
|
class AttachmentStreamLocalUriFetcher implements DataFetcher<InputStream> {
|
||||||
|
|
||||||
private static final String TAG = AttachmentStreamLocalUriFetcher.class.getSimpleName();
|
private static final String TAG = AttachmentStreamLocalUriFetcher.class.getSimpleName();
|
||||||
|
|
||||||
private File attachment;
|
private File attachment;
|
||||||
private byte[] key;
|
private byte[] key;
|
||||||
private InputStream is;
|
private InputStream is;
|
||||||
|
|
||||||
public AttachmentStreamLocalUriFetcher(File attachment, byte[] key) {
|
AttachmentStreamLocalUriFetcher(File attachment, byte[] key) {
|
||||||
this.attachment = attachment;
|
this.attachment = attachment;
|
||||||
this.key = key;
|
this.key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public InputStream loadData(Priority priority) throws Exception {
|
@Override
|
||||||
is = new AttachmentCipherInputStream(attachment, key, Optional.<byte[]>absent());
|
public void loadData(Priority priority, DataCallback<? super InputStream> callback) {
|
||||||
return is;
|
try {
|
||||||
|
is = new AttachmentCipherInputStream(attachment, key, Optional.absent());
|
||||||
|
callback.onDataReady(is);
|
||||||
|
} catch (IOException | InvalidMessageException e) {
|
||||||
|
callback.onLoadFailed(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void cleanup() {
|
@Override
|
||||||
|
public void cleanup() {
|
||||||
try {
|
try {
|
||||||
if (is != null) is.close();
|
if (is != null) is.close();
|
||||||
is = null;
|
is = null;
|
||||||
@ -43,11 +48,20 @@ public class AttachmentStreamLocalUriFetcher implements DataFetcher<InputStream>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public String getId() {
|
@Override
|
||||||
return AttachmentStreamLocalUriFetcher.class.getCanonicalName() + "::" + attachment.getAbsolutePath();
|
public void cancel() {}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Class<InputStream> getDataClass() {
|
||||||
|
return InputStream.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void cancel() {
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public DataSource getDataSource() {
|
||||||
|
return DataSource.LOCAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,39 +1,38 @@
|
|||||||
package org.thoughtcrime.securesms.mms;
|
package org.thoughtcrime.securesms.mms;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import com.bumptech.glide.load.data.DataFetcher;
|
import com.bumptech.glide.load.Key;
|
||||||
import com.bumptech.glide.load.model.GenericLoaderFactory;
|
import com.bumptech.glide.load.Options;
|
||||||
import com.bumptech.glide.load.model.ModelLoader;
|
import com.bumptech.glide.load.model.ModelLoader;
|
||||||
import com.bumptech.glide.load.model.ModelLoaderFactory;
|
import com.bumptech.glide.load.model.ModelLoaderFactory;
|
||||||
import com.bumptech.glide.load.model.stream.StreamModelLoader;
|
import com.bumptech.glide.load.model.MultiModelLoaderFactory;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
|
||||||
import org.thoughtcrime.securesms.mms.AttachmentStreamUriLoader.AttachmentModel;
|
import org.thoughtcrime.securesms.mms.AttachmentStreamUriLoader.AttachmentModel;
|
||||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
|
|
||||||
import org.thoughtcrime.securesms.util.SaveAttachmentTask.Attachment;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
|
||||||
/**
|
public class AttachmentStreamUriLoader implements ModelLoader<AttachmentModel, InputStream> {
|
||||||
* A {@link ModelLoader} for translating uri models into {@link InputStream} data. Capable of handling 'http',
|
|
||||||
* 'https', 'android.resource', 'content', and 'file' schemes. Unsupported schemes will throw an exception in
|
|
||||||
* {@link #getResourceFetcher(Uri, int, int)}.
|
|
||||||
*/
|
|
||||||
public class AttachmentStreamUriLoader implements StreamModelLoader<AttachmentModel> {
|
|
||||||
private final Context context;
|
|
||||||
|
|
||||||
/**
|
@Nullable
|
||||||
* THe default factory for {@link com.bumptech.glide.load.model.stream.StreamUriLoader}s.
|
@Override
|
||||||
*/
|
public LoadData<InputStream> buildLoadData(AttachmentModel attachmentModel, int width, int height, Options options) {
|
||||||
public static class Factory implements ModelLoaderFactory<AttachmentModel, InputStream> {
|
return new LoadData<>(attachmentModel, new AttachmentStreamLocalUriFetcher(attachmentModel.attachment, attachmentModel.key));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handles(AttachmentModel attachmentModel) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Factory implements ModelLoaderFactory<AttachmentModel, InputStream> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StreamModelLoader<AttachmentModel> build(Context context, GenericLoaderFactory factories) {
|
public ModelLoader<AttachmentModel, InputStream> build(MultiModelLoaderFactory multiFactory) {
|
||||||
return new AttachmentStreamUriLoader(context);
|
return new AttachmentStreamUriLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -42,16 +41,7 @@ public class AttachmentStreamUriLoader implements StreamModelLoader<AttachmentMo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public AttachmentStreamUriLoader(Context context) {
|
public static class AttachmentModel implements Key {
|
||||||
this.context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DataFetcher<InputStream> getResourceFetcher(AttachmentModel model, int width, int height) {
|
|
||||||
return new AttachmentStreamLocalUriFetcher(model.attachment, model.key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class AttachmentModel {
|
|
||||||
public @NonNull File attachment;
|
public @NonNull File attachment;
|
||||||
public @NonNull byte[] key;
|
public @NonNull byte[] key;
|
||||||
|
|
||||||
@ -60,6 +50,11 @@ public class AttachmentStreamUriLoader implements StreamModelLoader<AttachmentMo
|
|||||||
this.key = key;
|
this.key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateDiskCacheKey(MessageDigest messageDigest) {
|
||||||
|
messageDigest.update(attachment.toString().getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
|
@ -12,11 +12,12 @@ import com.bumptech.glide.load.data.StreamLocalUriFetcher;
|
|||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
public class ContactPhotoLocalUriFetcher extends StreamLocalUriFetcher {
|
class ContactPhotoLocalUriFetcher extends StreamLocalUriFetcher {
|
||||||
|
|
||||||
private static final String TAG = ContactPhotoLocalUriFetcher.class.getSimpleName();
|
private static final String TAG = ContactPhotoLocalUriFetcher.class.getSimpleName();
|
||||||
|
|
||||||
public ContactPhotoLocalUriFetcher(Context context, Uri uri) {
|
ContactPhotoLocalUriFetcher(Context context, Uri uri) {
|
||||||
super(context, uri);
|
super(context.getContentResolver(), uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -3,26 +3,49 @@ package org.thoughtcrime.securesms.mms;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import com.bumptech.glide.load.data.DataFetcher;
|
import com.bumptech.glide.load.Key;
|
||||||
import com.bumptech.glide.load.model.GenericLoaderFactory;
|
import com.bumptech.glide.load.Options;
|
||||||
|
import com.bumptech.glide.load.data.StreamLocalUriFetcher;
|
||||||
|
import com.bumptech.glide.load.model.ModelLoader;
|
||||||
import com.bumptech.glide.load.model.ModelLoaderFactory;
|
import com.bumptech.glide.load.model.ModelLoaderFactory;
|
||||||
import com.bumptech.glide.load.model.stream.StreamModelLoader;
|
import com.bumptech.glide.load.model.MultiModelLoaderFactory;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.mms.ContactPhotoUriLoader.ContactPhotoUri;
|
import org.thoughtcrime.securesms.mms.ContactPhotoUriLoader.ContactPhotoUri;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
|
||||||
|
public class ContactPhotoUriLoader implements ModelLoader<ContactPhotoUri, InputStream> {
|
||||||
|
|
||||||
public class ContactPhotoUriLoader implements StreamModelLoader<ContactPhotoUri> {
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
|
|
||||||
/**
|
private ContactPhotoUriLoader(Context context) {
|
||||||
* THe default factory for {@link com.bumptech.glide.load.model.stream.StreamUriLoader}s.
|
this.context = context;
|
||||||
*/
|
}
|
||||||
public static class Factory implements ModelLoaderFactory<ContactPhotoUri, InputStream> {
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public LoadData<InputStream> buildLoadData(ContactPhotoUri contactPhotoUri, int width, int height, Options options) {
|
||||||
|
return new LoadData<>(contactPhotoUri, new StreamLocalUriFetcher(context.getContentResolver(), contactPhotoUri.uri));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handles(ContactPhotoUri contactPhotoUri) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Factory implements ModelLoaderFactory<ContactPhotoUri, InputStream> {
|
||||||
|
|
||||||
|
private final Context context;
|
||||||
|
|
||||||
|
Factory(Context context) {
|
||||||
|
this.context = context.getApplicationContext();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StreamModelLoader<ContactPhotoUri> build(Context context, GenericLoaderFactory factories) {
|
public ModelLoader<ContactPhotoUri, InputStream> build(MultiModelLoaderFactory multiFactory) {
|
||||||
return new ContactPhotoUriLoader(context);
|
return new ContactPhotoUriLoader(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,21 +55,28 @@ public class ContactPhotoUriLoader implements StreamModelLoader<ContactPhotoUri>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ContactPhotoUriLoader(Context context) {
|
public static class ContactPhotoUri implements Key {
|
||||||
this.context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DataFetcher<InputStream> getResourceFetcher(ContactPhotoUri model, int width, int height) {
|
|
||||||
return new ContactPhotoLocalUriFetcher(context, model.uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ContactPhotoUri {
|
|
||||||
public @NonNull Uri uri;
|
public @NonNull Uri uri;
|
||||||
|
|
||||||
public ContactPhotoUri(@NonNull Uri uri) {
|
public ContactPhotoUri(@NonNull Uri uri) {
|
||||||
this.uri = uri;
|
this.uri = uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateDiskCacheKey(MessageDigest messageDigest) {
|
||||||
|
messageDigest.update(uri.toString().getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object other) {
|
||||||
|
if (other == null || !(other instanceof ContactPhotoUri)) return false;
|
||||||
|
|
||||||
|
return this.uri.equals(((ContactPhotoUri)other).uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
return uri.hashCode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,15 +17,15 @@ import java.io.FileNotFoundException;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
public class DecryptableStreamLocalUriFetcher extends StreamLocalUriFetcher {
|
class DecryptableStreamLocalUriFetcher extends StreamLocalUriFetcher {
|
||||||
|
|
||||||
private static final String TAG = DecryptableStreamLocalUriFetcher.class.getSimpleName();
|
private static final String TAG = DecryptableStreamLocalUriFetcher.class.getSimpleName();
|
||||||
|
|
||||||
private Context context;
|
private Context context;
|
||||||
private MasterSecret masterSecret;
|
private MasterSecret masterSecret;
|
||||||
|
|
||||||
public DecryptableStreamLocalUriFetcher(Context context, MasterSecret masterSecret, Uri uri) {
|
DecryptableStreamLocalUriFetcher(Context context, MasterSecret masterSecret, Uri uri) {
|
||||||
super(context, uri);
|
super(context.getContentResolver(), uri);
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.masterSecret = masterSecret;
|
this.masterSecret = masterSecret;
|
||||||
}
|
}
|
||||||
|
@ -3,33 +3,49 @@ package org.thoughtcrime.securesms.mms;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import com.bumptech.glide.load.data.DataFetcher;
|
import com.bumptech.glide.load.Key;
|
||||||
import com.bumptech.glide.load.model.GenericLoaderFactory;
|
import com.bumptech.glide.load.Options;
|
||||||
import com.bumptech.glide.load.model.ModelLoader;
|
import com.bumptech.glide.load.model.ModelLoader;
|
||||||
import com.bumptech.glide.load.model.ModelLoaderFactory;
|
import com.bumptech.glide.load.model.ModelLoaderFactory;
|
||||||
import com.bumptech.glide.load.model.stream.StreamModelLoader;
|
import com.bumptech.glide.load.model.MultiModelLoaderFactory;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
|
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
|
||||||
|
public class DecryptableStreamUriLoader implements ModelLoader<DecryptableUri, InputStream> {
|
||||||
|
|
||||||
/**
|
|
||||||
* A {@link ModelLoader} for translating uri models into {@link InputStream} data. Capable of handling 'http',
|
|
||||||
* 'https', 'android.resource', 'content', and 'file' schemes. Unsupported schemes will throw an exception in
|
|
||||||
* {@link #getResourceFetcher(Uri, int, int)}.
|
|
||||||
*/
|
|
||||||
public class DecryptableStreamUriLoader implements StreamModelLoader<DecryptableUri> {
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
|
|
||||||
/**
|
private DecryptableStreamUriLoader(Context context) {
|
||||||
* THe default factory for {@link com.bumptech.glide.load.model.stream.StreamUriLoader}s.
|
this.context = context;
|
||||||
*/
|
}
|
||||||
public static class Factory implements ModelLoaderFactory<DecryptableUri, InputStream> {
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public LoadData<InputStream> buildLoadData(DecryptableUri decryptableUri, int width, int height, Options options) {
|
||||||
|
return new LoadData<>(decryptableUri, new DecryptableStreamLocalUriFetcher(context, decryptableUri.masterSecret, decryptableUri.uri));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handles(DecryptableUri decryptableUri) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Factory implements ModelLoaderFactory<DecryptableUri, InputStream> {
|
||||||
|
|
||||||
|
private final Context context;
|
||||||
|
|
||||||
|
Factory(Context context) {
|
||||||
|
this.context = context.getApplicationContext();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StreamModelLoader<DecryptableUri> build(Context context, GenericLoaderFactory factories) {
|
public ModelLoader<DecryptableUri, InputStream> build(MultiModelLoaderFactory multiFactory) {
|
||||||
return new DecryptableStreamUriLoader(context);
|
return new DecryptableStreamUriLoader(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,16 +55,7 @@ public class DecryptableStreamUriLoader implements StreamModelLoader<Decryptable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DecryptableStreamUriLoader(Context context) {
|
public static class DecryptableUri implements Key {
|
||||||
this.context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DataFetcher<InputStream> getResourceFetcher(DecryptableUri model, int width, int height) {
|
|
||||||
return new DecryptableStreamLocalUriFetcher(context, model.masterSecret, model.uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class DecryptableUri {
|
|
||||||
public @NonNull MasterSecret masterSecret;
|
public @NonNull MasterSecret masterSecret;
|
||||||
public @NonNull Uri uri;
|
public @NonNull Uri uri;
|
||||||
|
|
||||||
@ -57,6 +64,11 @@ public class DecryptableStreamUriLoader implements StreamModelLoader<Decryptable
|
|||||||
this.uri = uri;
|
this.uri = uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateDiskCacheKey(MessageDigest messageDigest) {
|
||||||
|
messageDigest.update(uri.toString().getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
|
@ -37,7 +37,6 @@ import org.apache.http.impl.client.LaxRedirectStrategy;
|
|||||||
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
|
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
|
||||||
import org.apache.http.message.BasicHeader;
|
import org.apache.http.message.BasicHeader;
|
||||||
import org.thoughtcrime.securesms.database.ApnDatabase;
|
import org.thoughtcrime.securesms.database.ApnDatabase;
|
||||||
import org.thoughtcrime.securesms.util.Conversions;
|
|
||||||
import org.thoughtcrime.securesms.util.ServiceUtil;
|
import org.thoughtcrime.securesms.util.ServiceUtil;
|
||||||
import org.thoughtcrime.securesms.util.TelephonyUtil;
|
import org.thoughtcrime.securesms.util.TelephonyUtil;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
@ -130,6 +129,7 @@ public abstract class LegacyMmsConnection {
|
|||||||
|
|
||||||
Log.w(TAG, "Checking route to address: " + host + ", " + inetAddress.getHostAddress());
|
Log.w(TAG, "Checking route to address: " + host + ", " + inetAddress.getHostAddress());
|
||||||
ConnectivityManager manager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
ConnectivityManager manager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final Method requestRouteMethod = manager.getClass().getMethod("requestRouteToHostAddress", Integer.TYPE, InetAddress.class);
|
final Method requestRouteMethod = manager.getClass().getMethod("requestRouteToHostAddress", Integer.TYPE, InetAddress.class);
|
||||||
final boolean routeToHostObtained = (Boolean) requestRouteMethod.invoke(manager, MmsRadio.TYPE_MOBILE_MMS, inetAddress);
|
final boolean routeToHostObtained = (Boolean) requestRouteMethod.invoke(manager, MmsRadio.TYPE_MOBILE_MMS, inetAddress);
|
||||||
@ -143,10 +143,7 @@ public abstract class LegacyMmsConnection {
|
|||||||
Log.w(TAG, ite);
|
Log.w(TAG, ite);
|
||||||
}
|
}
|
||||||
|
|
||||||
final int ipAddress = Conversions.byteArrayToIntLittleEndian(ipAddressBytes, 0);
|
return false;
|
||||||
final boolean routeToHostObtained = manager.requestRouteToHost(MmsRadio.TYPE_MOBILE_MMS, ipAddress);
|
|
||||||
Log.w(TAG, "requestRouteToHost(" + ipAddress + ") -> " + routeToHostObtained);
|
|
||||||
return routeToHostObtained;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static byte[] parseResponse(InputStream is) throws IOException {
|
protected static byte[] parseResponse(InputStream is) throws IOException {
|
||||||
|
@ -11,8 +11,13 @@ import android.util.Log;
|
|||||||
|
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
public class MmsRadio {
|
public class MmsRadio {
|
||||||
|
|
||||||
|
private static final String TAG = MmsRadio.class.getSimpleName();
|
||||||
|
|
||||||
private static MmsRadio instance;
|
private static MmsRadio instance;
|
||||||
|
|
||||||
public static synchronized MmsRadio getInstance(Context context) {
|
public static synchronized MmsRadio getInstance(Context context) {
|
||||||
@ -52,7 +57,16 @@ public class MmsRadio {
|
|||||||
|
|
||||||
if (connectedCounter == 0) {
|
if (connectedCounter == 0) {
|
||||||
Log.w("MmsRadio", "Turning off MMS radio...");
|
Log.w("MmsRadio", "Turning off MMS radio...");
|
||||||
connectivityManager.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, FEATURE_ENABLE_MMS);
|
try {
|
||||||
|
final Method stopUsingNetworkFeatureMethod = connectivityManager.getClass().getMethod("stopUsingNetworkFeature", Integer.TYPE, String.class);
|
||||||
|
stopUsingNetworkFeatureMethod.invoke(connectivityManager, ConnectivityManager.TYPE_MOBILE, FEATURE_ENABLE_MMS);
|
||||||
|
} catch (NoSuchMethodException nsme) {
|
||||||
|
Log.w(TAG, nsme);
|
||||||
|
} catch (IllegalAccessException iae) {
|
||||||
|
Log.w(TAG, iae);
|
||||||
|
} catch (InvocationTargetException ite) {
|
||||||
|
Log.w(TAG, ite);
|
||||||
|
}
|
||||||
|
|
||||||
if (connectivityListener != null) {
|
if (connectivityListener != null) {
|
||||||
Log.w("MmsRadio", "Unregistering receiver...");
|
Log.w("MmsRadio", "Unregistering receiver...");
|
||||||
@ -63,8 +77,18 @@ public class MmsRadio {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void connect() throws MmsRadioException {
|
public synchronized void connect() throws MmsRadioException {
|
||||||
int status = connectivityManager.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
|
int status;
|
||||||
FEATURE_ENABLE_MMS);
|
|
||||||
|
try {
|
||||||
|
final Method startUsingNetworkFeatureMethod = connectivityManager.getClass().getMethod("startUsingNetworkFeature", Integer.TYPE, String.class);
|
||||||
|
status = (int)startUsingNetworkFeatureMethod.invoke(connectivityManager, ConnectivityManager.TYPE_MOBILE, FEATURE_ENABLE_MMS);
|
||||||
|
} catch (NoSuchMethodException nsme) {
|
||||||
|
throw new MmsRadioException(nsme);
|
||||||
|
} catch (IllegalAccessException iae) {
|
||||||
|
throw new MmsRadioException(iae);
|
||||||
|
} catch (InvocationTargetException ite) {
|
||||||
|
throw new MmsRadioException(ite);
|
||||||
|
}
|
||||||
|
|
||||||
Log.w("MmsRadio", "startUsingNetworkFeature status: " + status);
|
Log.w("MmsRadio", "startUsingNetworkFeature status: " + status);
|
||||||
|
|
||||||
|
@ -4,4 +4,8 @@ public class MmsRadioException extends Throwable {
|
|||||||
public MmsRadioException(String s) {
|
public MmsRadioException(String s) {
|
||||||
super(s);
|
super(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MmsRadioException(Exception e) {
|
||||||
|
super(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,105 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.mms;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.Bitmap.Config;
|
|
||||||
import android.graphics.BitmapShader;
|
|
||||||
import android.graphics.Canvas;
|
|
||||||
import android.graphics.Paint;
|
|
||||||
import android.graphics.RectF;
|
|
||||||
import android.graphics.Shader.TileMode;
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
|
|
||||||
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
|
|
||||||
import com.bumptech.glide.load.resource.bitmap.TransformationUtils;
|
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.util.ResUtil;
|
|
||||||
|
|
||||||
public class RoundedCorners extends BitmapTransformation {
|
|
||||||
private final boolean crop;
|
|
||||||
private final int radius;
|
|
||||||
private final int colorHint;
|
|
||||||
|
|
||||||
public RoundedCorners(@NonNull Context context, boolean crop, int radius, int colorHint) {
|
|
||||||
super(context);
|
|
||||||
this.crop = crop;
|
|
||||||
this.radius = radius;
|
|
||||||
this.colorHint = colorHint;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RoundedCorners(@NonNull Context context, int radius) {
|
|
||||||
this(context, true, radius, ResUtil.getColor(context, android.R.attr.windowBackground));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth,
|
|
||||||
int outHeight)
|
|
||||||
{
|
|
||||||
final Bitmap toRound = crop ? centerCrop(pool, toTransform, outWidth, outHeight)
|
|
||||||
: fitCenter(pool, toTransform, outWidth, outHeight);
|
|
||||||
|
|
||||||
final Bitmap rounded = round(pool, toRound);
|
|
||||||
|
|
||||||
if (toRound != null && toRound != rounded && toRound != toTransform && !pool.put(toRound)) {
|
|
||||||
toRound.recycle();
|
|
||||||
}
|
|
||||||
|
|
||||||
return rounded;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Bitmap centerCrop(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
|
|
||||||
final Bitmap toReuse = pool.get(outWidth, outHeight, getSafeConfig(toTransform));
|
|
||||||
final Bitmap transformed = TransformationUtils.centerCrop(toReuse, toTransform, outWidth, outHeight);
|
|
||||||
|
|
||||||
if (toReuse != null && toReuse != transformed && !pool.put(toReuse)) {
|
|
||||||
toReuse.recycle();
|
|
||||||
}
|
|
||||||
|
|
||||||
return transformed;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Bitmap fitCenter(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
|
|
||||||
return TransformationUtils.fitCenter(toTransform, pool, outWidth, outHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Bitmap round(@NonNull BitmapPool pool, @Nullable Bitmap toRound) {
|
|
||||||
if (toRound == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Bitmap result = pool.get(toRound.getWidth(), toRound.getHeight(), getSafeConfig(toRound));
|
|
||||||
|
|
||||||
if (result == null) {
|
|
||||||
result = Bitmap.createBitmap(toRound.getWidth(), toRound.getHeight(), getSafeConfig(toRound));
|
|
||||||
}
|
|
||||||
|
|
||||||
Canvas canvas = new Canvas(result);
|
|
||||||
|
|
||||||
if (Config.RGB_565.equals(result.getConfig())) {
|
|
||||||
Paint cornerPaint = new Paint();
|
|
||||||
cornerPaint.setColor(colorHint);
|
|
||||||
|
|
||||||
canvas.drawRect(0, 0, radius, radius, cornerPaint);
|
|
||||||
canvas.drawRect(0, toRound.getHeight() - radius, radius, toRound.getHeight(), cornerPaint);
|
|
||||||
canvas.drawRect(toRound.getWidth() - radius, 0, toRound.getWidth(), radius, cornerPaint);
|
|
||||||
canvas.drawRect(toRound.getWidth() - radius, toRound.getHeight() - radius, toRound.getWidth(), toRound.getHeight(), cornerPaint);
|
|
||||||
}
|
|
||||||
|
|
||||||
Paint shaderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
||||||
shaderPaint.setShader(new BitmapShader(toRound, TileMode.CLAMP, TileMode.CLAMP));
|
|
||||||
|
|
||||||
canvas.drawRoundRect(new RectF(0, 0, toRound.getWidth(), toRound.getHeight()), radius, radius, shaderPaint);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Bitmap.Config getSafeConfig(Bitmap bitmap) {
|
|
||||||
return bitmap.getConfig() != null ? bitmap.getConfig() : Bitmap.Config.ARGB_8888;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return RoundedCorners.class.getCanonicalName();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +1,16 @@
|
|||||||
package org.thoughtcrime.securesms.mms;
|
package org.thoughtcrime.securesms.mms;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
import com.bumptech.glide.Glide;
|
||||||
import com.bumptech.glide.GlideBuilder;
|
import com.bumptech.glide.GlideBuilder;
|
||||||
|
import com.bumptech.glide.Registry;
|
||||||
|
import com.bumptech.glide.annotation.GlideModule;
|
||||||
import com.bumptech.glide.load.engine.cache.DiskCache;
|
import com.bumptech.glide.load.engine.cache.DiskCache;
|
||||||
import com.bumptech.glide.load.engine.cache.DiskCacheAdapter;
|
import com.bumptech.glide.load.engine.cache.DiskCacheAdapter;
|
||||||
import com.bumptech.glide.load.model.GlideUrl;
|
import com.bumptech.glide.load.model.GlideUrl;
|
||||||
import com.bumptech.glide.module.GlideModule;
|
import com.bumptech.glide.module.AppGlideModule;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.glide.OkHttpUrlLoader;
|
import org.thoughtcrime.securesms.glide.OkHttpUrlLoader;
|
||||||
import org.thoughtcrime.securesms.mms.AttachmentStreamUriLoader.AttachmentModel;
|
import org.thoughtcrime.securesms.mms.AttachmentStreamUriLoader.AttachmentModel;
|
||||||
@ -18,19 +21,27 @@ import org.thoughtcrime.securesms.profiles.AvatarPhotoUriLoader.AvatarPhotoUri;
|
|||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
public class TextSecureGlideModule implements GlideModule {
|
@GlideModule
|
||||||
|
public class SignalGlideModule extends AppGlideModule {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isManifestParsingEnabled() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void applyOptions(Context context, GlideBuilder builder) {
|
public void applyOptions(Context context, GlideBuilder builder) {
|
||||||
|
builder.setLogLevel(Log.ERROR);
|
||||||
// builder.setDiskCache(new NoopDiskCacheFactory());
|
// builder.setDiskCache(new NoopDiskCacheFactory());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerComponents(Context context, Glide glide) {
|
public void registerComponents(Context context, Glide glide, Registry registry) {
|
||||||
glide.register(DecryptableUri.class, InputStream.class, new DecryptableStreamUriLoader.Factory());
|
registry.append(DecryptableUri.class, InputStream.class, new DecryptableStreamUriLoader.Factory(context));
|
||||||
glide.register(ContactPhotoUri.class, InputStream.class, new ContactPhotoUriLoader.Factory());
|
registry.append(ContactPhotoUri.class, InputStream.class, new ContactPhotoUriLoader.Factory(context));
|
||||||
glide.register(AttachmentModel.class, InputStream.class, new AttachmentStreamUriLoader.Factory());
|
registry.append(AttachmentModel.class, InputStream.class, new AttachmentStreamUriLoader.Factory());
|
||||||
glide.register(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory());
|
registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory());
|
||||||
glide.register(AvatarPhotoUri.class, InputStream.class, new AvatarPhotoUriLoader.Factory());
|
registry.append(AvatarPhotoUri.class, InputStream.class, new AvatarPhotoUriLoader.Factory(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class NoopDiskCacheFactory implements DiskCache.Factory {
|
public static class NoopDiskCacheFactory implements DiskCache.Factory {
|
@ -14,7 +14,6 @@ import android.support.v4.app.NotificationCompat.Action;
|
|||||||
import android.support.v4.app.RemoteInput;
|
import android.support.v4.app.RemoteInput;
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
@ -22,6 +21,7 @@ import org.thoughtcrime.securesms.contacts.avatars.ContactColors;
|
|||||||
import org.thoughtcrime.securesms.contacts.avatars.ContactPhotoFactory;
|
import org.thoughtcrime.securesms.contacts.avatars.ContactPhotoFactory;
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
|
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
|
||||||
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||||
import org.thoughtcrime.securesms.mms.Slide;
|
import org.thoughtcrime.securesms.mms.Slide;
|
||||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||||
import org.thoughtcrime.securesms.preferences.widgets.NotificationPrivacyPreference;
|
import org.thoughtcrime.securesms.preferences.widgets.NotificationPrivacyPreference;
|
||||||
@ -225,12 +225,12 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil
|
|||||||
@SuppressWarnings("ConstantConditions")
|
@SuppressWarnings("ConstantConditions")
|
||||||
Uri uri = slideDeck.getThumbnailSlide().getThumbnailUri();
|
Uri uri = slideDeck.getThumbnailSlide().getThumbnailUri();
|
||||||
|
|
||||||
return Glide.with(context)
|
return GlideApp.with(context)
|
||||||
.load(new DecryptableStreamUriLoader.DecryptableUri(masterSecret, uri))
|
.asBitmap()
|
||||||
.asBitmap()
|
.load(new DecryptableStreamUriLoader.DecryptableUri(masterSecret, uri))
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
.into(500, 500)
|
.submit(500, 500)
|
||||||
.get();
|
.get();
|
||||||
} catch (InterruptedException | ExecutionException e) {
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
throw new AssertionError(e);
|
throw new AssertionError(e);
|
||||||
}
|
}
|
||||||
|
@ -5,32 +5,34 @@ import android.content.Context;
|
|||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
import com.bumptech.glide.Priority;
|
import com.bumptech.glide.Priority;
|
||||||
|
import com.bumptech.glide.load.DataSource;
|
||||||
import com.bumptech.glide.load.data.DataFetcher;
|
import com.bumptech.glide.load.data.DataFetcher;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.database.Address;
|
import org.thoughtcrime.securesms.database.Address;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
public class AvatarPhotoUriFetcher implements DataFetcher<InputStream> {
|
class AvatarPhotoUriFetcher implements DataFetcher<InputStream> {
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final Address address;
|
private final Address address;
|
||||||
|
|
||||||
private InputStream inputStream;
|
private InputStream inputStream;
|
||||||
|
|
||||||
public AvatarPhotoUriFetcher(@NonNull Context context, @NonNull Address address) {
|
AvatarPhotoUriFetcher(@NonNull Context context, @NonNull Address address) {
|
||||||
this.context = context.getApplicationContext();
|
this.context = context.getApplicationContext();
|
||||||
this.address = address;
|
this.address = address;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InputStream loadData(Priority priority) throws IOException {
|
public void loadData(Priority priority, DataCallback<? super InputStream> callback) {
|
||||||
inputStream = AvatarHelper.getInputStreamFor(context, address);
|
try {
|
||||||
return inputStream;
|
inputStream = AvatarHelper.getInputStreamFor(context, address);
|
||||||
|
callback.onDataReady(inputStream);
|
||||||
|
} catch (IOException e) {
|
||||||
|
callback.onLoadFailed(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -40,13 +42,20 @@ public class AvatarPhotoUriFetcher implements DataFetcher<InputStream> {
|
|||||||
} catch (IOException e) {}
|
} catch (IOException e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return address.serialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cancel() {
|
public void cancel() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Class<InputStream> getDataClass() {
|
||||||
|
return InputStream.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public DataSource getDataSource() {
|
||||||
|
return DataSource.LOCAL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,24 +3,48 @@ package org.thoughtcrime.securesms.profiles;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import com.bumptech.glide.load.data.DataFetcher;
|
import com.bumptech.glide.load.Key;
|
||||||
import com.bumptech.glide.load.model.GenericLoaderFactory;
|
import com.bumptech.glide.load.Options;
|
||||||
|
import com.bumptech.glide.load.model.ModelLoader;
|
||||||
import com.bumptech.glide.load.model.ModelLoaderFactory;
|
import com.bumptech.glide.load.model.ModelLoaderFactory;
|
||||||
import com.bumptech.glide.load.model.stream.StreamModelLoader;
|
import com.bumptech.glide.load.model.MultiModelLoaderFactory;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.database.Address;
|
import org.thoughtcrime.securesms.database.Address;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
|
||||||
public class AvatarPhotoUriLoader implements StreamModelLoader<AvatarPhotoUriLoader.AvatarPhotoUri> {
|
public class AvatarPhotoUriLoader implements ModelLoader<AvatarPhotoUriLoader.AvatarPhotoUri, InputStream> {
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
|
|
||||||
|
private AvatarPhotoUriLoader(Context context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public LoadData<InputStream> buildLoadData(AvatarPhotoUri avatarPhotoUri, int width, int height, Options options) {
|
||||||
|
return new LoadData<>(avatarPhotoUri, new AvatarPhotoUriFetcher(context, avatarPhotoUri.address));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handles(AvatarPhotoUri avatarPhotoUri) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public static class Factory implements ModelLoaderFactory<AvatarPhotoUri, InputStream> {
|
public static class Factory implements ModelLoaderFactory<AvatarPhotoUri, InputStream> {
|
||||||
|
|
||||||
|
private final Context context;
|
||||||
|
|
||||||
|
public Factory(Context context) {
|
||||||
|
this.context = context.getApplicationContext();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StreamModelLoader<AvatarPhotoUri> build(Context context, GenericLoaderFactory factories) {
|
public ModelLoader<AvatarPhotoUri, InputStream> build(MultiModelLoaderFactory multiFactory) {
|
||||||
return new AvatarPhotoUriLoader(context);
|
return new AvatarPhotoUriLoader(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,21 +52,29 @@ public class AvatarPhotoUriLoader implements StreamModelLoader<AvatarPhotoUriLoa
|
|||||||
public void teardown() {}
|
public void teardown() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
public AvatarPhotoUriLoader(Context context) {
|
public static class AvatarPhotoUri implements Key {
|
||||||
this.context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DataFetcher<InputStream> getResourceFetcher(AvatarPhotoUri model, int width, int height) {
|
|
||||||
return new AvatarPhotoUriFetcher(context, model.address);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class AvatarPhotoUri {
|
|
||||||
public @NonNull Address address;
|
public @NonNull Address address;
|
||||||
|
|
||||||
public AvatarPhotoUri(@NonNull Address address) {
|
public AvatarPhotoUri(@NonNull Address address) {
|
||||||
this.address = address;
|
this.address = address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateDiskCacheKey(MessageDigest messageDigest) {
|
||||||
|
messageDigest.update(address.serialize().getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object other) {
|
||||||
|
if (other == null || !(other instanceof AvatarPhotoUri)) return false;
|
||||||
|
|
||||||
|
return this.address.equals(((AvatarPhotoUri)other).address);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return address.hashCode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/**
|
/*
|
||||||
* Copyright (C) 2016 Open Whisper Systems
|
* Copyright (C) 2016 Open Whisper Systems
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
@ -31,10 +31,10 @@ import android.view.View;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||||
|
|
||||||
public class StickerSelectFragment extends Fragment implements LoaderManager.LoaderCallbacks<String[]> {
|
public class StickerSelectFragment extends Fragment implements LoaderManager.LoaderCallbacks<String[]> {
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ public class StickerSelectFragment extends Fragment implements LoaderManager.Loa
|
|||||||
@Nullable Bundle savedInstanceState)
|
@Nullable Bundle savedInstanceState)
|
||||||
{
|
{
|
||||||
View view = inflater.inflate(R.layout.scribble_select_sticker_fragment, container, false);
|
View view = inflater.inflate(R.layout.scribble_select_sticker_fragment, container, false);
|
||||||
this.recyclerView = (RecyclerView)view.findViewById(R.id.stickers_recycler_view);
|
this.recyclerView = view.findViewById(R.id.stickers_recycler_view);
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
@ -113,10 +113,10 @@ public class StickerSelectFragment extends Fragment implements LoaderManager.Loa
|
|||||||
public void onBindViewHolder(StickerViewHolder holder, int position) {
|
public void onBindViewHolder(StickerViewHolder holder, int position) {
|
||||||
holder.fileName = stickerFiles[position];
|
holder.fileName = stickerFiles[position];
|
||||||
|
|
||||||
Glide.with(context)
|
GlideApp.with(context)
|
||||||
.load(Uri.parse("file:///android_asset/" + holder.fileName))
|
.load(Uri.parse("file:///android_asset/" + holder.fileName))
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
.into(holder.image);
|
.into(holder.image);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -127,7 +127,7 @@ public class StickerSelectFragment extends Fragment implements LoaderManager.Loa
|
|||||||
@Override
|
@Override
|
||||||
public void onViewRecycled(StickerViewHolder holder) {
|
public void onViewRecycled(StickerViewHolder holder) {
|
||||||
super.onViewRecycled(holder);
|
super.onViewRecycled(holder);
|
||||||
Glide.clear(holder.image);
|
GlideApp.with(context).clear(holder.image);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onStickerSelected(String fileName) {
|
private void onStickerSelected(String fileName) {
|
||||||
@ -141,22 +141,19 @@ public class StickerSelectFragment extends Fragment implements LoaderManager.Loa
|
|||||||
|
|
||||||
StickerViewHolder(View itemView) {
|
StickerViewHolder(View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
image = (ImageView) itemView.findViewById(R.id.sticker_image);
|
image = itemView.findViewById(R.id.sticker_image);
|
||||||
itemView.setOnClickListener(new View.OnClickListener() {
|
itemView.setOnClickListener(view -> {
|
||||||
@Override
|
int pos = getAdapterPosition();
|
||||||
public void onClick(View view) {
|
if (pos >= 0) {
|
||||||
int pos = getAdapterPosition();
|
onStickerSelected(fileName);
|
||||||
if (pos >= 0) {
|
|
||||||
onStickerSelected(fileName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface StickerSelectionListener {
|
interface StickerSelectionListener {
|
||||||
public void onStickerSelected(String name);
|
void onStickerSelected(String name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,13 +30,13 @@ import android.util.Log;
|
|||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||||
import com.bumptech.glide.request.target.Target;
|
import com.bumptech.glide.request.target.Target;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
|
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
|
||||||
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||||
import org.thoughtcrime.securesms.scribbles.widget.entity.MotionEntity;
|
import org.thoughtcrime.securesms.scribbles.widget.entity.MotionEntity;
|
||||||
import org.thoughtcrime.securesms.scribbles.widget.entity.TextEntity;
|
import org.thoughtcrime.securesms.scribbles.widget.entity.TextEntity;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
@ -81,11 +81,11 @@ public class ScribbleView extends FrameLayout {
|
|||||||
this.imageUri = uri;
|
this.imageUri = uri;
|
||||||
this.masterSecret = masterSecret;
|
this.masterSecret = masterSecret;
|
||||||
|
|
||||||
Glide.with(getContext())
|
GlideApp.with(getContext())
|
||||||
.load(new DecryptableUri(masterSecret, uri))
|
.load(new DecryptableUri(masterSecret, uri))
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
.fitCenter()
|
.fitCenter()
|
||||||
.into(imageView);
|
.into(imageView);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NonNull ListenableFuture<Bitmap> getRenderedImage() {
|
public @NonNull ListenableFuture<Bitmap> getRenderedImage() {
|
||||||
@ -110,13 +110,13 @@ public class ScribbleView extends FrameLayout {
|
|||||||
height = 768;
|
height = 768;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Glide.with(context)
|
return GlideApp.with(context)
|
||||||
.load(new DecryptableUri(masterSecret, imageUri))
|
.asBitmap()
|
||||||
.asBitmap()
|
.load(new DecryptableUri(masterSecret, imageUri))
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
.skipMemoryCache(true)
|
.skipMemoryCache(true)
|
||||||
.into(width, height)
|
.into(width, height)
|
||||||
.get();
|
.get();
|
||||||
} catch (InterruptedException | ExecutionException e) {
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
Log.w(TAG, e);
|
Log.w(TAG, e);
|
||||||
return null;
|
return null;
|
||||||
|
@ -15,14 +15,9 @@ import android.support.annotation.Nullable;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy;
|
||||||
import com.bumptech.glide.Priority;
|
|
||||||
import com.bumptech.glide.load.DecodeFormat;
|
|
||||||
import com.bumptech.glide.load.engine.Resource;
|
|
||||||
import com.bumptech.glide.load.resource.bitmap.BitmapResource;
|
|
||||||
import com.bumptech.glide.load.resource.bitmap.Downsampler;
|
|
||||||
import com.bumptech.glide.load.resource.bitmap.FitCenter;
|
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||||
import org.thoughtcrime.securesms.mms.MediaConstraints;
|
import org.thoughtcrime.securesms.mms.MediaConstraints;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
@ -30,6 +25,7 @@ import java.io.ByteArrayInputStream;
|
|||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
import javax.microedition.khronos.egl.EGL10;
|
import javax.microedition.khronos.egl.EGL10;
|
||||||
@ -49,90 +45,80 @@ public class BitmapUtil {
|
|||||||
public static <T> byte[] createScaledBytes(Context context, T model, MediaConstraints constraints)
|
public static <T> byte[] createScaledBytes(Context context, T model, MediaConstraints constraints)
|
||||||
throws BitmapDecodingException
|
throws BitmapDecodingException
|
||||||
{
|
{
|
||||||
int quality = MAX_COMPRESSION_QUALITY;
|
|
||||||
int attempts = 0;
|
|
||||||
byte[] bytes;
|
|
||||||
|
|
||||||
Bitmap scaledBitmap = Downsampler.AT_MOST.decode(getInputStreamForModel(context, model),
|
|
||||||
Glide.get(context).getBitmapPool(),
|
|
||||||
constraints.getImageMaxWidth(context),
|
|
||||||
constraints.getImageMaxHeight(context),
|
|
||||||
DecodeFormat.PREFER_RGB_565);
|
|
||||||
|
|
||||||
if (scaledBitmap == null) {
|
|
||||||
throw new BitmapDecodingException("Unable to decode image");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
do {
|
int quality = MAX_COMPRESSION_QUALITY;
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
int attempts = 0;
|
||||||
scaledBitmap.compress(CompressFormat.JPEG, quality, baos);
|
byte[] bytes;
|
||||||
bytes = baos.toByteArray();
|
|
||||||
|
|
||||||
Log.w(TAG, "iteration with quality " + quality + " size " + (bytes.length / 1024) + "kb");
|
Bitmap scaledBitmap = GlideApp.with(context)
|
||||||
if (quality == MIN_COMPRESSION_QUALITY) break;
|
.asBitmap()
|
||||||
|
.load(model)
|
||||||
|
.downsample(DownsampleStrategy.AT_MOST)
|
||||||
|
.submit(constraints.getImageMaxWidth(context),
|
||||||
|
constraints.getImageMaxWidth(context))
|
||||||
|
.get();
|
||||||
|
|
||||||
int nextQuality = (int)Math.floor(quality * Math.sqrt((double)constraints.getImageMaxSize(context) / bytes.length));
|
if (scaledBitmap == null) {
|
||||||
if (quality - nextQuality < MIN_COMPRESSION_QUALITY_DECREASE) {
|
throw new BitmapDecodingException("Unable to decode image");
|
||||||
nextQuality = quality - MIN_COMPRESSION_QUALITY_DECREASE;
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
do {
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
scaledBitmap.compress(CompressFormat.JPEG, quality, baos);
|
||||||
|
bytes = baos.toByteArray();
|
||||||
|
|
||||||
|
Log.w(TAG, "iteration with quality " + quality + " size " + (bytes.length / 1024) + "kb");
|
||||||
|
if (quality == MIN_COMPRESSION_QUALITY) break;
|
||||||
|
|
||||||
|
int nextQuality = (int)Math.floor(quality * Math.sqrt((double)constraints.getImageMaxSize(context) / bytes.length));
|
||||||
|
if (quality - nextQuality < MIN_COMPRESSION_QUALITY_DECREASE) {
|
||||||
|
nextQuality = quality - MIN_COMPRESSION_QUALITY_DECREASE;
|
||||||
|
}
|
||||||
|
quality = Math.max(nextQuality, MIN_COMPRESSION_QUALITY);
|
||||||
}
|
}
|
||||||
quality = Math.max(nextQuality, MIN_COMPRESSION_QUALITY);
|
while (bytes.length > constraints.getImageMaxSize(context) && attempts++ < MAX_COMPRESSION_ATTEMPTS);
|
||||||
|
if (bytes.length > constraints.getImageMaxSize(context)) {
|
||||||
|
throw new BitmapDecodingException("Unable to scale image below: " + bytes.length);
|
||||||
|
}
|
||||||
|
Log.w(TAG, "createScaledBytes(" + model.toString() + ") -> quality " + Math.min(quality, MAX_COMPRESSION_QUALITY) + ", " + attempts + " attempt(s)");
|
||||||
|
return bytes;
|
||||||
|
} finally {
|
||||||
|
if (scaledBitmap != null) scaledBitmap.recycle();
|
||||||
}
|
}
|
||||||
while (bytes.length > constraints.getImageMaxSize(context) && attempts++ < MAX_COMPRESSION_ATTEMPTS);
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
if (bytes.length > constraints.getImageMaxSize(context)) {
|
throw new BitmapDecodingException(e);
|
||||||
throw new BitmapDecodingException("Unable to scale image below: " + bytes.length);
|
|
||||||
}
|
|
||||||
Log.w(TAG, "createScaledBytes(" + model.toString() + ") -> quality " + Math.min(quality, MAX_COMPRESSION_QUALITY) + ", " + attempts + " attempt(s)");
|
|
||||||
return bytes;
|
|
||||||
} finally {
|
|
||||||
if (scaledBitmap != null) scaledBitmap.recycle();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> Bitmap createScaledBitmap(Context context, T model, int maxWidth, int maxHeight)
|
public static <T> Bitmap createScaledBitmap(Context context, T model, int maxWidth, int maxHeight)
|
||||||
throws BitmapDecodingException
|
throws BitmapDecodingException
|
||||||
{
|
|
||||||
final Pair<Integer, Integer> dimensions = getDimensions(getInputStreamForModel(context, model));
|
|
||||||
final Pair<Integer, Integer> clamped = clampDimensions(dimensions.first, dimensions.second,
|
|
||||||
maxWidth, maxHeight);
|
|
||||||
return createScaledBitmapInto(context, model, clamped.first, clamped.second);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <T> InputStream getInputStreamForModel(Context context, T model)
|
|
||||||
throws BitmapDecodingException
|
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return Glide.buildStreamModelLoader(model, context)
|
return GlideApp.with(context)
|
||||||
.getResourceFetcher(model, -1, -1)
|
.asBitmap()
|
||||||
.loadData(Priority.NORMAL);
|
.load(model)
|
||||||
} catch (Exception e) {
|
.downsample(DownsampleStrategy.AT_MOST)
|
||||||
|
.submit(maxWidth, maxHeight)
|
||||||
|
.get();
|
||||||
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
throw new BitmapDecodingException(e);
|
throw new BitmapDecodingException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T> Bitmap createScaledBitmapInto(Context context, T model, int width, int height)
|
|
||||||
throws BitmapDecodingException
|
|
||||||
{
|
|
||||||
final Bitmap rough = Downsampler.AT_LEAST.decode(getInputStreamForModel(context, model),
|
|
||||||
Glide.get(context).getBitmapPool(),
|
|
||||||
width, height,
|
|
||||||
DecodeFormat.PREFER_RGB_565);
|
|
||||||
|
|
||||||
final Resource<Bitmap> resource = BitmapResource.obtain(rough, Glide.get(context).getBitmapPool());
|
|
||||||
final Resource<Bitmap> result = new FitCenter(context).transform(resource, width, height);
|
|
||||||
|
|
||||||
if (result == null) {
|
|
||||||
throw new BitmapDecodingException("unable to transform Bitmap");
|
|
||||||
}
|
|
||||||
return result.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> Bitmap createScaledBitmap(Context context, T model, float scale)
|
public static <T> Bitmap createScaledBitmap(Context context, T model, float scale)
|
||||||
throws BitmapDecodingException
|
throws BitmapDecodingException
|
||||||
{
|
{
|
||||||
Pair<Integer, Integer> dimens = getDimensions(getInputStreamForModel(context, model));
|
try {
|
||||||
return createScaledBitmapInto(context, model,
|
return GlideApp.with(context)
|
||||||
(int)(dimens.first * scale), (int)(dimens.second * scale));
|
.asBitmap()
|
||||||
|
.load(model)
|
||||||
|
.sizeMultiplier(scale)
|
||||||
|
.submit()
|
||||||
|
.get();
|
||||||
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
|
throw new BitmapDecodingException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BitmapFactory.Options getImageDimensions(InputStream inputStream)
|
private static BitmapFactory.Options getImageDimensions(InputStream inputStream)
|
||||||
@ -253,27 +239,6 @@ public class BitmapUtil {
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Pair<Integer, Integer> clampDimensions(int inWidth, int inHeight, int maxWidth, int maxHeight) {
|
|
||||||
if (inWidth > maxWidth || inHeight > maxHeight) {
|
|
||||||
final float aspectWidth, aspectHeight;
|
|
||||||
|
|
||||||
if (inWidth == 0 || inHeight == 0) {
|
|
||||||
aspectWidth = maxWidth;
|
|
||||||
aspectHeight = maxHeight;
|
|
||||||
} else if (inWidth >= inHeight) {
|
|
||||||
aspectWidth = maxWidth;
|
|
||||||
aspectHeight = (aspectWidth / inWidth) * inHeight;
|
|
||||||
} else {
|
|
||||||
aspectHeight = maxHeight;
|
|
||||||
aspectWidth = (aspectHeight / inHeight) * inWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Pair<>(Math.round(aspectWidth), Math.round(aspectHeight));
|
|
||||||
} else {
|
|
||||||
return new Pair<>(inWidth, inHeight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Bitmap createFromDrawable(final Drawable drawable, final int width, final int height) {
|
public static Bitmap createFromDrawable(final Drawable drawable, final int width, final int height) {
|
||||||
final AtomicBoolean created = new AtomicBoolean(false);
|
final AtomicBoolean created = new AtomicBoolean(false);
|
||||||
final Bitmap[] result = new Bitmap[1];
|
final Bitmap[] result = new Bitmap[1];
|
||||||
|
@ -11,8 +11,6 @@ import android.text.TextUtils;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.webkit.MimeTypeMap;
|
import android.webkit.MimeTypeMap;
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.attachments.Attachment;
|
import org.thoughtcrime.securesms.attachments.Attachment;
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||||
@ -20,6 +18,7 @@ import org.thoughtcrime.securesms.mms.AudioSlide;
|
|||||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
|
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
|
||||||
import org.thoughtcrime.securesms.mms.DocumentSlide;
|
import org.thoughtcrime.securesms.mms.DocumentSlide;
|
||||||
import org.thoughtcrime.securesms.mms.GifSlide;
|
import org.thoughtcrime.securesms.mms.GifSlide;
|
||||||
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||||
import org.thoughtcrime.securesms.mms.ImageSlide;
|
import org.thoughtcrime.securesms.mms.ImageSlide;
|
||||||
import org.thoughtcrime.securesms.mms.MmsSlide;
|
import org.thoughtcrime.securesms.mms.MmsSlide;
|
||||||
import org.thoughtcrime.securesms.mms.PartAuthority;
|
import org.thoughtcrime.securesms.mms.PartAuthority;
|
||||||
@ -67,12 +66,12 @@ public class MediaUtil {
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
int maxSize = context.getResources().getDimensionPixelSize(R.dimen.media_bubble_height);
|
int maxSize = context.getResources().getDimensionPixelSize(R.dimen.media_bubble_height);
|
||||||
return Glide.with(context)
|
return GlideApp.with(context)
|
||||||
.load(new DecryptableUri(masterSecret, uri))
|
.asBitmap()
|
||||||
.asBitmap()
|
.load(new DecryptableUri(masterSecret, uri))
|
||||||
.centerCrop()
|
.centerCrop()
|
||||||
.into(maxSize, maxSize)
|
.into(maxSize, maxSize)
|
||||||
.get();
|
.get();
|
||||||
} catch (InterruptedException | ExecutionException e) {
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
Log.w(TAG, e);
|
Log.w(TAG, e);
|
||||||
throw new BitmapDecodingException(e);
|
throw new BitmapDecodingException(e);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user