Add more information to rest timer notifications

From homepage - Name of exercise
From plans - Name (count/total)
This commit is contained in:
Brandon Presley 2024-02-07 17:31:41 +13:00
parent 9b881c3d58
commit 6a9e2224ec
2 changed files with 72 additions and 63 deletions

View File

@ -76,7 +76,7 @@ export default function EditSet() {
const canNotify = await check(PERMISSIONS.ANDROID.POST_NOTIFICATIONS); const canNotify = await check(PERMISSIONS.ANDROID.POST_NOTIFICATIONS);
if (canNotify === RESULTS.DENIED) if (canNotify === RESULTS.DENIED)
await request(PERMISSIONS.ANDROID.POST_NOTIFICATIONS); await request(PERMISSIONS.ANDROID.POST_NOTIFICATIONS);
if (milliseconds) NativeModules.AlarmModule.timer(milliseconds); if (milliseconds) NativeModules.AlarmModule.timer(milliseconds, `${first.name}`);
}, },
[settings] [settings]
); );

View File

@ -15,32 +15,34 @@ import com.facebook.react.bridge.*
import com.facebook.react.modules.core.DeviceEventManagerModule import com.facebook.react.modules.core.DeviceEventManagerModule
import kotlin.math.floor import kotlin.math.floor
class AlarmModule constructor(context: ReactApplicationContext?) : class AlarmModule constructor(context: ReactApplicationContext?) :
ReactContextBaseJavaModule(context) { ReactContextBaseJavaModule(context) {
private var countdownTimer: CountDownTimer? = null private var countdownTimer: CountDownTimer? = null
var currentMs: Long = 0 var currentMs: Long = 0
var running = false private var running = false
private var currentDescription = ""
override fun getName(): String { override fun getName(): String {
return "AlarmModule" return "AlarmModule"
} }
private val stopReceiver = object : BroadcastReceiver() { private val stopReceiver =
@RequiresApi(Build.VERSION_CODES.O) object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) { @RequiresApi(Build.VERSION_CODES.O)
Log.d("AlarmModule", "Received stop broadcast intent") override fun onReceive(context: Context?, intent: Intent?) {
stop() Log.d("AlarmModule", "Received stop broadcast intent")
} stop()
} }
}
private val addReceiver = object : BroadcastReceiver() { private val addReceiver =
@RequiresApi(Build.VERSION_CODES.O) object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) { @RequiresApi(Build.VERSION_CODES.O)
add() override fun onReceive(context: Context?, intent: Intent?) {
} add()
} }
}
init { init {
reactApplicationContext.registerReceiver(stopReceiver, IntentFilter(STOP_BROADCAST)) reactApplicationContext.registerReceiver(stopReceiver, IntentFilter(STOP_BROADCAST))
@ -71,9 +73,8 @@ class AlarmModule constructor(context: ReactApplicationContext?) :
@ReactMethod(isBlockingSynchronousMethod = true) @ReactMethod(isBlockingSynchronousMethod = true)
fun getCurrent(): Int { fun getCurrent(): Int {
Log.d("AlarmModule", "currentMs=$currentMs") Log.d("AlarmModule", "currentMs=$currentMs")
if (running) if (running) return currentMs.toInt()
return currentMs.toInt(); return 0
return 0;
} }
@RequiresApi(api = Build.VERSION_CODES.O) @RequiresApi(api = Build.VERSION_CODES.O)
@ -87,19 +88,21 @@ class AlarmModule constructor(context: ReactApplicationContext?) :
val manager = getManager() val manager = getManager()
manager.cancel(AlarmService.NOTIFICATION_ID_DONE) manager.cancel(AlarmService.NOTIFICATION_ID_DONE)
manager.cancel(NOTIFICATION_ID_PENDING) manager.cancel(NOTIFICATION_ID_PENDING)
val params = Arguments.createMap().apply { val params =
putString("minutes", "00") Arguments.createMap().apply {
putString("seconds", "00") putString("minutes", "00")
} putString("seconds", "00")
}
reactApplicationContext reactApplicationContext
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
.emit("tick", params) .emit("tick", params)
} }
@RequiresApi(api = Build.VERSION_CODES.O) @RequiresApi(api = Build.VERSION_CODES.O)
@ReactMethod @ReactMethod
fun timer(milliseconds: Int) { fun timer(milliseconds: Int, description: String) {
Log.d("AlarmModule", "Queue alarm for $milliseconds delay") Log.d("AlarmModule", "Queue alarm for $milliseconds delay")
currentDescription = description
val manager = getManager() val manager = getManager()
manager.cancel(AlarmService.NOTIFICATION_ID_DONE) manager.cancel(AlarmService.NOTIFICATION_ID_DONE)
val intent = Intent(reactApplicationContext, AlarmService::class.java) val intent = Intent(reactApplicationContext, AlarmService::class.java)
@ -112,7 +115,7 @@ class AlarmModule constructor(context: ReactApplicationContext?) :
@RequiresApi(Build.VERSION_CODES.M) @RequiresApi(Build.VERSION_CODES.M)
private fun getTimer( private fun getTimer(
endMs: Int, endMs: Int,
): CountDownTimer { ): CountDownTimer {
val builder = getBuilder() val builder = getBuilder()
return object : CountDownTimer(endMs.toLong(), 1000) { return object : CountDownTimer(endMs.toLong(), 1000) {
@ -120,34 +123,39 @@ class AlarmModule constructor(context: ReactApplicationContext?) :
override fun onTick(current: Long) { override fun onTick(current: Long) {
currentMs = current currentMs = current
val seconds = val seconds =
floor((current / 1000).toDouble() % 60).toInt().toString().padStart(2, '0') floor((current / 1000).toDouble() % 60).toInt().toString().padStart(2, '0')
val minutes = val minutes =
floor((current / 1000).toDouble() / 60).toInt().toString().padStart(2, '0') floor((current / 1000).toDouble() / 60).toInt().toString().padStart(2, '0')
builder.setContentText("$minutes:$seconds").setAutoCancel(false).setDefaults(0) builder.setContentText("$minutes:$seconds")
.setProgress(endMs, current.toInt(), false) .setAutoCancel(false)
.setCategory(NotificationCompat.CATEGORY_PROGRESS).priority = .setDefaults(0)
NotificationCompat.PRIORITY_LOW .setProgress(endMs, current.toInt(), false)
.setCategory(NotificationCompat.CATEGORY_PROGRESS)
.priority = NotificationCompat.PRIORITY_LOW
val manager = getManager() val manager = getManager()
manager.notify(NOTIFICATION_ID_PENDING, builder.build()) manager.notify(NOTIFICATION_ID_PENDING, builder.build())
val params = Arguments.createMap().apply { val params =
putString("minutes", minutes) Arguments.createMap().apply {
putString("seconds", seconds) putString("minutes", minutes)
} putString("seconds", seconds)
}
reactApplicationContext reactApplicationContext
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
.emit("tick", params) .emit("tick", params)
} }
@RequiresApi(Build.VERSION_CODES.O) @RequiresApi(Build.VERSION_CODES.O)
override fun onFinish() { override fun onFinish() {
val context = reactApplicationContext val context = reactApplicationContext
context.startService(Intent(context, AlarmService::class.java)) context.startService(Intent(context, AlarmService::class.java))
context context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) .emit(
.emit("tick", Arguments.createMap().apply { "tick",
putString("minutes", "00") Arguments.createMap().apply {
putString("seconds", "00") putString("minutes", "00")
}) putString("seconds", "00")
}
)
} }
} }
} }
@ -158,32 +166,33 @@ class AlarmModule constructor(context: ReactApplicationContext?) :
val context = reactApplicationContext val context = reactApplicationContext
val contentIntent = Intent(context, MainActivity::class.java) val contentIntent = Intent(context, MainActivity::class.java)
val pendingContent = val pendingContent =
PendingIntent.getActivity(context, 0, contentIntent, PendingIntent.FLAG_IMMUTABLE) PendingIntent.getActivity(context, 0, contentIntent, PendingIntent.FLAG_IMMUTABLE)
val addBroadcast = Intent(ADD_BROADCAST).apply { val addBroadcast = Intent(ADD_BROADCAST).apply { setPackage(context.packageName) }
setPackage(context.packageName)
}
val pendingAdd = val pendingAdd =
PendingIntent.getBroadcast(context, 0, addBroadcast, PendingIntent.FLAG_MUTABLE) PendingIntent.getBroadcast(context, 0, addBroadcast, PendingIntent.FLAG_MUTABLE)
val stopBroadcast = Intent(STOP_BROADCAST) val stopBroadcast = Intent(STOP_BROADCAST)
stopBroadcast.setPackage(context.packageName) stopBroadcast.setPackage(context.packageName)
val pendingStop = val pendingStop =
PendingIntent.getBroadcast(context, 0, stopBroadcast, PendingIntent.FLAG_IMMUTABLE) PendingIntent.getBroadcast(context, 0, stopBroadcast, PendingIntent.FLAG_IMMUTABLE)
return NotificationCompat.Builder(context, CHANNEL_ID_PENDING) return NotificationCompat.Builder(context, CHANNEL_ID_PENDING)
.setSmallIcon(R.drawable.ic_baseline_hourglass_bottom_24).setContentTitle("Resting") .setSmallIcon(R.drawable.ic_baseline_hourglass_bottom_24)
.setContentIntent(pendingContent) .setContentTitle(currentDescription)
.addAction(R.drawable.ic_baseline_stop_24, "Stop", pendingStop) .setContentIntent(pendingContent)
.addAction(R.drawable.ic_baseline_stop_24, "Add 1 min", pendingAdd) .addAction(R.drawable.ic_baseline_stop_24, "Stop", pendingStop)
.setDeleteIntent(pendingStop) .addAction(R.drawable.ic_baseline_stop_24, "Add 1 min", pendingAdd)
.setDeleteIntent(pendingStop)
} }
@RequiresApi(Build.VERSION_CODES.O) @RequiresApi(Build.VERSION_CODES.O)
private fun getManager(): NotificationManager { private fun getManager(): NotificationManager {
val notificationManager = reactApplicationContext.getSystemService( val notificationManager =
NotificationManager::class.java reactApplicationContext.getSystemService(NotificationManager::class.java)
) val timersChannel =
val timersChannel = NotificationChannel( NotificationChannel(
CHANNEL_ID_PENDING, CHANNEL_ID_PENDING, NotificationManager.IMPORTANCE_LOW CHANNEL_ID_PENDING,
) CHANNEL_ID_PENDING,
NotificationManager.IMPORTANCE_LOW
)
timersChannel.setSound(null, null) timersChannel.setSound(null, null)
timersChannel.description = "Progress on rest timers." timersChannel.description = "Progress on rest timers."
notificationManager.createNotificationChannel(timersChannel) notificationManager.createNotificationChannel(timersChannel)