feat(qs): add a 'New event' Quick Settings tile
A stateless TileService that opens the create-event form on today — the same action as the launcher 'New event' shortcut and the agenda widget's +. Reuses MainActivity.openCreateIntent; wrapped in unlockAndRun and using the API 34+ startActivityAndCollapse(PendingIntent) form (deprecated Intent form below 34). No new permission (BIND_QUICK_SETTINGS_TILE is system-side). Discoverability: Settings → New event form gains an 'Add Quick Settings tile' row that fires StatusBarManager.requestAddTileService (API 33+); on older versions the tile is still addable manually from the system QS editor. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
package de.jeanlucmakiola.calendula.qs
|
||||
|
||||
import android.app.PendingIntent
|
||||
import android.os.Build
|
||||
import android.service.quicksettings.TileService
|
||||
import de.jeanlucmakiola.calendula.MainActivity
|
||||
import kotlinx.datetime.TimeZone
|
||||
import kotlinx.datetime.toLocalDateTime
|
||||
import kotlin.time.Clock
|
||||
|
||||
/**
|
||||
* Quick Settings tile: tapping it opens the create-event form on today — the
|
||||
* same action as the launcher "New event" shortcut and the agenda widget's "+".
|
||||
* A stateless action tile, so there is no on/off state to keep in sync.
|
||||
*/
|
||||
class NewEventTileService : TileService() {
|
||||
|
||||
override fun onClick() {
|
||||
super.onClick()
|
||||
val today = Clock.System.now()
|
||||
.toLocalDateTime(TimeZone.currentSystemDefault()).date
|
||||
val intent = MainActivity.openCreateIntent(this, today)
|
||||
// Launch only once the device is unlocked: creating an event behind the
|
||||
// keyguard makes no sense, and the shade can't start an activity over a
|
||||
// locked screen anyway.
|
||||
unlockAndRun {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||
val pending = PendingIntent.getActivity(
|
||||
this,
|
||||
0,
|
||||
intent,
|
||||
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT,
|
||||
)
|
||||
startActivityAndCollapse(pending)
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
startActivityAndCollapse(intent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,16 @@
|
||||
package de.jeanlucmakiola.calendula.ui.settings
|
||||
|
||||
import android.Manifest
|
||||
import android.app.StatusBarManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.drawable.Icon
|
||||
import android.os.Build
|
||||
import android.os.PowerManager
|
||||
import android.provider.Settings
|
||||
import androidx.annotation.RequiresApi
|
||||
import android.text.format.DateFormat
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
@@ -80,6 +84,7 @@ import de.jeanlucmakiola.calendula.data.prefs.CalendarReminderOverride
|
||||
import de.jeanlucmakiola.calendula.data.prefs.ThemeMode
|
||||
import de.jeanlucmakiola.calendula.data.prefs.WeekStartPref
|
||||
import de.jeanlucmakiola.calendula.domain.EventFormField
|
||||
import de.jeanlucmakiola.calendula.qs.NewEventTileService
|
||||
import de.jeanlucmakiola.calendula.ui.crash.CrashReportDialog
|
||||
import de.jeanlucmakiola.calendula.ui.crash.openIssueTracker
|
||||
import de.jeanlucmakiola.calendula.ui.crash.submitCrashReport
|
||||
@@ -514,9 +519,39 @@ private fun EventFormScreen(
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
// One-tap add of the "New event" Quick Settings tile. The system prompt
|
||||
// is API 33+; on older versions the tile is still addable manually from
|
||||
// the QS editor, so the row simply doesn't appear there.
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
Spacer(Modifier.height(24.dp))
|
||||
val context = LocalContext.current
|
||||
GroupedRow(
|
||||
title = stringResource(R.string.settings_qs_tile),
|
||||
summary = stringResource(R.string.settings_qs_tile_hint),
|
||||
position = Position.Alone,
|
||||
onClick = { requestAddQsTile(context) },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask the system to add the "New event" Quick Settings tile (API 33+). The OS
|
||||
* shows its own confirmation dialog and handles the already-added case, so no
|
||||
* result handling is needed here.
|
||||
*/
|
||||
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||
private fun requestAddQsTile(context: Context) {
|
||||
val statusBar = context.getSystemService(StatusBarManager::class.java) ?: return
|
||||
statusBar.requestAddTileService(
|
||||
ComponentName(context, NewEventTileService::class.java),
|
||||
context.getString(R.string.qs_tile_new_event_label),
|
||||
Icon.createWithResource(context, R.drawable.ic_qs_new_event),
|
||||
context.mainExecutor,
|
||||
) { /* result code unused — the system surfaces its own feedback */ }
|
||||
}
|
||||
|
||||
/**
|
||||
* Reminder-notifications toggle (v1.4), mirroring the onboarding step.
|
||||
* Turning it on re-requests `POST_NOTIFICATIONS` when missing (API 33+) —
|
||||
|
||||
Reference in New Issue
Block a user