package com.anas4tech.noteable import android.app.PendingIntent import android.appwidget.AppWidgetManager import android.content.BroadcastReceiver import android.content.ComponentName import android.content.Context import android.content.Intent import android.net.Uri import es.antonborri.home_widget.HomeWidgetBackgroundIntent /** Handles native checklist taps without opening MainActivity or the note editor. */ class WidgetItemClickReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val noteId = intent.getIntExtra(EXTRA_NOTE_ID, -1) when (intent.action) { ACTION_TOGGLE_CHECK -> { val itemId = intent.getIntExtra(EXTRA_ITEM_ID, -1) if (noteId > 0 && itemId > 0) toggleChecklistItem(context, noteId, itemId) } ACTION_OPEN_NOTE -> { if (noteId <= 0) return val openIntent = Intent(context, MainActivity::class.java).apply { action = Intent.ACTION_VIEW data = Uri.parse("noteable://open-note/$noteId?source=list_view") addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP) } context.startActivity(openIntent) } } } companion object { const val ACTION_TOGGLE_CHECK = "com.anas4tech.noteable.action.TOGGLE_CHECK" const val ACTION_OPEN_NOTE = "com.anas4tech.noteable.action.OPEN_NOTE" const val EXTRA_NOTE_ID = "note_id" const val EXTRA_ITEM_ID = "check_item_id" private const val PREFERENCES = "HomeWidgetPreferences" /** Updates the visible preference immediately and queues its exact value for Drift. */ @JvmStatic fun toggleChecklistItem( context: Context, noteId: Int, itemId: Int, refreshEdgeOverlay: Boolean = true ): Boolean { if (noteId <= 0 || itemId <= 0) return false val prefs = context.getSharedPreferences(PREFERENCES, Context.MODE_PRIVATE) val completedKey = "widget_check_${itemId}_completed" val pendingKey = "widget_check_${itemId}_pending" val pendingCompletedKey = "widget_check_${itemId}_pending_completed" val nextCompleted = !prefs.getBoolean(completedKey, false) // commit() updates in-memory preferences synchronously so a widget refresh // cannot observe the old value directly after the tap. prefs.edit() .putBoolean(completedKey, nextCompleted) .putBoolean(pendingKey, true) .putBoolean(pendingCompletedKey, nextCompleted) .commit() refreshWidgets(context, refreshEdgeOverlay) try { val backgroundIntent = HomeWidgetBackgroundIntent.getBroadcast( context, Uri.parse("noteable://toggle-check?noteId=$noteId&itemId=$itemId&completed=$nextCompleted") ) backgroundIntent.send() } catch (_: PendingIntent.CanceledException) { // The queued preference remains durable and will be applied by the next app refresh. } return nextCompleted } private fun refreshWidgets(context: Context, refreshEdgeOverlay: Boolean) { val manager = AppWidgetManager.getInstance(context) val provider = ComponentName(context, NoteableWidgetProvider::class.java) manager.getAppWidgetIds(provider).forEach { widgetId -> manager.notifyAppWidgetViewDataChanged(widgetId, R.id.widget_notes) } if (refreshEdgeOverlay && EdgeNotesOverlayService.isRunning(context)) { context.startService( Intent(context, EdgeNotesOverlayService::class.java) .setAction(EdgeNotesOverlayService.ACTION_REFRESH) ) } } } }