1
0
mirror of https://github.com/AllanWang/Frost-for-Facebook.git synced 2024-09-19 15:11:42 +02:00

Redo image activity to support text content

This commit is contained in:
Allan Wang 2019-07-03 14:01:19 -07:00
parent 6685ed8d71
commit 16ab9a8dfa
No known key found for this signature in database
GPG Key ID: C93E3F9C679D7A56
8 changed files with 172 additions and 131 deletions

View File

@ -21,6 +21,7 @@
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
@ -31,6 +32,7 @@
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
@ -42,6 +44,7 @@
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
@ -52,6 +55,7 @@
<match>
<AND>
<NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
@ -62,6 +66,7 @@
<match>
<AND>
<NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
@ -72,6 +77,7 @@
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
@ -82,6 +88,7 @@
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
@ -93,6 +100,7 @@
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
@ -104,6 +112,7 @@
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>

View File

@ -22,7 +22,7 @@ apply from: '../spotless.gradle'
group = APP_GROUP
android {
compileSdkVersion kau.Versions.targetSdk
compileSdkVersion Versions.targetSdk
buildToolsVersion kau.Versions.buildTools
androidGitVersion {
@ -34,7 +34,7 @@ android {
defaultConfig {
applicationId "${project.APP_GROUP}.${project.APP_ID.toLowerCase(Locale.CANADA)}"
minSdkVersion kau.Versions.minSdk
targetSdkVersion kau.Versions.targetSdk
targetSdkVersion Versions.targetSdk
versionCode androidGitVersion.code()
versionName androidGitVersion.name()
multiDexEnabled true
@ -65,6 +65,10 @@ android {
textOutput 'stdout'
}
dataBinding {
enabled = true
}
def testKeystoreFile = file('../files/test.keystore')
def testPropFile = file('../files/test.properties')
def withTestSigning = testKeystoreFile.exists() && testPropFile.exists()

View File

@ -46,6 +46,7 @@ import com.pitchedapps.frost.utils.BiometricUtils
import com.pitchedapps.frost.utils.EXTRA_COOKIES
import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.utils.Prefs
import com.pitchedapps.frost.utils.launchImageActivity
import com.pitchedapps.frost.utils.launchNewTask
import com.pitchedapps.frost.utils.loadAssets
import com.raizlabs.android.dbflow.kotlinextensions.from
@ -98,11 +99,12 @@ class StartActivity : KauBaseActivity() {
cookies.isEmpty() -> launchNewTask<LoginActivity>()
// Has cookies but no selected account
Prefs.userId == -1L -> launchNewTask<SelectorActivity>(cookies)
else -> startActivity<MainActivity>(intentBuilder = {
putParcelableArrayListExtra(EXTRA_COOKIES, cookies)
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or
Intent.FLAG_ACTIVITY_SINGLE_TOP
})
else -> launchImageActivity("https://images.pexels.com/photos/374870/pexels-photo-374870.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", "Hello world\nLong Text\nLSEF")
// else -> startActivity<MainActivity>(intentBuilder = {
// putParcelableArrayListExtra(EXTRA_COOKIES, cookies)
// flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or
// Intent.FLAG_ACTIVITY_SINGLE_TOP
// })
}
} catch (e: Exception) {
L._e(e) { "Load start failed" }

View File

@ -24,6 +24,7 @@ import android.os.Bundle
import android.os.Environment
import android.view.View
import androidx.customview.widget.ViewDragHelper
import androidx.databinding.DataBindingUtil
import ca.allanwang.kau.internal.KauBaseActivity
import ca.allanwang.kau.logging.KauLoggerExtension
import ca.allanwang.kau.mediapicker.scanMedia
@ -33,6 +34,7 @@ import ca.allanwang.kau.utils.adjustAlpha
import ca.allanwang.kau.utils.colorToForeground
import ca.allanwang.kau.utils.copyFromInputStream
import ca.allanwang.kau.utils.fadeOut
import ca.allanwang.kau.utils.gone
import ca.allanwang.kau.utils.isHidden
import ca.allanwang.kau.utils.isVisible
import ca.allanwang.kau.utils.materialDialog
@ -43,10 +45,12 @@ 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.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.mikepenz.google_material_typeface_library.GoogleMaterial
import com.mikepenz.iconics.typeface.IIcon
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
@ -63,8 +67,6 @@ import com.pitchedapps.frost.utils.isIndirectImageUrl
import com.pitchedapps.frost.utils.logFrostEvent
import com.pitchedapps.frost.utils.sendFrostEmail
import com.pitchedapps.frost.utils.setFrostColors
import com.sothree.slidinguppanel.SlidingUpPanelLayout
import kotlinx.android.synthetic.main.activity_image.*
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
@ -104,7 +106,7 @@ class ImageActivity : KauBaseActivity() {
set(value) {
if (field == value) return
field = value
value.update(image_fab)
value.update(binding.imageFab)
}
private lateinit var dragHelper: ViewDragHelper
@ -141,14 +143,19 @@ class ImageActivity : KauBaseActivity() {
)}_${Math.abs(imageUrl.hashCode())}"
}
private lateinit var binding: ActivityImageBinding
private lateinit var bottomBehavior: BottomSheetBehavior<View>
private val baseBackgroundColor = if (Prefs.blackMediaBg) Color.BLACK
else Prefs.bgColor.withMinAlpha(235)
private fun loadError(e: Throwable) {
errorRef = e
e.logFrostEvent("Image load error")
if (image_progress.isVisible)
image_progress.fadeOut()
with(binding) {
if (imageProgress.isVisible)
imageProgress.fadeOut()
}
tempFile.delete()
fabAction = FabStates.ERROR
}
@ -166,28 +173,49 @@ class ImageActivity : KauBaseActivity() {
L.v { "Launching with true url $result" }
result
}
binding = DataBindingUtil.setContentView(this, R.layout.activity_image)
binding.onCreate()
tempFile = File(cacheDir(this), imageHash)
launch(CoroutineExceptionHandler { _, throwable -> loadError(throwable) }) {
downloadImageTo(tempFile)
binding.imageProgress.fadeOut()
binding.imagePhoto.setImage(ImageSource.uri(frostUriFromFile(tempFile)))
fabAction = FabStates.DOWNLOAD
binding.imagePhoto.animate().alpha(1f).scaleXY(1f).start()
}
}
val layout =
if (!imageText.isNullOrBlank()) R.layout.activity_image else R.layout.activity_image_textless
setContentView(layout)
image_container.setBackgroundColor(baseBackgroundColor)
image_text?.setTextColor(if (Prefs.blackMediaBg) Color.WHITE else Prefs.textColor)
image_text?.setBackgroundColor(
(if (Prefs.blackMediaBg) Color.BLACK else Prefs.bgColor)
.colorToForeground(0.2f).withAlpha(255)
)
image_text?.text = imageText
image_progress.tint(if (Prefs.blackMediaBg) Color.WHITE else Prefs.accentColor)
image_panel?.addPanelSlideListener(object :
SlidingUpPanelLayout.SimplePanelSlideListener() {
override fun onPanelSlide(panel: View, slideOffset: Float) {
if (slideOffset == 0f && !image_fab.isShown) image_fab.show()
else if (slideOffset != 0f && image_fab.isShown) image_fab.hide()
image_text?.alpha = slideOffset / 2 + 0.5f
private fun ActivityImageBinding.onCreate() {
imageContainer.setBackgroundColor(baseBackgroundColor)
this@ImageActivity.imageText.also { text ->
if (text == null) {
imageText.gone()
} else {
imageText.setTextColor(if (Prefs.blackMediaBg) Color.WHITE else Prefs.textColor)
imageText.setBackgroundColor(
(if (Prefs.blackMediaBg) Color.BLACK else Prefs.bgColor)
.colorToForeground(0.2f).withAlpha(255)
)
imageText.text = text
bottomBehavior = BottomSheetBehavior.from<View>(imageText).apply {
setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
override fun onSlide(bottomSheet: View, slideOffset: Float) {
if (slideOffset == 0f && !imageFab.isShown) imageFab.show()
else if (slideOffset != 0f && imageFab.isShown) imageFab.hide()
imageText.alpha = slideOffset / 2 + 0.5f
}
override fun onStateChanged(bottomSheet: View, newState: Int) {
// No op
}
})
}
imageText.bringToFront()
}
})
image_fab.setOnClickListener { fabAction.onClick(this) }
image_photo.setOnImageEventListener(object :
}
imageProgress.tint(if (Prefs.blackMediaBg) Color.WHITE else Prefs.accentColor)
imageFab.setOnClickListener { fabAction.onClick(this@ImageActivity) }
imagePhoto.setOnImageEventListener(object :
SubsamplingScaleImageView.DefaultOnImageEventListener() {
override fun onImageLoadError(e: Exception) {
loadError(e)
@ -196,18 +224,11 @@ class ImageActivity : KauBaseActivity() {
setFrostColors {
themeWindow = false
}
tempFile = File(cacheDir(this), imageHash)
launch(CoroutineExceptionHandler { _, throwable -> loadError(throwable) }) {
downloadImageTo(tempFile)
image_progress.fadeOut()
image_photo.setImage(ImageSource.uri(frostUriFromFile(tempFile)))
fabAction = FabStates.DOWNLOAD
image_photo.animate().alpha(1f).scaleXY(1f).start()
dragHelper = ViewDragHelper.create(image_drag, ViewDragCallback()).apply {
setEdgeTrackingEnabled(ViewDragHelper.EDGE_TOP or ViewDragHelper.EDGE_BOTTOM)
}
image_drag.dragHelper = dragHelper
dragHelper = ViewDragHelper.create(imageDrag, ViewDragCallback()).apply {
setEdgeTrackingEnabled(ViewDragHelper.EDGE_TOP or ViewDragHelper.EDGE_BOTTOM)
}
imageDrag.dragHelper = dragHelper
imageDrag.viewToIgnore = imageText
}
private inner class ViewDragCallback : ViewDragHelper.Callback() {
@ -216,7 +237,8 @@ class ImageActivity : KauBaseActivity() {
private var scrollToTop = false
override fun tryCaptureView(view: View, i: Int): Boolean {
return true
L.d { "Try capture ${view.id} $i ${binding.imagePhoto.id} ${binding.imageText.id}" }
return view === binding.imagePhoto
}
override fun getViewHorizontalDragRange(child: View): Int = 0
@ -231,18 +253,22 @@ class ImageActivity : KauBaseActivity() {
dy: Int
) {
super.onViewPositionChanged(changedView, left, top, dx, dy)
//make sure that we are using the proper axis
scrollPercent = abs(top.toFloat() / image_container.height)
scrollToTop = top < 0
val multiplier = max(1f - scrollPercent, 0f)
image_fab.alpha = multiplier
image_panel?.alpha = multiplier
image_container.setBackgroundColor(baseBackgroundColor.adjustAlpha(multiplier))
with(binding) {
//make sure that we are using the proper axis
scrollPercent = abs(top.toFloat() / imageContainer.height)
scrollToTop = top < 0
val multiplier = max(1f - scrollPercent, 0f)
if (scrollPercent >= 1) {
if (!isFinishing) {
finish()
overridePendingTransition(0, 0)
imageFab.alpha = multiplier
imageText.alpha =
multiplier * (if (bottomBehavior.state == BottomSheetBehavior.STATE_COLLAPSED) 0.5f else 1f)
imageContainer.setBackgroundColor(baseBackgroundColor.adjustAlpha(multiplier))
if (scrollPercent >= 1) {
if (!isFinishing) {
finish()
overridePendingTransition(0, 0)
}
}
}
}
@ -256,7 +282,7 @@ class ImageActivity : KauBaseActivity() {
else -> 0
}
dragHelper.settleCapturedViewAt(0, finalTop)
image_drag.invalidate()
binding.imageDrag.invalidate()
}
override fun clampViewPositionHorizontal(child: View, left: Int, dx: Int): Int = 0

View File

@ -18,20 +18,34 @@ package com.pitchedapps.frost.views
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Rect
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.widget.FrameLayout
import androidx.core.view.ViewCompat
import androidx.customview.widget.ViewDragHelper
import com.pitchedapps.frost.utils.L
class DragFrame @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {
var dragHelper: ViewDragHelper? = null
var viewToIgnore: View? = null
private val rect = Rect()
private val location = IntArray(2)
private var shouldIgnore: Boolean = false
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
if (event.actionMasked == MotionEvent.ACTION_DOWN) {
shouldIgnore = shouldIgnore(event)
}
if (shouldIgnore) {
return false
}
return try {
dragHelper?.shouldInterceptTouchEvent(event) ?: false
} catch (e: Exception) {
@ -41,6 +55,12 @@ class DragFrame @JvmOverloads constructor(
@SuppressLint("ClickableViewAccessibility")
override fun onTouchEvent(event: MotionEvent): Boolean {
if (event.actionMasked == MotionEvent.ACTION_DOWN) {
shouldIgnore = shouldIgnore(event)
}
if (shouldIgnore) {
return false
}
try {
dragHelper?.processTouchEvent(event) ?: return false
} catch (e: Exception) {
@ -49,6 +69,25 @@ class DragFrame @JvmOverloads constructor(
return true
}
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
if (event.actionMasked == MotionEvent.ACTION_DOWN) {
shouldIgnore = shouldIgnore(event)
}
if (shouldIgnore) {
return false
}
return super.dispatchTouchEvent(event)
}
private fun shouldIgnore(event: MotionEvent): Boolean {
val v = viewToIgnore ?: return false
v.getDrawingRect(rect)
v.getLocationOnScreen(location)
rect.offset(location[0], location[1])
L.d { "${event.rawX} ${event.x} ${event.rawY} ${event.y} ${rect}" }
return rect.contains(event.rawX.toInt(), event.rawY.toInt())
}
override fun computeScroll() {
super.computeScroll()
if (dragHelper?.continueSettling(true) == true) {

View File

@ -1,44 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/image_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ProgressBar
android:id="@+id/image_progress"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/image_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="@dimen/kau_fab_margin"
android:visibility="invisible" />
<com.pitchedapps.frost.views.DragFrame
android:id="@+id/image_drag"
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/image_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.sothree.slidinguppanel.SlidingUpPanelLayout
android:id="@+id/image_panel"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="bottom"
app:umanoPanelHeight="44dp"
app:umanoShadowHeight="0dp">
<ProgressBar
android:id="@+id/image_progress"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
<TextView
android:id="@+id/image_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alpha="0.5"
android:padding="@dimen/kau_padding_normal" />
<com.pitchedapps.frost.views.DragFrame
android:id="@+id/image_drag"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
android:id="@+id/image_photo"
@ -48,8 +27,25 @@
android:scaleX="0.9"
android:scaleY="0.9" />
</com.sothree.slidinguppanel.SlidingUpPanelLayout>
</com.pitchedapps.frost.views.DragFrame>
</com.pitchedapps.frost.views.DragFrame>
<TextView
android:id="@+id/image_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alpha="0.5"
android:padding="@dimen/kau_padding_normal"
app:behavior_peekHeight="44dp"
app:layout_behavior="@string/bottom_sheet_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/image_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="@dimen/kau_fab_margin"
android:visibility="invisible" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</layout>

View File

@ -1,37 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/image_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:id="@+id/image_progress"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
<com.pitchedapps.frost.views.DragFrame
android:id="@+id/image_drag"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
android:id="@+id/image_photo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:alpha="0"
android:scaleX="0.9"
android:scaleY="0.9" />
</com.pitchedapps.frost.views.DragFrame>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/image_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="@dimen/kau_fab_margin"
android:visibility="invisible" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -1,5 +1,7 @@
object Versions {
const val targetSdk = 28
const val andxBiometric = "1.0.0-alpha04"
// https://mvnrepository.com/artifact/org.apache.commons/commons-text