aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.idea/compiler.xml4
-rw-r--r--.idea/jarRepositories.xml5
-rw-r--r--.idea/misc.xml8
-rw-r--r--app/build.gradle6
-rw-r--r--app/src/main/AndroidManifest.xml5
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt5
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt136
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/services/LocalService.kt90
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostUrlOverlayValidator.kt10
-rw-r--r--app/src/main/play/en-US/whatsnew5
-rw-r--r--app/src/main/res/layout/activity_image.xml4
-rw-r--r--app/src/main/res/xml/frost_changelog.xml6
-rw-r--r--buildSrc/src/main/kotlin/Versions.kt4
-rw-r--r--docs/Changelog.md3
15 files changed, 88 insertions, 205 deletions
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index fb7f4a8a..fcfdfd20 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
- <bytecodeTargetLevel target="11" />
+ <bytecodeTargetLevel target="11">
+ <module name="Frost-for-Facebook.buildSrc" target="11" />
+ </bytecodeTargetLevel>
</component>
</project> \ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
index 1e2d92c1..7c680430 100644
--- a/.idea/jarRepositories.xml
+++ b/.idea/jarRepositories.xml
@@ -31,5 +31,10 @@
<option name="name" value="MavenRepo" />
<option name="url" value="https://repo.maven.apache.org/maven2/" />
</remote-repository>
+ <remote-repository>
+ <option name="id" value="maven" />
+ <option name="name" value="maven" />
+ <option name="url" value="https://oss.sonatype.org/content/repositories/snapshots/" />
+ </remote-repository>
</component>
</project> \ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index c17036ff..dac62c47 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,5 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
+ <component name="DesignSurface">
+ <option name="filePathToZoomLevelMap">
+ <map>
+ <entry key="../../../../layout/custom_preview.xml" value="0.209375" />
+ <entry key="app/src/main/res/layout/activity_image.xml" value="0.1585144927536232" />
+ </map>
+ </option>
+ </component>
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
diff --git a/app/build.gradle b/app/build.gradle
index 8779069a..2655f695 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -274,6 +274,10 @@ dependencies {
implementation "androidx.biometric:biometric:${Versions.andxBiometric}"
+ implementation "com.github.piasy:BigImageViewer:${Versions.bigImageViewer}"
+ implementation "com.github.piasy:GlideImageLoader:${Versions.bigImageViewer}"
+ implementation "com.github.piasy:GlideImageViewFactory:${Versions.bigImageViewer}"
+
implementation kau.Dependencies.hilt
kapt kau.Dependencies.hiltCompiler
testImplementation kau.Dependencies.hiltTest
@@ -314,8 +318,6 @@ dependencies {
testImplementation "com.squareup.okhttp3:mockwebserver:${Versions.okhttp}"
androidTestImplementation "com.squareup.okhttp3:mockwebserver:${Versions.okhttp}"
- implementation "com.davemorrissey.labs:subsampling-scale-image-view:${Versions.scaleImageView}"
-
implementation "androidx.room:room-ktx:${Versions.room}"
implementation "androidx.room:room-runtime:${Versions.room}"
kapt "androidx.room:room-compiler:${Versions.room}"
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5485ac15..eeab750f 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -173,11 +173,6 @@
android:enabled="true"
android:label="@string/frost_notifications"
android:permission="android.permission.BIND_JOB_SERVICE" />
- <service
- android:name=".services.LocalService"
- android:enabled="true"
- android:label="@string/local_service_name"
- android:permission="android.permission.BIND_JOB_SERVICE" />
<receiver
android:name=".services.UpdateReceiver"
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt b/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt
index f5ef0b74..d444d225 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt
@@ -22,8 +22,11 @@ import android.os.Bundle
import android.util.Log
import ca.allanwang.kau.logging.KL
import ca.allanwang.kau.utils.buildIsLollipopAndUp
+import com.github.piasy.biv.BigImageViewer
+import com.github.piasy.biv.loader.glide.GlideImageLoader
import com.pitchedapps.frost.db.CookieDao
import com.pitchedapps.frost.db.NotificationDao
+import com.pitchedapps.frost.facebook.requests.httpClient
import com.pitchedapps.frost.injectors.ThemeProvider
import com.pitchedapps.frost.prefs.Prefs
import com.pitchedapps.frost.services.scheduleNotificationsFromPrefs
@@ -66,6 +69,8 @@ class FrostApp : Application() {
scheduleNotificationsFromPrefs(prefs)
+ BigImageViewer.initialize(GlideImageLoader.with(this, httpClient))
+
if (BuildConfig.DEBUG) {
registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
override fun onActivityPaused(activity: Activity) {}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt
index b8a71fa1..2700f1b4 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt
@@ -16,10 +16,10 @@
*/
package com.pitchedapps.frost.activities
-import android.content.Context
import android.content.Intent
import android.content.res.ColorStateList
import android.graphics.Color
+import android.net.Uri
import android.os.Bundle
import android.view.View
import android.widget.ImageView
@@ -28,7 +28,6 @@ import ca.allanwang.kau.internal.KauBaseActivity
import ca.allanwang.kau.logging.KauLoggerExtension
import ca.allanwang.kau.utils.adjustAlpha
import ca.allanwang.kau.utils.colorToForeground
-import ca.allanwang.kau.utils.copyFromInputStream
import ca.allanwang.kau.utils.fadeIn
import ca.allanwang.kau.utils.fadeOut
import ca.allanwang.kau.utils.gone
@@ -42,22 +41,17 @@ import ca.allanwang.kau.utils.tint
import ca.allanwang.kau.utils.toast
import ca.allanwang.kau.utils.withAlpha
import ca.allanwang.kau.utils.withMinAlpha
-import com.davemorrissey.labs.subscaleview.ImageSource
-import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
+import com.github.piasy.biv.loader.ImageLoader
+import com.github.piasy.biv.view.ImageShownCallback
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.mikepenz.iconics.typeface.IIcon
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
import com.pitchedapps.frost.R
import com.pitchedapps.frost.databinding.ActivityImageBinding
-import com.pitchedapps.frost.facebook.FB_IMAGE_ID_MATCHER
-import com.pitchedapps.frost.facebook.get
-import com.pitchedapps.frost.facebook.requests.call
import com.pitchedapps.frost.facebook.requests.getFullSizedImageUrl
-import com.pitchedapps.frost.facebook.requests.requestBuilder
import com.pitchedapps.frost.injectors.ThemeProvider
import com.pitchedapps.frost.prefs.Prefs
-import com.pitchedapps.frost.services.LocalService
import com.pitchedapps.frost.utils.ARG_COOKIE
import com.pitchedapps.frost.utils.ARG_IMAGE_URL
import com.pitchedapps.frost.utils.ARG_TEXT
@@ -73,10 +67,8 @@ import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
import java.io.File
import java.io.FileNotFoundException
-import java.io.IOException
import javax.inject.Inject
import kotlin.math.abs
import kotlin.math.max
@@ -102,25 +94,10 @@ class ImageActivity : KauBaseActivity() {
/**
* Reference to the temporary file path
*/
- internal var tempFile: File? = null
+ internal val tempFile: File? get() = binding.imagePhoto.currentImageFile
private lateinit var dragHelper: ViewDragHelper
- companion object {
- /**
- * Cache folder to store images
- * Linked to the uri provider
- */
- private const val IMAGE_FOLDER = "images"
- private const val TIME_FORMAT = "yyyyMMdd_HHmmss"
- private const val IMG_TAG = "Frost"
- const val PURGE_TIME: Long = 10 * 60 * 1000 // 10 min block
- private val L = KauLoggerExtension("Image", com.pitchedapps.frost.utils.L)
-
- fun cacheDir(context: Context): File =
- File(context.cacheDir, IMAGE_FOLDER)
- }
-
private val cookie: String? by lazy { intent.getStringExtra(ARG_COOKIE) }
val imageUrl: String by lazy { intent.getStringExtra(ARG_IMAGE_URL)?.trim('"') ?: "" }
@@ -129,11 +106,6 @@ class ImageActivity : KauBaseActivity() {
private val imageText: String? by lazy { intent.getStringExtra(ARG_TEXT) }
- // a unique image identifier based on the id (if it exists), and its hash
- private val imageHash: String by lazy {
- "${abs(FB_IMAGE_ID_MATCHER.find(imageUrl)[1]?.hashCode() ?: 0)}_${abs(imageUrl.hashCode())}"
- }
-
lateinit var binding: ActivityImageBinding
private var bottomBehavior: BottomSheetBehavior<View>? = null
@@ -167,21 +139,31 @@ class ImageActivity : KauBaseActivity() {
val result = if (!imageUrl.isIndirectImageUrl) imageUrl
else cookie?.getFullSizedImageUrl(imageUrl) ?: imageUrl
if (result != imageUrl)
- L.v { "Launching with true url $result" }
+ L.v { "Launching image with true url $result" }
+ else
+ L.v { "Launching image with url $result" }
result
}
binding = ActivityImageBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.init()
launch(CoroutineExceptionHandler { _, throwable -> loadError(throwable) }) {
- val tempFile = downloadTempImage()
- this@ImageActivity.tempFile = tempFile
- binding.imageProgress.fadeOut()
- binding.imagePhoto.setImage(ImageSource.uri(frostUriFromFile(tempFile)))
- binding.imagePhoto.animate().alpha(1f).scaleXY(1f).start()
+ binding.showImage(trueImageUrl.await())
}
}
+ private fun ActivityImageBinding.showImage(url: String) {
+ imagePhoto.showImage(Uri.parse(url))
+ imagePhoto.setImageShownCallback(object : ImageShownCallback {
+ override fun onThumbnailShown() {}
+
+ override fun onMainImageShown() {
+ imageProgress.fadeOut()
+ imagePhoto.animate().alpha(1f).scaleXY(1f).start()
+ }
+ })
+ }
+
private fun ActivityImageBinding.init() {
imageContainer.setBackgroundColor(baseBackgroundColor)
toolbar.setBackgroundColor(baseBackgroundColor)
@@ -226,12 +208,25 @@ class ImageActivity : KauBaseActivity() {
share.apply {
setState(FabStates.SHARE)
}
- imagePhoto.setOnImageEventListener(object :
- SubsamplingScaleImageView.DefaultOnImageEventListener() {
- override fun onImageLoadError(e: Exception) {
- loadError(e)
- }
- })
+
+ imagePhoto.setImageLoaderCallback(object : ImageLoader.Callback {
+ override fun onCacheHit(imageType: Int, image: File?) {}
+
+ override fun onCacheMiss(imageType: Int, image: File?) {}
+
+ override fun onStart() {}
+
+ override fun onProgress(progress: Int) {}
+
+ override fun onFinish() {}
+
+ override fun onSuccess(image: File) {}
+
+ override fun onFail(error: Exception) {
+ loadError(error)
+ }
+ })
+
activityThemer.setFrostColors {
themeWindow = false
}
@@ -303,61 +298,12 @@ class ImageActivity : KauBaseActivity() {
override fun clampViewPositionVertical(child: View, top: Int, dy: Int): Int = top
}
- private fun getImageExtension(type: String?): String? {
- if (type?.startsWith("image/") != true) {
- return null
- }
- return when (type.substring(6)) {
- "jpeg" -> "jpg"
- "png" -> "png"
- "gif" -> "gif"
- else -> null
- }
- }
-
- @Throws(IOException::class)
- private suspend fun downloadTempImage(): File = withContext(Dispatchers.IO) {
-
- // We assume all images are jpg
- // Activity launcher may be able to provide specifics, but this beats sending a request
- // just to get the content header
- val file = File(cacheDir(this@ImageActivity), "$imageHash.jpg")
-
- if (!file.isFile) {
- file.parentFile?.mkdirs()
- file.createNewFile()
- } else {
- file.setLastModified(System.currentTimeMillis())
- }
-
- // Forbid overwrites
- if (file.isFile && file.length() > 0) {
- L.i { "Forbid image overwrite" }
- return@withContext file
- }
-
- val response = cookie.requestBuilder()
- .url(trueImageUrl.await())
- .get()
- .call()
- .execute()
-
- if (!response.isSuccessful) {
- throw IOException("Unsuccessful response for image: ${response.peekBody(128).string()}")
- }
-
- val body = response.body ?: throw IOException("Failed to retrieve image body")
- file.copyFromInputStream(body.byteStream())
- file
- }
-
internal suspend fun saveImage() {
frostDownload(cookie = cookie, url = trueImageUrl.await())
}
- override fun onDestroy() {
- LocalService.schedule(this, LocalService.Flag.PURGE_IMAGE)
- super.onDestroy()
+ companion object {
+ private val L = KauLoggerExtension("Image", com.pitchedapps.frost.utils.L)
}
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt
index 1a714374..ab041adc 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt
@@ -60,7 +60,7 @@ class FbCookie @Inject internal constructor(
* Note that this is a synchronized call
*/
val webCookie: String?
- get() = CookieManager.getInstance().getCookie(FB_COOKIE_DOMAIN)
+ get() = CookieManager.getInstance().getCookie(HTTPS_FACEBOOK_COM)
val messengerCookie: String?
get() = CookieManager.getInstance().getCookie(HTTPS_MESSENGER_COM)
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/services/LocalService.kt b/app/src/main/kotlin/com/pitchedapps/frost/services/LocalService.kt
deleted file mode 100644
index 3d66f1ee..00000000
--- a/app/src/main/kotlin/com/pitchedapps/frost/services/LocalService.kt
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2018 Allan Wang
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-package com.pitchedapps.frost.services
-
-import android.app.job.JobInfo
-import android.app.job.JobParameters
-import android.app.job.JobScheduler
-import android.content.ComponentName
-import android.content.Context
-import android.os.PersistableBundle
-import com.pitchedapps.frost.activities.ImageActivity
-import com.pitchedapps.frost.utils.L
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-import java.io.FileFilter
-
-class LocalService : BaseJobService() {
-
- enum class Flag {
- PURGE_IMAGE
- }
-
- companion object {
- private const val FLAG = "extra_local_flag"
-
- /**
- * Launches a local service with the provided flag
- */
- fun schedule(context: Context, flag: Flag): Boolean {
- val scheduler = context.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
- val serviceComponent = ComponentName(context, LocalService::class.java)
- val bundle = PersistableBundle()
- bundle.putString(FLAG, flag.name)
-
- val builder = JobInfo.Builder(LOCAL_SERVICE_BASE + flag.ordinal, serviceComponent)
- .setMinimumLatency(0L)
- .setExtras(bundle)
- .setOverrideDeadline(2000L)
-
- val result = scheduler.schedule(builder.build())
- if (result <= 0) {
- L.eThrow("FrostRequestService scheduler failed for ${flag.name}")
- return false
- }
- L.d { "Scheduled ${flag.name}" }
- return true
- }
- }
-
- override fun onStartJob(params: JobParameters?): Boolean {
- super.onStartJob(params)
- val flagString = params?.extras?.getString(FLAG)
- val flag: Flag = try {
- Flag.valueOf(flagString!!)
- } catch (e: Exception) {
- L.e { "Local service with invalid flag $flagString" }
- return true
- }
- launch {
- when (flag) {
- Flag.PURGE_IMAGE -> purgeImages()
- }
- }
- return false
- }
-
- private suspend fun purgeImages() {
- withContext(Dispatchers.IO) {
- val purge = System.currentTimeMillis() - ImageActivity.PURGE_TIME
- ImageActivity.cacheDir(this@LocalService)
- .listFiles(FileFilter { it.isFile && it.lastModified() < purge })
- ?.forEach { it.delete() }
- }
- }
-}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostUrlOverlayValidator.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostUrlOverlayValidator.kt
index 94300348..a0842267 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostUrlOverlayValidator.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostUrlOverlayValidator.kt
@@ -61,16 +61,16 @@ fun FrostWebView.requestWebOverlay(url: String): Boolean {
context.runOnUiThread { context.showVideo(url) }
return true
}
- if (url.isImageUrl) {
- L.d { "Found fb image" }
- context.launchImageActivity(url)
- return true
- }
if (url.isIndirectImageUrl) {
L.d { "Found indirect fb image" }
context.launchImageActivity(url, cookie = fbCookie.webCookie)
return true
}
+ if (url.isImageUrl) {
+ L.d { "Found fb image" }
+ context.launchImageActivity(url)
+ return true
+ }
if (!url.isIndependent) {
L.d { "Forbid overlay switch" }
return false
diff --git a/app/src/main/play/en-US/whatsnew b/app/src/main/play/en-US/whatsnew
index 06b44904..2e50ba70 100644
--- a/app/src/main/play/en-US/whatsnew
+++ b/app/src/main/play/en-US/whatsnew
@@ -1,4 +1,3 @@
-v3.1.1
+v3.1.2
-* Many internal fixes to address 3.1.0 issues
-* Theme updates \ No newline at end of file
+* Fix loading full size images \ No newline at end of file
diff --git a/app/src/main/res/layout/activity_image.xml b/app/src/main/res/layout/activity_image.xml
index 6530dc4a..689c4f4d 100644
--- a/app/src/main/res/layout/activity_image.xml
+++ b/app/src/main/res/layout/activity_image.xml
@@ -17,7 +17,9 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
- <com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
+ <!-- Alpha and scaling will be reset on load -->
+
+ <com.github.piasy.biv.view.BigImageView
android:id="@+id/image_photo"
android:layout_width="match_parent"
android:layout_height="match_parent"
diff --git a/app/src/main/res/xml/frost_changelog.xml b/app/src/main/res/xml/frost_changelog.xml
index e5f0ade6..9bc126fb 100644
--- a/app/src/main/res/xml/frost_changelog.xml
+++ b/app/src/main/res/xml/frost_changelog.xml
@@ -5,6 +5,12 @@
<version title="v" />
<item text="" />
-->
+
+ <version title="v3.1.2" />
+ <item text="Fix loading full size images" />
+ <item text="" />
+ <item text="" />
+
<version title="v3.1.1" />
<item text="Many internal fixes to address 3.1.0 issues" />
<item text="Theme updates" />
diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt
index 5c68a01d..a8069507 100644
--- a/buildSrc/src/main/kotlin/Versions.kt
+++ b/buildSrc/src/main/kotlin/Versions.kt
@@ -19,8 +19,8 @@ object Versions {
const val room = "2.3.0"
// http://robolectric.org/getting-started/
const val roboelectric = "4.6"
- // https://github.com/davemorrissey/subsampling-scale-image-view#quick-start
- const val scaleImageView = "3.10.0"
+ // https://github.com/Piasy/BigImageViewer#add-the-dependencies
+ const val bigImageViewer = "1.8.1"
// https://github.com/node-gradle/gradle-node-plugin/releases
const val nodeGradle = "3.1.1"
} \ No newline at end of file
diff --git a/docs/Changelog.md b/docs/Changelog.md
index d763f8da..87a48b87 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -1,5 +1,8 @@
# Changelog
+## v3.1.2
+* Fix loading full size images
+
## v3.1.1
* Many internal fixes to address 3.1.0 issues
* Theme updates