feat: Material You colors, settings backup/restore, add LICENSE
Build APK / build (push) Successful in 1m33s
Build APK / build (push) Successful in 1m33s
- Material You toggle: bars/rings use wallpaper-derived system accents on Android 12+ (ThemeColors.sessionFill/weeklyFill), Claude brand colors otherwise - Settings backup/restore via SAF (export/import JSON); session cookie never included so backups are safe to store anywhere - Add source-available LICENSE (mirrors SyncFlow's), with Anthropic trademark note Built + installed on emulator, launches clean.
This commit is contained in:
@@ -30,6 +30,33 @@ class MainActivity : AppCompatActivity() {
|
||||
private val notifPermLauncher =
|
||||
registerForActivityResult(ActivityResultContracts.RequestPermission()) { /* result handled silently */ }
|
||||
|
||||
/** SAF: pick a destination file and write the current settings JSON to it. */
|
||||
private val exportLauncher =
|
||||
registerForActivityResult(ActivityResultContracts.CreateDocument("application/json")) { uri ->
|
||||
if (uri == null) return@registerForActivityResult
|
||||
try {
|
||||
contentResolver.openOutputStream(uri)?.use { it.write(prefs.exportSettings().toByteArray()) }
|
||||
toast("Settings exported")
|
||||
} catch (_: Exception) { toast("Export failed") }
|
||||
}
|
||||
|
||||
/** SAF: pick a backup file and apply it. */
|
||||
private val importLauncher =
|
||||
registerForActivityResult(ActivityResultContracts.OpenDocument()) { uri ->
|
||||
if (uri == null) return@registerForActivityResult
|
||||
try {
|
||||
val json = contentResolver.openInputStream(uri)?.bufferedReader()?.use { it.readText() } ?: ""
|
||||
if (prefs.importSettings(json)) {
|
||||
toast("Settings restored")
|
||||
// Reflect restored prefs immediately: re-sync switches and redraw any widgets.
|
||||
binding.switchNotify.isChecked = prefs.isNotifyEnabled()
|
||||
binding.switchRingStyle.isChecked = prefs.getWidgetStyle() == PreferencesManager.STYLE_RINGS
|
||||
binding.switchMaterialYou.isChecked = prefs.isMaterialYou()
|
||||
ClaudeUsageWidget.notifyDataChanged(this)
|
||||
} else toast("Not a valid settings file")
|
||||
} catch (_: Exception) { toast("Import failed") }
|
||||
}
|
||||
|
||||
/** Live refresh loop that runs only while the app is in the foreground. */
|
||||
private var autoRefreshJob: Job? = null
|
||||
|
||||
@@ -67,6 +94,8 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
setupNotificationSettings()
|
||||
setupWidgetStyleSetting()
|
||||
setupMaterialYouSetting()
|
||||
setupBackupRestore()
|
||||
|
||||
binding.btnDebug.setOnClickListener {
|
||||
if (binding.tvDebugInfo.visibility == android.view.View.GONE) {
|
||||
@@ -122,6 +151,28 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
/** Material You toggle — switches the bars/rings to wallpaper-derived accents (Android 12+). */
|
||||
private fun setupMaterialYouSetting() {
|
||||
binding.switchMaterialYou.isChecked = prefs.isMaterialYou()
|
||||
binding.switchMaterialYou.setOnCheckedChangeListener { _, checked ->
|
||||
prefs.setMaterialYou(checked)
|
||||
ClaudeUsageWidget.notifyDataChanged(this)
|
||||
}
|
||||
}
|
||||
|
||||
/** Export/Import settings via the Storage Access Framework (no extra permissions needed). */
|
||||
private fun setupBackupRestore() {
|
||||
binding.btnExportSettings.setOnClickListener {
|
||||
exportLauncher.launch("claude-usage-settings.json")
|
||||
}
|
||||
binding.btnImportSettings.setOnClickListener {
|
||||
importLauncher.launch(arrayOf("application/json", "text/*", "*/*"))
|
||||
}
|
||||
}
|
||||
|
||||
private fun toast(msg: String) =
|
||||
android.widget.Toast.makeText(this, msg, android.widget.Toast.LENGTH_SHORT).show()
|
||||
|
||||
private fun requestNotificationPermission() {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) return
|
||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS)
|
||||
|
||||
Reference in New Issue
Block a user