瀏覽代碼

chore: implemented undo functionality when deleted note

beautusg 7 年之前
父節點
當前提交
863922e713

+ 7 - 17
app/src/main/java/com/sduduzog/slimlauncher/MainActivity.kt

@@ -123,24 +123,14 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh
     companion object {
 
         fun resolveTheme(i: Int): Int {
-            when (i) {
-                1 -> {
-                    return R.style.AppDarkTheme
-                }
-                2 -> {
-                    return R.style.AppGreyTheme
-                }
-                3 -> {
-                    return R.style.AppTealTheme
-                }
-                4 -> {
-                    return R.style.AppCandyTheme
-                }
-                5 -> {
-                    return R.style.AppPinkTheme
-                }
+            return when (i) {
+                1 -> R.style.AppDarkTheme
+                2 -> R.style.AppGreyTheme
+                3 -> R.style.AppTealTheme
+                4 -> R.style.AppCandyTheme
+                5 -> R.style.AppPinkTheme
+                else -> R.style.AppTheme
             }
-            return R.style.AppTheme
         }
     }
 

+ 1 - 1
app/src/main/java/com/sduduzog/slimlauncher/dialogs/RenameAppDialog.kt

@@ -18,7 +18,7 @@ class RenameAppDialog : DialogFragment() {
     private lateinit var model: MainViewModel
 
     override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
-        val view = LayoutInflater.from(context).inflate(R.layout.rename_app_dialog_edit_text, customise_apps_fragment, false)
+        val view = LayoutInflater.from(context).inflate(R.layout.rename_dialog_edit_text, customise_apps_fragment, false)
         val editText: EditText = view.findViewById(R.id.rename_editText)
         editText.text.append(app.appName)
         val builder = AlertDialog.Builder(context!!)

+ 57 - 0
app/src/main/java/com/sduduzog/slimlauncher/dialogs/RenameNoteDialog.kt

@@ -0,0 +1,57 @@
+package com.sduduzog.slimlauncher.dialogs
+
+import android.app.Dialog
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.widget.EditText
+import android.widget.Toast
+import androidx.appcompat.app.AlertDialog
+import androidx.fragment.app.DialogFragment
+import com.sduduzog.slimlauncher.R
+import com.sduduzog.slimlauncher.data.MainViewModel
+import com.sduduzog.slimlauncher.data.model.Note
+import kotlinx.android.synthetic.main.voice_note_fragment.*
+
+class RenameNoteDialog : DialogFragment() {
+
+    private lateinit var note: Note
+    private lateinit var viewModel: MainViewModel
+
+    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+        val view = LayoutInflater.from(context).inflate(R.layout.rename_dialog_edit_text, voice_note_fragment, false)
+        val editText: EditText = view.findViewById(R.id.rename_editText)
+        editText.text.append(note.title)
+        val builder = AlertDialog.Builder(context!!)
+        builder.setTitle("Rename Audio")
+        builder.setView(view)
+        builder.setPositiveButton("DONE") { _, _ ->
+            val name = editText.text.toString()
+            updateNote(name)
+        }
+        editText.setOnEditorActionListener { v, _, _ ->
+            val title = v.text.toString()
+            updateNote(title)
+            this@RenameNoteDialog.dismiss()
+            true
+        }
+        return builder.create()
+    }
+
+    private fun updateNote(newTitle: String) {
+        if (newTitle.isNotEmpty()) {
+            note.title = newTitle
+            viewModel.update(note)
+        } else {
+            Toast.makeText(context, "Couldn't save, title shouldn't be empty", Toast.LENGTH_LONG).show()
+        }
+    }
+
+    companion object {
+        fun getInstance(note: Note, viewModel: MainViewModel): RenameNoteDialog {
+            return RenameNoteDialog().apply {
+                this.note = note
+                this.viewModel = viewModel
+            }
+        }
+    }
+}

+ 43 - 16
app/src/main/java/com/sduduzog/slimlauncher/ui/main/NotesFragment.kt

@@ -6,7 +6,6 @@ import android.os.Bundle
 import android.os.Handler
 import android.os.SystemClock
 import android.text.format.DateUtils
-import android.util.Log
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
@@ -23,6 +22,7 @@ import com.sduduzog.slimlauncher.data.MainViewModel
 import com.sduduzog.slimlauncher.data.model.Note
 import com.sduduzog.slimlauncher.utils.*
 import kotlinx.android.synthetic.main.notes_fragment.*
+import java.io.File
 
 
 class NotesFragment : BaseFragment(), OnShitDoneToNotesListener {
@@ -40,12 +40,25 @@ class NotesFragment : BaseFragment(), OnShitDoneToNotesListener {
             timeInMilliseconds = SystemClock.uptimeMillis()
             updateTime = timeInMilliseconds - startTime
             val time = DateUtils.formatElapsedTime(updateTime / 1000)
-            notes_fragment_create_note.text = getString(R.string.notes_fragment_stop_recording)
+            notes_fragment_create_note.text = getString(R.string.notes_fragment_stop)
             notes_fragment_counter.text = getString(R.string.notes_fragment_counter, time)
             customHandler.postDelayed(this, 100)
         }
     }
 
+    private var isDeletePending = false
+    private var noteToDelete: Note? = null
+
+    private val deleteNoteThread = Runnable {
+        if (isDeletePending) {
+            noteToDelete?.let {
+                deleteNote(it)
+            }
+        }
+        notes_fragment_create_note.text = getString(R.string.notes_fragment_create_new_note)
+        isDeletePending = false
+    }
+
     override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
         return inflater.inflate(R.layout.notes_fragment, container, false)
     }
@@ -81,15 +94,19 @@ class NotesFragment : BaseFragment(), OnShitDoneToNotesListener {
         val itemTouchHelper = ItemTouchHelper(simpleItemTouchCallback)
         itemTouchHelper.attachToRecyclerView(notes_fragment_list)
         notes_fragment_create_note.setOnClickListener {
-            if (voiceRecorder.state == VoiceRecorder.Companion.State.RECORDING) {
-                try {
+            when {
+                isDeletePending -> {
+                    isDeletePending = false
+                    adapter.notifyDataSetChanged()
+                    notes_fragment_create_note.text = getString(R.string.notes_fragment_create_new_note)
+                }
+                voiceRecorder.state == VoiceRecorder.RECORDING -> try {
                     voiceRecorder.stopRecording()
                     voiceRecorder.save(viewModel)
                 } catch (e: RuntimeException) {
-                    Log.e("check", "$e")
+                    // I pray this doesn't happen
                 }
-            } else {
-                Navigation.findNavController(notes_fragment)
+                else -> Navigation.findNavController(notes_fragment)
                         .navigate(R.id.action_notesFragment_to_editNoteFragment)
             }
         }
@@ -106,12 +123,12 @@ class NotesFragment : BaseFragment(), OnShitDoneToNotesListener {
         voiceRecorder.stateLiveData.observe(this, Observer {
             it?.let { state ->
                 when (state) {
-                    VoiceRecorder.Companion.State.RECORDING -> startTimer()
-                    VoiceRecorder.Companion.State.IDLE -> {
+                    VoiceRecorder.RECORDING -> startTimer()
+                    VoiceRecorder.IDLE -> {
                         notes_fragment_create_note.text = getString(R.string.notes_fragment_create_new_note)
                         stopTimer()
                     }
-                    VoiceRecorder.Companion.State.ERROR -> stopTimer()
+                    VoiceRecorder.ERROR -> stopTimer()
                 }
             }
         })
@@ -128,6 +145,11 @@ class NotesFragment : BaseFragment(), OnShitDoneToNotesListener {
         notes_fragment_counter.visibility = View.GONE
     }
 
+    private fun deleteNote(note: Note) {
+        if (note.type == Note.TYPE_VOICE) File(note.path).delete()
+        viewModel.remove(note)
+    }
+
     override fun onStart() {
         super.onStart()
         voiceRecorder.onStart()
@@ -140,7 +162,7 @@ class NotesFragment : BaseFragment(), OnShitDoneToNotesListener {
     }
 
     override fun onView(note: Note) {
-        if (voiceRecorder.state == VoiceRecorder.Companion.State.RECORDING) return
+        if (voiceRecorder.state == VoiceRecorder.RECORDING) return
         val bundle = Bundle()
         bundle.putLong(getString(R.string.nav_key_note), note.id)
         if (note.type == Note.TYPE_TEXT)
@@ -152,11 +174,16 @@ class NotesFragment : BaseFragment(), OnShitDoneToNotesListener {
     }
 
     override fun onDelete(note: Note) {
-        if (voiceRecorder.state == VoiceRecorder.Companion.State.RECORDING) {
-            notes_fragment_list.adapter?.notifyDataSetChanged()
-            return
+        notes_fragment_create_note.text = getString(R.string.notes_fragment_undo)
+        if (isDeletePending) {
+            customHandler.removeCallbacks(deleteNoteThread)
+            noteToDelete?.let {
+                deleteNote(it)
+            }
         }
-        if (note.type == Note.TYPE_VOICE) context?.deleteFile(note.path)
-        viewModel.remove(note)
+
+        noteToDelete = note.copy()
+        isDeletePending = true
+        customHandler.postDelayed(deleteNoteThread, 2000)
     }
 }

+ 49 - 8
app/src/main/java/com/sduduzog/slimlauncher/ui/notes/VoiceNoteFragment.kt

@@ -2,6 +2,8 @@ package com.sduduzog.slimlauncher.ui.notes
 
 import android.media.MediaPlayer
 import android.os.Bundle
+import android.os.Handler
+import android.os.SystemClock
 import android.text.format.DateUtils
 import android.view.LayoutInflater
 import android.view.View
@@ -12,6 +14,7 @@ import androidx.lifecycle.ViewModelProviders
 import com.sduduzog.slimlauncher.R
 import com.sduduzog.slimlauncher.data.MainViewModel
 import com.sduduzog.slimlauncher.data.model.Note
+import com.sduduzog.slimlauncher.dialogs.RenameNoteDialog
 import com.sduduzog.slimlauncher.utils.BaseFragment
 import kotlinx.android.synthetic.main.voice_note_fragment.*
 
@@ -21,6 +24,20 @@ class VoiceNoteFragment : BaseFragment() {
 
     private lateinit var viewModel: MainViewModel
     private var mediaPlayer: MediaPlayer? = null
+    private val customHandler = Handler()
+    private var timeInMilliseconds = 0L
+    private var startTime = 0L
+    private var updateTime = 0L
+    private var pauseTime = 0L
+    private val updateTimerThread = object : Runnable {
+        override fun run() {
+            timeInMilliseconds = SystemClock.uptimeMillis()
+            updateTime = (timeInMilliseconds + pauseTime) - startTime
+            val time = DateUtils.formatElapsedTime(updateTime / 1000)
+            voice_note_fragment_counter.text = getString(R.string.notes_fragment_counter, time)
+            customHandler.postDelayed(this, 100)
+        }
+    }
 
     override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
         return inflater.inflate(R.layout.voice_note_fragment, container, false)
@@ -46,20 +63,38 @@ class VoiceNoteFragment : BaseFragment() {
         voice_note_fragment_play.setOnClickListener {
             if (mediaPlayer!!.isPlaying) {
                 mediaPlayer?.pause()
+                pauseTimer()
                 voice_note_fragment_play.text = getString(R.string.voice_note_fragment_play)
             } else {
                 mediaPlayer?.start()
+                startTimer()
                 voice_note_fragment_play.text = getString(R.string.voice_note_fragment_pause)
             }
         }
         voice_note_fragment_stop.setOnClickListener {
             mediaPlayer?.stop()
             mediaPlayer?.prepare()
+            stopTimer()
             showDuration()
             voice_note_fragment_play.text = getString(R.string.voice_note_fragment_play)
         }
     }
 
+    private fun startTimer() {
+        startTime = SystemClock.uptimeMillis()
+        customHandler.postDelayed(updateTimerThread, 0)
+    }
+
+    private fun pauseTimer() {
+        pauseTime = updateTime
+        customHandler.removeCallbacks(updateTimerThread)
+    }
+
+    private fun stopTimer() {
+        pauseTime = 0L
+        customHandler.removeCallbacks(updateTimerThread)
+    }
+
     override fun onStop() {
         super.onStop()
         mediaPlayer?.let {
@@ -73,15 +108,15 @@ class VoiceNoteFragment : BaseFragment() {
         note.title?.let { title -> if (title.isNotBlank()) voice_note_fragment_title.text = title }
         voice_note_fragment_body.text = note.body
         mediaPlayer = MediaPlayer()
+        mediaPlayer?.setOnCompletionListener {
+            stopTimer()
+            showDuration()
+            voice_note_fragment_play.text = getString(R.string.voice_note_fragment_play)
+        }
         mediaPlayer?.setDataSource(note.path)
         mediaPlayer?.prepare()
         showDuration()
-        voice_note_fragment_options.setOnClickListener {
-            showPopupMenu(it).setOnMenuItemClickListener {
-
-                true
-            }
-        }
+        voice_note_fragment_options.setOnClickListener { showPopupMenu(it, note) }
     }
 
     private fun showDuration() {
@@ -91,10 +126,16 @@ class VoiceNoteFragment : BaseFragment() {
         }
     }
 
-    private fun showPopupMenu(view: View): PopupMenu {
+
+    private fun showPopupMenu(view: View, note: Note) {
         val popup = PopupMenu(context!!, view)
         popup.menuInflater.inflate(R.menu.voice_note_popup_menu, popup.menu)
+        popup.setOnMenuItemClickListener {
+            if (it.itemId == R.id.vn_menu_rename) {
+                RenameNoteDialog.getInstance(note, viewModel).show(fragmentManager, "note_dialog")
+            }
+            true
+        }
         popup.show()
-        return popup
     }
 }

+ 2 - 6
app/src/main/java/com/sduduzog/slimlauncher/utils/HomeWatcher.kt

@@ -28,17 +28,13 @@ class HomeWatcher(private val context: Context) {
         }
     }
 
-    @Suppress("PrivatePropertyName")
     inner class InnerReceiver : BroadcastReceiver() {
 
-        private val SYSTEM_DIALOG_REASON_KEY = "reason"
-        private val SYSTEM_DIALOG_REASON_HOME_KEY = "homekey"
-
         override fun onReceive(context: Context?, intent: Intent?) {
             if (intent == null) return
             if (intent.action != Intent.ACTION_CLOSE_SYSTEM_DIALOGS) return
-            val reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY) ?: return
-            if (reason != SYSTEM_DIALOG_REASON_HOME_KEY) return
+            val reason = intent.getStringExtra("reason") ?: return
+            if (reason != "homekey") return
             listener?.onHomePressed()
         }
     }

+ 9 - 11
app/src/main/java/com/sduduzog/slimlauncher/utils/VoiceRecorder.kt

@@ -12,12 +12,12 @@ import java.util.*
 
 class VoiceRecorder private constructor() {
 
-    var state: State = State.IDLE
+    var state: Int = IDLE
         set(value) {
             stateLiveData.value = value
             field = value
         }
-    val stateLiveData = MutableLiveData<State>()
+    val stateLiveData = MutableLiveData<Int>()
     private var note: Note? = null
     private var mediaRecorder: MediaRecorder? = null
 
@@ -34,17 +34,17 @@ class VoiceRecorder private constructor() {
         try {
             mediaRecorder?.prepare()
             mediaRecorder?.start()
-            state = State.RECORDING
+            state = RECORDING
         } catch (e: IOException) {
             note = null
-            state = State.ERROR
+            state = ERROR
         }
     }
 
     fun stopRecording() {
         mediaRecorder?.stop()
         mediaRecorder?.reset()
-        state = State.IDLE
+        state = IDLE
     }
 
     fun save(viewModel: MainViewModel) {
@@ -52,7 +52,7 @@ class VoiceRecorder private constructor() {
     }
 
     fun onStart() {
-        state = State.IDLE
+        state = IDLE
         mediaRecorder = MediaRecorder()
     }
 
@@ -76,10 +76,8 @@ class VoiceRecorder private constructor() {
             }
         }
 
-        enum class State {
-            RECORDING,
-            IDLE,
-            ERROR
-        }
+        const val RECORDING = 1
+        const val IDLE = 2
+        const val ERROR = 4
     }
 }

+ 4 - 2
app/src/main/res/layout/notes_fragment.xml

@@ -49,11 +49,13 @@
 
     <TextView
         android:id="@+id/notes_fragment_counter"
-        android:layout_width="match_parent"
+        android:layout_width="0dp"
         android:layout_height="0dp"
         android:background="?attr/colorPrimary"
         android:gravity="center"
-        android:textSize="@dimen/_68ssp"
+        android:textSize="@dimen/_64ssp"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintTop_toBottomOf="@+id/notes_fragment_create_note"
         tools:visibility="gone" />

+ 0 - 0
app/src/main/res/layout/rename_app_dialog_edit_text.xml → app/src/main/res/layout/rename_dialog_edit_text.xml


+ 2 - 1
app/src/main/res/layout/voice_note_fragment.xml

@@ -53,6 +53,7 @@
         android:layout_height="wrap_content"
         android:textAppearance="@style/Base.AlertDialog.AppCompat"
         android:textSize="@dimen/_64ssp"
+        android:text="@string/main_placeholder_clock"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
@@ -74,7 +75,7 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:padding="@dimen/_8sdp"
-        android:text="@string/voice_note_fragment_stop"
+        android:text="@string/notes_fragment_stop"
         android:textAppearance="@style/Base.AlertDialog.AppCompat"
         android:textSize="@dimen/_18ssp"
         app:layout_constraintRight_toRightOf="@+id/voice_note_fragment_counter"

+ 3 - 3
app/src/main/res/values/strings.xml

@@ -47,7 +47,7 @@
     <string name="choose_theme_dialog_title">Choose Theme</string>
     <string name="notes_fragment_create_new_note">CREATE</string>
     <string name="notes_fragment_counter">%s</string>
-    <string name="notes_fragment_stop_recording">STOP RECORDING</string>
+    <string name="notes_fragment_stop">STOP</string>
     <string name="add_apps_fragment_search_apps">Search apps</string>
     <string name="tasks_fragment_list_item_complete">&lt;strike>%s&lt;/strike></string>
     <string name="tasks_fragment_sort">Sort</string>
@@ -56,11 +56,11 @@
     <string name="edit_note_fragment_save">SAVE</string>
     <string name="edit_note_fragment_untitled">Untitled</string>
     <string name="note_fragment_edit">EDIT</string>
-    <string name="nav_key_note">note</string>
+    <string name="nav_key_note">nav_key_note</string>
     <string name="voice_note_fragment_pause">PAUSE</string>
     <string name="voice_note_fragment_play">PLAY</string>
     <string name="menu_share">Share</string>
     <string name="menu_delete">Delete</string>
-    <string name="voice_note_fragment_stop">STOP</string>
+    <string name="notes_fragment_undo">UNDO</string>
 
 </resources>