ankidroid / Anki-Android

AnkiDroid: Anki flashcards on Android. Your secret trick to achieve superhuman information retention.
GNU General Public License v3.0
7.93k stars 2.16k forks source link

Check Pronunciation: "Hold to record" #16282

Open david-allison opened 2 weeks ago

david-allison commented 2 weeks ago

I proposed a 'hold to record' feature, but it requires additional work

Requirements Recording should start as soon as the button is pressed, rather than after a long press

The following patch implements the functionality, but recording only starts after the long-press time if it's a 'hold' action


Subject: [PATCH] feat(audio-recorder): hold to record
Holding the record button starts a recording
releasing the record stops the recording

This streamlines UX for an advanced user,
as it takes the recording process from 2 to 1 taps

---
Index: AnkiDroid/src/main/java/com/ichi2/audio/AudioRecordingController.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/AnkiDroid/src/main/java/com/ichi2/audio/AudioRecordingController.kt b/AnkiDroid/src/main/java/com/ichi2/audio/AudioRecordingController.kt
--- a/AnkiDroid/src/main/java/com/ichi2/audio/AudioRecordingController.kt   (revision 8a72fe586cbde02375a0542845d51734c268ed40)
+++ b/AnkiDroid/src/main/java/com/ichi2/audio/AudioRecordingController.kt   (date 1714232522230)
@@ -41,6 +41,8 @@
 import com.ichi2.anki.multimediacard.fields.IFieldController
 import com.ichi2.anki.showThemedToast
 import com.ichi2.anki.snackbar.showSnackbar
+import com.ichi2.anki.ui.OnHoldListener
+import com.ichi2.anki.ui.setOnHoldListener
 import com.ichi2.anki.utils.elapsed
 import com.ichi2.anki.utils.formatAsString
 import com.ichi2.audio.AudioRecordingController.RecordingState.AppendToRecording
@@ -189,6 +191,27 @@
             Timber.i("primary 'record' button clicked")
             controlAudioRecorder()
         }
+
+        // if the recorder is in the 'cleared' state
+        // holding the 'record' button should start a recording
+        // releasing the 'record' button should complete the recording
+        recordButton.setOnHoldListener(object : OnHoldListener {
+            override fun onHoldStart(): Boolean {
+                if (state != ImmediatePlayback.CLEARED && state != AppendToRecording.CLEARED) return false
+                Timber.d("holding 'record' button'")
+                controlAudioRecorder()
+                return true
+            }
+
+            override fun onHoldEnd() {
+                Timber.d("finished holding 'record' button'")
+                if (state is ImmediatePlayback) {
+                    controlAudioRecorder()
+                } else {
+                    saveButton?.performClick()
+                }
+            }
+        })

         playAudioButton.setOnClickListener {
             Timber.i("play/pause clicked")
Index: AnkiDroid/src/main/java/com/ichi2/anki/ui/OnHoldListener.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/OnHoldListener.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/OnHoldListener.kt
new file mode 100644
--- /dev/null   (date 1714232522229)
+++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/OnHoldListener.kt   (date 1714232522229)
@@ -0,0 +1,49 @@
+/*
+ *  Copyright (c) 2024 David Allison <davidallisongithub@gmail.com>
+ *
+ *  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.ichi2.anki.ui
+
+import android.view.MotionEvent
+import android.view.View
+
+interface OnHoldListener {
+    fun onHoldStart(): Boolean
+    fun onHoldEnd()
+}
+
+fun View.setOnHoldListener(listener: OnHoldListener) {
+    val listenerWrapper = object : View.OnTouchListener, View.OnLongClickListener {
+
+        var isHolding = false
+        override fun onTouch(v: View?, event: MotionEvent?): Boolean {
+            if (event?.action == MotionEvent.ACTION_UP && isHolding) {
+                isHolding = false
+                listener.onHoldEnd()
+                return true
+            }
+            return false
+        }
+
+        override fun onLongClick(v: View?): Boolean {
+            if (listener.onHoldStart()) {
+                isHolding = true
+            }
+            return true
+        }
+    }
+    this.setOnLongClickListener(listenerWrapper)
+    this.setOnTouchListener(listenerWrapper)
+}
Giyutomioka-SS commented 2 weeks ago

can i take this up ?

david-allison commented 2 weeks ago

Sure, you'll want to rebase it on https://github.com/ankidroid/Anki-Android/pull/16248#issuecomment-2079849844, and it'll be blocked on the base PR being merged