@@ -6,6 +6,7 @@ import android.content.Context
66import android.media.MediaPlayer
77import android.os.Bundle
88import android.os.Environment
9+ import android.util.Log
910import android.view.ViewGroup
1011import android.view.Window
1112import androidx.compose.foundation.layout.Row
@@ -30,6 +31,23 @@ import com.offsetnull.bt.responder.TriggerResponder.FIRE_WHEN
3031import com.offsetnull.bt.responder.TriggerResponderEditorDoneListener
3132import com.offsetnull.bt.ui.EditorDialogScaffold
3233import java.io.File
34+ import java.io.IOException
35+
36+ private data class NotificationResult (
37+ val title : String ,
38+ val message : String ,
39+ val useLights : Boolean ,
40+ val lightColor : Int ,
41+ val useVibrate : Boolean ,
42+ val vibrateLength : Int ,
43+ val useSound : Boolean ,
44+ val soundPath : String ,
45+ val spawnNew : Boolean
46+ )
47+
48+ private const val SOUND_LIST_OFFSET = 2
49+ private const val VIBRATE_LONG = 3
50+ private const val VIBRATE_SUPER_LONG = 4
3351
3452class NotificationResponderEditor (
3553 context : Context ,
@@ -75,11 +93,7 @@ class NotificationResponderEditor(
7593 onPickLightColor = { onChecked, callback -> pickLightColor(onChecked, callback) },
7694 onPickVibrate = { onChecked, callback -> pickVibrate(onChecked, callback) },
7795 onPickSound = { onChecked, callback -> pickSound(onChecked, callback) },
78- onDone = { title, message, useLights, lightColor, useVibrate, vibrateLen,
79- useSound, soundPath, spawnNew ->
80- doFinish(title, message, useLights, lightColor, useVibrate, vibrateLen,
81- useSound, soundPath, spawnNew)
82- },
96+ onDone = { result -> doFinish(result) },
8397 onCancel = { dismiss() }
8498 )
8599 }
@@ -90,22 +104,16 @@ class NotificationResponderEditor(
90104 ))
91105 }
92106
93- private fun doFinish (
94- title : String , message : String ,
95- useLights : Boolean , lightColor : Int ,
96- useVibrate : Boolean , vibrateLength : Int ,
97- useSound : Boolean , soundPath : String ,
98- spawnNew : Boolean
99- ) {
100- responder.title = title
101- responder.message = message
102- responder.isUseDefaultLight = useLights
103- responder.colorToUse = lightColor
104- responder.isUseDefaultVibrate = useVibrate
105- responder.vibrateLength = vibrateLength
106- responder.isUseDefaultSound = useSound
107- responder.soundPath = soundPath
108- responder.isSpawnNewNotification = spawnNew
107+ private fun doFinish (result : NotificationResult ) {
108+ responder.title = result.title
109+ responder.message = result.message
110+ responder.isUseDefaultLight = result.useLights
111+ responder.colorToUse = result.lightColor
112+ responder.isUseDefaultVibrate = result.useVibrate
113+ responder.vibrateLength = result.vibrateLength
114+ responder.isUseDefaultSound = result.useSound
115+ responder.soundPath = result.soundPath
116+ responder.isSpawnNewNotification = result.spawnNew
109117
110118 if (isEditor) {
111119 finishWith.editTriggerResponder(responder, original)
@@ -161,18 +169,7 @@ class NotificationResponderEditor(
161169 }
162170
163171 @Suppress(" DEPRECATION" )
164- private fun pickSound (onChecked : Boolean , callback : (Boolean , String , String ) -> Unit ) {
165- if (! onChecked) {
166- callback(false , " " , " Currently disabled." )
167- return
168- }
169-
170- val state = Environment .getExternalStorageState()
171- if (state != Environment .MEDIA_MOUNTED_READ_ONLY && state != Environment .MEDIA_MOUNTED ) {
172- callback(false , " " , " Currently disabled." )
173- return
174- }
175-
172+ private fun scanAvailableSounds (): Map <String , String > {
176173 val paths = mutableMapOf<String , String >()
177174 val systemPaths = arrayOf(
178175 " /system/media/audio/ringtones/" ,
@@ -185,55 +182,68 @@ class NotificationResponderEditor(
185182 dir.listFiles()?.forEach { paths[it.name] = it.path }
186183 }
187184 }
188-
189185 val btDir = File (Environment .getExternalStorageDirectory(), " /BlowTorch/" )
190186 btDir.listFiles { _, name -> name.endsWith(" .mp3" ) }?.forEach {
191187 paths[it.name] = it.path
192188 }
189+ return paths
190+ }
191+
192+ private fun findCurrentSoundPosition (soundNames : List <String >, paths : Map <String , String >): Int {
193+ if (responder.isUseDefaultSound && responder.soundPath.isNullOrEmpty()) return 1
194+ soundNames.forEachIndexed { idx, name ->
195+ if (paths[name] == responder.soundPath) return idx + SOUND_LIST_OFFSET
196+ }
197+ return 0
198+ }
199+
200+ private fun previewSound (path : String ) {
201+ try {
202+ mp.stop()
203+ mp = MediaPlayer ()
204+ mp.setDataSource(path)
205+ mp.prepare()
206+ mp.start()
207+ } catch (e: IOException ) {
208+ Log .e(" NotificationEditor" , " Failed to play sound preview" , e)
209+ }
210+ }
193211
212+ private fun pickSound (onChecked : Boolean , callback : (Boolean , String , String ) -> Unit ) {
213+ if (! onChecked) {
214+ callback(false , " " , " Currently disabled." )
215+ return
216+ }
217+
218+ val state = Environment .getExternalStorageState()
219+ if (state != Environment .MEDIA_MOUNTED_READ_ONLY && state != Environment .MEDIA_MOUNTED ) {
220+ callback(false , " " , " Currently disabled." )
221+ return
222+ }
223+
224+ val paths = scanAvailableSounds()
194225 val soundNames = paths.keys.toList()
195- val items = Array (soundNames.size + 2 ) { i ->
226+ val items = Array (soundNames.size + SOUND_LIST_OFFSET ) { i ->
196227 when (i) {
197228 0 -> " Disabled"
198229 1 -> " Default"
199- else -> soundNames[i - 2 ]
200- }
201- }
202-
203- var currentPosition = 0
204- if (responder.isUseDefaultSound && responder.soundPath.isNullOrEmpty()) {
205- currentPosition = 1
206- } else {
207- soundNames.forEachIndexed { idx, name ->
208- if (paths[name] == responder.soundPath) currentPosition = idx + 2
230+ else -> soundNames[i - SOUND_LIST_OFFSET ]
209231 }
210232 }
211233
212234 val builder = AlertDialog .Builder (context)
213235 builder.setTitle(" Pick Sound: (Back to Exit)" )
214- builder.setSingleChoiceItems(items, currentPosition ) { _, which ->
236+ builder.setSingleChoiceItems(items, findCurrentSoundPosition(soundNames, paths) ) { _, which ->
215237 when (which) {
216- 0 -> {
217- callback(false , " " , " Currently disabled." )
218- }
219- 1 -> {
220- callback(true , " " , " Currently using: default" )
221- }
238+ 0 -> callback(false , " " , " Currently disabled." )
239+ 1 -> callback(true , " " , " Currently using: default" )
222240 else -> {
223- val name = soundNames[which - 2 ]
241+ val name = soundNames[which - SOUND_LIST_OFFSET ]
224242 val path = paths[name] ? : " "
225243 val label = if (path.isEmpty()) " Currently using: default"
226244 else context.getString(R .string.fmt_currently_using, path)
227245 callback(true , path, label)
228- try {
229- mp.stop()
230- mp = MediaPlayer ()
231- mp.setDataSource(path)
232- mp.prepare()
233- mp.start()
234- } catch (e: Exception ) {
235- throw RuntimeException (e)
236- }
246+ previewSound(path)
237247 }
238248 }
239249 }
@@ -257,7 +267,7 @@ private fun NotificationEditorContent(
257267 onPickLightColor : (Boolean , (Boolean , Int , String ) -> Unit ) -> Unit ,
258268 onPickVibrate : (Boolean , (Boolean , Int , String ) -> Unit ) -> Unit ,
259269 onPickSound : (Boolean , (Boolean , String , String ) -> Unit ) -> Unit ,
260- onDone : (String , String , Boolean , Int , Boolean , Int , Boolean , String , Boolean ) -> Unit ,
270+ onDone : (NotificationResult ) -> Unit ,
261271 onCancel : () -> Unit
262272) {
263273 var title by remember { mutableStateOf(initialTitle) }
@@ -276,8 +286,8 @@ private fun NotificationEditorContent(
276286 EditorDialogScaffold (
277287 title = " Notification Responder" ,
278288 onSave = {
279- onDone(title, message, useLights, lightColor, useVibrate, vibrateLength ,
280- useSound, soundPath, spawnNew)
289+ onDone(NotificationResult ( title, message, useLights, lightColor, useVibrate,
290+ vibrateLength, useSound, soundPath, spawnNew) )
281291 },
282292 onCancel = onCancel
283293 ) {
@@ -360,8 +370,8 @@ private fun formatVibrateLabel(enabled: Boolean, length: Int): String {
360370 0 -> " Currently using: default"
361371 1 -> " Currently using: Very Short"
362372 2 -> " Currently using: Short"
363- 3 -> " Currently using: Long"
364- 4 -> " Currently using: Suuper Long"
373+ VIBRATE_LONG -> " Currently using: Long"
374+ VIBRATE_SUPER_LONG -> " Currently using: Suuper Long"
365375 else -> " Currently using: default"
366376 }
367377}
0 commit comments