aboutsummaryrefslogtreecommitdiff
path: root/app/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main')
-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
9 files changed, 63 insertions, 200 deletions
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" />