From 1e26196e9eb63239192af5d4cda772e565ac999a Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Sun, 26 Jul 2020 03:11:33 +0300 Subject: [PATCH 1/6] ViewImageFragment: finalize transition to BigImageViewer. Now it should correctly handle EXIF rotation, do not stuck at transition and pick preview image if it's in cache but full image isn't --- .../tusky/fragment/ViewImageFragment.kt | 187 ++++++++++++------ 1 file changed, 128 insertions(+), 59 deletions(-) diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/ViewImageFragment.kt b/app/src/main/java/com/keylesspalace/tusky/fragment/ViewImageFragment.kt index 86948403..7707076f 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/ViewImageFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/ViewImageFragment.kt @@ -25,11 +25,15 @@ import android.os.Bundle import android.util.Log import android.view.* import android.widget.TextView +import androidx.exifinterface.media.ExifInterface import com.bumptech.glide.Glide import com.bumptech.glide.load.DataSource import com.bumptech.glide.load.engine.GlideException import com.bumptech.glide.request.RequestListener +import com.bumptech.glide.request.target.CustomTarget import com.bumptech.glide.request.target.Target +import com.bumptech.glide.request.transition.Transition +import com.github.piasy.biv.BigImageViewer import com.github.piasy.biv.loader.ImageLoader import com.github.piasy.biv.view.GlideImageViewFactory import com.keylesspalace.tusky.R @@ -42,9 +46,10 @@ import kotlinx.android.synthetic.main.fragment_view_image.* import java.io.File import java.lang.Exception import kotlin.math.abs +import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView -class ViewImageFragment : ViewMediaFragment(), ImageLoader.Callback, View.OnTouchListener { +class ViewImageFragment : ViewMediaFragment() { interface PhotoActionsListener { fun onBringUp() fun onDismiss() @@ -60,6 +65,10 @@ class ViewImageFragment : ViewMediaFragment(), ImageLoader.Callback, View.OnTouc @Volatile private var startedTransition = false + private var uri = Uri.EMPTY + private var previewUri = Uri.EMPTY + private var showingPreview = false + override lateinit var descriptionView: TextView override fun onAttach(context: Context) { super.onAttach(context) @@ -70,7 +79,11 @@ class ViewImageFragment : ViewMediaFragment(), ImageLoader.Callback, View.OnTouc descriptionView = mediaDescription photoView.transitionName = url startedTransition = false - loadImageFromNetwork(url, previewUrl) + uri = Uri.parse(url) + if(previewUrl != null && !previewUrl.equals(url)) { + previewUri = Uri.parse(previewUrl) + } + loadImageFromNetwork() } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { @@ -78,51 +91,52 @@ class ViewImageFragment : ViewMediaFragment(), ImageLoader.Callback, View.OnTouc return inflater.inflate(R.layout.fragment_view_image, container, false) } - private var lastY = 0.0f - private var swipeStartedWithOneFinger = false private lateinit var gestureDetector : GestureDetector - override fun onTouch(v: View, event: MotionEvent): Boolean { - // This part is for scaling/translating on vertical move. - // We use raw coordinates to get the correct ones during scaling - gestureDetector.onTouchEvent(event) + private val imageOnTouchListener = object : View.OnTouchListener { + private var lastY = 0.0f + private var swipeStartedWithOneFinger = false - if(event.pointerCount != 1) { - swipeStartedWithOneFinger = false - return false - } + override fun onTouch(v: View, event: MotionEvent): Boolean { + // This part is for scaling/translating on vertical move. + // We use raw coordinates to get the correct ones during scaling + gestureDetector.onTouchEvent(event) - var result = false - - when(event.action) { - MotionEvent.ACTION_DOWN -> { - swipeStartedWithOneFinger = true - lastY = event.rawY - } - MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { - onGestureEnd() + if(event.pointerCount != 1) { swipeStartedWithOneFinger = false + return false } - MotionEvent.ACTION_MOVE -> { - if(swipeStartedWithOneFinger && photoView.ssiv.scale <= photoView.ssiv.minScale) { - val diff = event.rawY - lastY - // This code is to prevent transformations during page scrolling - // If we are already translating or we reached the threshold, then transform. - if (photoView.translationY != 0f || abs(diff) > 40) { - photoView.translationY += (diff) - val scale = (-abs(photoView.translationY) / 720 + 1).coerceAtLeast(0.5f) - photoView.scaleY = scale - photoView.scaleX = scale - lastY = event.rawY + + when(event.action) { + MotionEvent.ACTION_DOWN -> { + swipeStartedWithOneFinger = true + lastY = event.rawY + } + MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { + onGestureEnd() + swipeStartedWithOneFinger = false + } + MotionEvent.ACTION_MOVE -> { + if(swipeStartedWithOneFinger && photoView.ssiv.scale <= photoView.ssiv.minScale) { + val diff = event.rawY - lastY + // This code is to prevent transformations during page scrolling + // If we are already translating or we reached the threshold, then transform. + if (photoView.translationY != 0f || abs(diff) > 40) { + photoView.translationY += (diff) + val scale = (-abs(photoView.translationY) / 720 + 1).coerceAtLeast(0.5f) + photoView.scaleY = scale + photoView.scaleX = scale + lastY = event.rawY + } } - result = true } } - } - return result + return false + } } + @SuppressLint("ClickableViewAccessibility") override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -135,7 +149,7 @@ class ViewImageFragment : ViewMediaFragment(), ImageLoader.Callback, View.OnTouc }) // photoView.setOnTouchListener(this) - photoView.setImageLoaderCallback(this) + photoView.setImageLoaderCallback(imageLoaderCallback) photoView.setImageViewFactory(GlideImageViewFactory()) val arguments = this.requireArguments() @@ -190,33 +204,88 @@ class ViewImageFragment : ViewMediaFragment(), ImageLoader.Callback, View.OnTouc photoView.ssiv?.recycle() } - private fun loadImageFromNetwork(url: String, previewUrl: String?) { - photoView.showImage(Uri.parse(previewUrl), Uri.parse(url)) + private inner class DummyCacheTarget(val ctx: Context, val requestPreview : Boolean) : CustomTarget() { + override fun onLoadCleared(placeholder: Drawable?) {} + override fun onLoadFailed(errorDrawable: Drawable?) { + if(requestPreview) { + // no preview, no full image in cache, load full image + // forget about fancy transition + showingPreview = false + photoView.showImage(uri) + } else { + // let's start downloading full image that we supposedly don't have + BigImageViewer.prefetch(uri) + + // meanwhile poke cache about preview image + Glide.with(ctx).asFile() + .load(previewUri) + .dontAnimate() + .onlyRetrieveFromCache(true) + .into(DummyCacheTarget(ctx, true)) + } + } + + override fun onResourceReady(resource: File, transition: Transition?) { + showingPreview = requestPreview + if(requestPreview) { + // have preview cached but not full image + photoView.showImage(previewUri, uri, true) + } else { + photoView.showImage(uri) + } + } } - override fun onSuccess(image: File?) { - progressBar?.hide() // Always hide the progress bar on success - photoActionsListener.onBringUp() - photoView.ssiv?.setOnTouchListener(this) - } - - override fun onFail(error: Exception?) { - progressBar?.hide() - photoActionsListener.onBringUp() - } - - override fun onCacheHit(imageType: Int, image: File?) { - } - - override fun onCacheMiss(imageType: Int, image: File?) { - } - - override fun onFinish() { - } - - override fun onProgress(progress: Int) { + private fun loadImageFromNetwork() { + Glide.with(this).asFile() + .load(uri) + .onlyRetrieveFromCache(true) + .dontAnimate() + .into(DummyCacheTarget(context!!, false)) } override fun onTransitionEnd() { + // if we had preview, load full image, as transition has ended + if (showingPreview) { + showingPreview = false + photoView.loadMainImageNow() + } + } + + private val imageLoaderCallback = object : ImageLoader.Callback { + override fun onSuccess(image: File?) { + if(!showingPreview) { + progressBar?.hide() + photoView.ssiv?.let { + it.orientation = SubsamplingScaleImageView.ORIENTATION_USE_EXIF + it.setOnTouchListener(imageOnTouchListener) + } + } + } + + override fun onFail(error: Exception?) { + progressBar?.hide() + } + + override fun onCacheHit(imageType: Int, image: File?) { + // image is here, bring up the activity! + photoActionsListener.onBringUp() + } + + override fun onStart() { + // cache miss but image is downloading, bring up the activity + photoActionsListener.onBringUp() + } + + override fun onCacheMiss(imageType: Int, image: File?) { + // this callback is useless because it's called after + // image is downloaded or pulled from cache + // so in case of cache miss, onStart is used + } + + override fun onFinish() {} + override fun onProgress(progress: Int) { + // TODO: make use of it :) + } } } From 318c9b49efdee20d964f447e6390d7a81dd63cde Mon Sep 17 00:00:00 2001 From: Isak Alexander Date: Mon, 29 Jun 2020 15:41:13 +0000 Subject: [PATCH 2/6] Added translation using Weblate (Swedish) --- app/src/husky/res/values-sv/strings.xml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 app/src/husky/res/values-sv/strings.xml diff --git a/app/src/husky/res/values-sv/strings.xml b/app/src/husky/res/values-sv/strings.xml new file mode 100644 index 00000000..a6b3daec --- /dev/null +++ b/app/src/husky/res/values-sv/strings.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file From d551a2eb3f30b7d81c516a1330cf71831d455cde Mon Sep 17 00:00:00 2001 From: Isak Alexander Date: Mon, 29 Jun 2020 15:41:35 +0000 Subject: [PATCH 3/6] Translated using Weblate (Swedish) Currently translated at 47.6% (30 of 63 strings) Translation: Husky/Husky translations Translate-URL: https://l10n.mentality.rip/projects/husky/husky-translations/sv/ --- app/src/husky/res/values-sv/strings.xml | 33 ++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/app/src/husky/res/values-sv/strings.xml b/app/src/husky/res/values-sv/strings.xml index a6b3daec..16ee2c3a 100644 --- a/app/src/husky/res/values-sv/strings.xml +++ b/app/src/husky/res/values-sv/strings.xml @@ -1,2 +1,33 @@ - \ No newline at end of file + + Reagera + Ta bort reaktion + Vem reagerade + Aktivera %s + Avaktivera %s + %s reagerade av + Applikationsmanamn + Administratör + Klistermärken + Filstorleken är större än vad instanser tillåter + Ett fel inträffade vid hämtning av klistermärke + Emoji Reaktioner + Dölj tystade användare + Aktivera större anpassade emojis + Inläggssynlighet + Schemalägg inlägg + Repetera + Ta bort repetering + Dölj repeteringar + Visa repeteringar + SKICKA + SKICKA! + Svara till + Applikationswebbplats + Moderator + %s reagerade med %s på ditt inlägg + Aviseringar på nya emoji-reaktioner + Syntax på formatteringsstandard (om instansen stödjer det) + reaktioner på mina inlägg med emojis + Aktivera experimentell Pleroma-FE klistermärke (om möjligt) + \ No newline at end of file From ba7f71742f631a96c661eda7ddeceb67c542515b Mon Sep 17 00:00:00 2001 From: Karol Kosek Date: Fri, 3 Jul 2020 20:27:28 +0000 Subject: [PATCH 4/6] Translated using Weblate (Polish) Currently translated at 87.3% (55 of 63 strings) Translation: Husky/Husky translations Translate-URL: https://l10n.mentality.rip/projects/husky/husky-translations/pl/ --- app/src/husky/res/values-pl/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/husky/res/values-pl/strings.xml b/app/src/husky/res/values-pl/strings.xml index 6b4af082..edc43c89 100644 --- a/app/src/husky/res/values-pl/strings.xml +++ b/app/src/husky/res/values-pl/strings.xml @@ -60,4 +60,5 @@ Kopia postu została zapisana jako szkic Wysyłanie postu nie powiodło się. Nie ukrywaj zawartości multimedialnej oznaczonej jako wrażliwa + Zaplanowane posty \ No newline at end of file From a239dc3638747249033f7cb38aca9fca9d9c1733 Mon Sep 17 00:00:00 2001 From: Criss Date: Sun, 12 Jul 2020 18:05:23 +0000 Subject: [PATCH 5/6] Translated using Weblate (German) Currently translated at 100.0% (63 of 63 strings) Translation: Husky/Husky translations Translate-URL: https://l10n.mentality.rip/projects/husky/husky-translations/de/ --- app/src/husky/res/values-de/strings.xml | 50 ++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/app/src/husky/res/values-de/strings.xml b/app/src/husky/res/values-de/strings.xml index 1cb8ba3f..8cfaca50 100644 --- a/app/src/husky/res/values-de/strings.xml +++ b/app/src/husky/res/values-de/strings.xml @@ -18,4 +18,52 @@ Ignorierte Nutzer verstecken Reaktionen auf meine Nachrichten Antwort auf - + Sticker + Große eigene Emoji aktivieren + Experimentelle Pleroma-FE Sticker aktiveren (wenn verfügbar) + POSTEN + POSTEN! + Beitragssichtbarkeit + Wiederholen + Widerholungen verbergen + Wiederholungen anzeigen + Wiederholungsauthor anzeigen + Wiederholungen anzeigen + Beitrag planen + Es passierte ein Fehler bei dem Empfang des Stickers + Beitrags-URL teilen mit… + Beitrag teilen mit… + Beitrag wird gesendet… + Fehler beim Senden des Beitrages + Beiträge werden gesendet + Eine Kopier des Beitrages wurde in den Entwurfen gesichert + Inhalt des Beitrages teilen + Wiederholung entfernen + Geplante Beiträe + Löschen und Beitrag neu verfassen\? + Benachrichtigungen, wenn deine Beiträge wiederholt werden + %s wiederholte + Beitrag verfassen + Wiederholung entfernen + Beitrag öffnen + Für originale Audienz wiederholen + Wiederholt + Diesen Beitrag löschen\? + Fehler beim Senden des Beitrages. + %s hat deinen Beitrag wiederholt + %s hat deinen Beitrag favorisiert + Wiederholt + Benachrichigungen, wenn deine Beiträge favorisiert wurden + Bestätigung vor dem Löschen anzeigen + Meine Beiträge wurden wiederholt + Wiederholungen anzeigen + Beiträge mit sensiblen Inhalten immer anzeigen + + %s wiederholt + %s wiederholten + + Link zum Beitrag teilen + Geplante Beiträge + Wiederholt von + Beitrag + \ No newline at end of file From f5110420a82091f27e91037b6475d9d6c5eb5b10 Mon Sep 17 00:00:00 2001 From: Isak Alexander Date: Mon, 20 Jul 2020 21:10:09 +0000 Subject: [PATCH 6/6] Translated using Weblate (Swedish) Currently translated at 61.9% (39 of 63 strings) Translation: Husky/Husky translations Translate-URL: https://l10n.mentality.rip/projects/husky/husky-translations/sv/ --- app/src/husky/res/values-sv/strings.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/src/husky/res/values-sv/strings.xml b/app/src/husky/res/values-sv/strings.xml index 16ee2c3a..834060c6 100644 --- a/app/src/husky/res/values-sv/strings.xml +++ b/app/src/husky/res/values-sv/strings.xml @@ -30,4 +30,13 @@ Syntax på formatteringsstandard (om instansen stödjer det) reaktioner på mina inlägg med emojis Aktivera experimentell Pleroma-FE klistermärke (om möjligt) + Visa repeteringar + Schemalagda inlägg + Repetera till den ursprungliga målgruppen + Ta bort repetering + Öppna inlägg + Skriv inlägg + Ta bort detta inlägg\? + Öppna avsändaren av repeteringen + Repeterat \ No newline at end of file