diff options
author | Allan Wang <me@allanwang.ca> | 2017-11-13 05:09:24 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-11-13 05:09:24 -0500 |
commit | 63d8779ad4fab7d2eb762be34eeca04c7debc6f3 (patch) | |
tree | 334f3c0c4c6a717d7c0b0872574cb65b3b50166c /app/src/main/kotlin | |
parent | 4aed05a8923a7f76799bbaa254f407f7e11fef0b (diff) | |
download | frost-63d8779ad4fab7d2eb762be34eeca04c7debc6f3.tar.gz frost-63d8779ad4fab7d2eb762be34eeca04c7debc6f3.tar.bz2 frost-63d8779ad4fab7d2eb762be34eeca04c7debc6f3.zip |
Enhancement/video (#484)v1.6.4
* Fix more parsing issues
* Try catch decoder resolves #456
* Fix unit test and add null check for images, resolves #458
* Remove downloadservice, resolves #459
* Clean up progress animator
* Check for download manager before download attempt
* Update strings
Diffstat (limited to 'app/src/main/kotlin')
8 files changed, 66 insertions, 96 deletions
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 0a713649..2fe6b8d8 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt @@ -76,6 +76,7 @@ class ImageActivity : KauBaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + intent?.extras ?: return finish() L.i("Displaying image", imageUrl) val layout = if (!text.isNullOrBlank()) R.layout.activity_image else R.layout.activity_image_textless setContentView(layout) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbUrlFormatter.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbUrlFormatter.kt index 0e74bb59..22ca3138 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbUrlFormatter.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbUrlFormatter.kt @@ -26,30 +26,39 @@ class FbUrlFormatter(url: String) { * 4. Url is split into sections */ init { - if (url.isBlank()) cleaned = "" - else { - var cleanedUrl = url - discardable.forEach { cleanedUrl = cleanedUrl.replace(it, "", true) } - converter.forEach { (k, v) -> cleanedUrl = cleanedUrl.replace(k, v, true) } - if (cleanedUrl != url && !cleanedUrl.contains("?")) cleanedUrl = cleanedUrl.replaceFirst("&", "?") + cleaned = clean(url) + } + + fun clean(url: String): String { + if (url.isBlank()) return "" + var cleanedUrl = url + discardable.forEach { cleanedUrl = cleanedUrl.replace(it, "", true) } + val changed = cleanedUrl != url + converter.forEach { (k, v) -> cleanedUrl = cleanedUrl.replace(k, v, true) } + try { cleanedUrl = URLDecoder.decode(cleanedUrl, StandardCharsets.UTF_8.name()) - val qm = cleanedUrl.indexOf("?") - if (qm > -1) { - cleanedUrl.substring(qm + 1).split("&").forEach { - val p = it.split("=") - queries.put(p[0], p.elementAtOrNull(1) ?: "") - } - cleanedUrl = cleanedUrl.substring(0, qm) + } catch (e: Exception) { + L.e(e, "Failed url formatting") + return url + } + if (changed && !cleanedUrl.contains("?")) //ensure we aren't missing '?' + cleanedUrl = cleanedUrl.replaceFirst("&", "?") + val qm = cleanedUrl.indexOf("?") + if (qm > -1) { + cleanedUrl.substring(qm + 1).split("&").forEach { + val p = it.split("=") + queries.put(p[0], p.elementAtOrNull(1) ?: "") } - discardableQueries.forEach { queries.remove(it) } - //final cleanup - misc.forEach { (k, v) -> cleanedUrl = cleanedUrl.replace(k, v, true) } - if (cleanedUrl.startsWith("#!")) cleanedUrl = cleanedUrl.substring(2) - if (cleanedUrl.startsWith("/")) cleanedUrl = FB_URL_BASE + cleanedUrl.substring(1) - cleanedUrl = cleanedUrl.replaceFirst(".facebook.com//", ".facebook.com/") //sometimes we are given a bad url - L.v(null, "Formatted url from $url to $cleanedUrl") - cleaned = cleanedUrl + cleanedUrl = cleanedUrl.substring(0, qm) } + discardableQueries.forEach { queries.remove(it) } + //final cleanup + misc.forEach { (k, v) -> cleanedUrl = cleanedUrl.replace(k, v, true) } + if (cleanedUrl.startsWith("#!")) cleanedUrl = cleanedUrl.substring(2) + if (cleanedUrl.startsWith("/")) cleanedUrl = FB_URL_BASE + cleanedUrl.substring(1) + cleanedUrl = cleanedUrl.replaceFirst(".facebook.com//", ".facebook.com/") //sometimes we are given a bad url + L.v(null, "Formatted url from $url to $cleanedUrl") + return cleanedUrl } override fun toString(): String { @@ -76,6 +85,10 @@ class FbUrlFormatter(url: String) { * Items here are explicitly removed from the url * Taken from FaceSlim * https://github.com/indywidualny/FaceSlim/blob/master/app/src/main/java/org/indywidualni/fblite/util/Miscellany.java + * + * Note: Typically, in this case, the redirect url should have all the necessary queries + * I am unsure how Facebook reacts in all cases, so the ones after the redirect are appended on afterwards + * That shouldn't break anything */ val discardable = arrayOf( "http://lm.facebook.com/l.php?u=", diff --git a/app/src/main/kotlin/com/pitchedapps/frost/services/DownloadService.kt b/app/src/main/kotlin/com/pitchedapps/frost/services/DownloadService.kt index fda5ebf5..520d750f 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/services/DownloadService.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/services/DownloadService.kt @@ -1,5 +1,6 @@ package com.pitchedapps.frost.services +import android.annotation.SuppressLint import android.app.IntentService import android.app.Notification import android.app.PendingIntent @@ -26,11 +27,14 @@ import java.io.File /** * Created by Allan Wang on 2017-08-08. * + * Not in use + * * Background file downloader * All we are given is a link and a mime type * * With reference to the <a href="https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/Progress.java">OkHttp3 sample</a> */ +@SuppressLint("Registered") class DownloadService : IntentService("FrostVideoDownloader") { companion object { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/Animator.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/Animator.kt deleted file mode 100644 index da852e6e..00000000 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Animator.kt +++ /dev/null @@ -1,70 +0,0 @@ -package com.pitchedapps.frost.utils - -import android.animation.Animator -import android.animation.AnimatorListenerAdapter -import android.animation.ValueAnimator -import android.view.animation.Interpolator - -/** - * Created by Allan Wang on 2017-11-10. - */ -class ProgressAnimator private constructor(private vararg val values: Float) { - - companion object { - inline fun ofFloat(crossinline builder: ProgressAnimator.() -> Unit) = ofFloat(0f, 1f) { builder() } - - fun ofFloat(vararg values: Float, builder: ProgressAnimator.() -> Unit) = ProgressAnimator(*values).apply { - builder() - build() - } - } - - private val animators: MutableList<(Float) -> Unit> = mutableListOf() - private val startActions: MutableList<() -> Unit> = mutableListOf() - private val endActions: MutableList<() -> Unit> = mutableListOf() - - var duration: Long = -1L - var interpolator: Interpolator? = null - - /** - * Add more changes to the [ValueAnimator] before running - */ - var extraConfigs: ValueAnimator.() -> Unit = {} - - fun withAnimator(from: Float, to: Float, animator: (Float) -> Unit) = animators.add { - val range = to - from - animator(range * it + from) - } - - fun withAnimator(animator: (Float) -> Unit) = animators.add(animator) - - fun withAnimatorInv(animator: (Float) -> Unit) = animators.add { animator(1f - it) } - - fun withStartAction(action: () -> Unit) = startActions.add(action) - - fun withEndAction(action: () -> Unit) = endActions.add(action) - - fun build() { - ValueAnimator.ofFloat(*values).apply { - if (this@ProgressAnimator.duration > 0L) - duration = this@ProgressAnimator.duration - if (this@ProgressAnimator.interpolator != null) - interpolator = this@ProgressAnimator.interpolator - addUpdateListener { - val progress = it.animatedValue as Float - animators.forEach { it(progress) } - } - addListener(object : AnimatorListenerAdapter() { - override fun onAnimationStart(animation: Animator?) { - startActions.forEach { it() } - } - - override fun onAnimationEnd(animation: Animator?) { - endActions.forEach { it() } - } - }) - extraConfigs() - start() - } - } -}
\ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/Downloader.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/Downloader.kt index 3e1e1dde..e6db8eee 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Downloader.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Downloader.kt @@ -8,10 +8,15 @@ import android.os.Environment import android.webkit.URLUtil import ca.allanwang.kau.permissions.PERMISSION_WRITE_EXTERNAL_STORAGE import ca.allanwang.kau.permissions.kauRequestPermissions +import ca.allanwang.kau.utils.isAppEnabled import ca.allanwang.kau.utils.string import com.pitchedapps.frost.R import com.pitchedapps.frost.dbflow.loadFbCookie import com.pitchedapps.frost.facebook.USER_AGENT_BASIC +import android.support.v4.content.ContextCompat.startActivity +import android.content.Intent +import android.content.ActivityNotFoundException +import ca.allanwang.kau.utils.showAppInfo /** @@ -37,6 +42,16 @@ fun Context.frostDownload(uri: Uri?, L.d("Received download request", "Download $uri") if (uri.scheme != "http" && uri.scheme != "https") return L.e("Invalid download attempt", uri.toString()) + if (!isAppEnabled(DOWNLOAD_MANAGER_PACKAGE)) { + materialDialogThemed { + title(R.string.no_download_manager) + content(R.string.no_download_manager_desc) + positiveText(R.string.kau_yes) + onPositive { _, _ -> showAppInfo(DOWNLOAD_MANAGER_PACKAGE) } + negativeText(R.string.kau_no) + } + return + } kauRequestPermissions(PERMISSION_WRITE_EXTERNAL_STORAGE) { granted, _ -> if (!granted) return@kauRequestPermissions val request = DownloadManager.Request(uri) @@ -53,4 +68,6 @@ fun Context.frostDownload(uri: Uri?, val dm = getSystemService(DOWNLOAD_SERVICE) as DownloadManager dm.enqueue(request) } -}
\ No newline at end of file +} + +private const val DOWNLOAD_MANAGER_PACKAGE = "com.android.providers.downloads"
\ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt index 22c77f5f..c644499e 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt @@ -202,7 +202,7 @@ inline val String?.isFacebookUrl get() = this != null && this.contains(FACEBOOK_COM) inline val String?.isVideoUrl - get() = this != null && this.startsWith(VIDEO_REDIRECT) + get() = this != null && (this.startsWith(VIDEO_REDIRECT) || this.startsWith("https://video-")) fun Context.frostChangelog() = showChangelog(R.xml.frost_changelog, Prefs.textColor) { theme() diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoView.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoView.kt index 639dc9ba..9d5e199a 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoView.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoView.kt @@ -8,12 +8,12 @@ import android.util.AttributeSet import android.view.GestureDetector import android.view.MotionEvent import android.view.View +import ca.allanwang.kau.ui.ProgressAnimator import ca.allanwang.kau.utils.AnimHolder import ca.allanwang.kau.utils.dpToPx import ca.allanwang.kau.utils.scaleXY import com.devbrackets.android.exomedia.ui.widget.VideoView import com.pitchedapps.frost.utils.L -import com.pitchedapps.frost.utils.ProgressAnimator /** * Created by Allan Wang on 2017-10-13. @@ -83,7 +83,7 @@ class FrostVideoView @JvmOverloads constructor( ProgressAnimator.ofFloat { duration = ANIMATION_DURATION interpolator = AnimHolder.fastOutSlowInInterpolator(context) - withAnimatorInv { viewerContract.onExpand(it) } + withAnimator { viewerContract.onExpand(1f - it) } withAnimator(origScale, scale) { scaleXY = it } withAnimator(origX, tX) { translationX = it } withAnimator(origY, tY) { translationY = it } 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 ca88a23e..e8f9fee9 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostUrlOverlayValidator.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostUrlOverlayValidator.kt @@ -3,11 +3,13 @@ package com.pitchedapps.frost.web import com.pitchedapps.frost.activities.WebOverlayActivity import com.pitchedapps.frost.activities.WebOverlayActivityBase import com.pitchedapps.frost.activities.WebOverlayBasicActivity + import com.pitchedapps.frost.contracts.VideoViewHolder import com.pitchedapps.frost.facebook.FbItem import com.pitchedapps.frost.facebook.USER_AGENT_BASIC import com.pitchedapps.frost.facebook.formattedFbUrl import com.pitchedapps.frost.utils.* +import org.jetbrains.anko.runOnUiThread /** * Created by Allan Wang on 2017-08-15. @@ -18,6 +20,9 @@ import com.pitchedapps.frost.utils.* * This helper method will collect all known cases and launch the overlay accordingly * Returns {@code true} (default) if action is consumed, {@code false} otherwise * + * Note that this is not always called on the main thread! + * UI related methods should always be posted or they may not be properly executed. + * * If the request already comes from an instance of [WebOverlayActivity], we will then judge * whether the user agent string should be changed. All propagated results will return false, * as we have no need of sending a new intent to the same activity @@ -26,7 +31,7 @@ fun FrostWebViewCore.requestWebOverlay(url: String): Boolean { if (url == "#") return false if (url.isVideoUrl && context is VideoViewHolder) { L.i("Found video", url) - (context as VideoViewHolder).showVideo(url) + context.runOnUiThread { (context as VideoViewHolder).showVideo(url) } return true } if (!Prefs.overlayEnabled) return false |