From d4f90c28ce51640d9e76952ea454c52d6c8663ba Mon Sep 17 00:00:00 2001 From: Piotr Garlej Date: Mon, 25 May 2026 18:14:19 +0200 Subject: [PATCH 1/5] Add per-item delete in list edit form and hide checked items in widget - ListForm: add trash icon button per row so users can delete individual items while editing a list - Android widget: filter out checked items so only unchecked tasks are shown; preserve original JSON indices so checkbox taps still toggle the correct item in the database Co-Authored-By: Claude Sonnet 4.6 --- .../widget/NoteListRemoteViewsFactory.kt | 4 +-- .../simplenotepad/widget/WidgetDbHelper.kt | 4 +-- components/ListForm.tsx | 31 ++++++++++++++----- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/android/app/src/main/java/com/pgarr/simplenotepad/widget/NoteListRemoteViewsFactory.kt b/android/app/src/main/java/com/pgarr/simplenotepad/widget/NoteListRemoteViewsFactory.kt index 2525569..e6c730d 100644 --- a/android/app/src/main/java/com/pgarr/simplenotepad/widget/NoteListRemoteViewsFactory.kt +++ b/android/app/src/main/java/com/pgarr/simplenotepad/widget/NoteListRemoteViewsFactory.kt @@ -29,7 +29,7 @@ class NoteListRemoteViewsFactory( boundListId = -1 return } - items = list.items + items = list.items.filter { !it.checked } listTitle = list.title boundListId = list.id } @@ -63,7 +63,7 @@ class NoteListRemoteViewsFactory( // Fill-in intent carries position and listId to the broadcast receiver val fillIntent = Intent().apply { - putExtra("item_index", position) + putExtra("item_index", item.originalIndex) putExtra("list_id", boundListId) } rv.setOnClickFillInIntent(R.id.item_checkbox, fillIntent) diff --git a/android/app/src/main/java/com/pgarr/simplenotepad/widget/WidgetDbHelper.kt b/android/app/src/main/java/com/pgarr/simplenotepad/widget/WidgetDbHelper.kt index e416628..1e07de4 100644 --- a/android/app/src/main/java/com/pgarr/simplenotepad/widget/WidgetDbHelper.kt +++ b/android/app/src/main/java/com/pgarr/simplenotepad/widget/WidgetDbHelper.kt @@ -6,7 +6,7 @@ import org.json.JSONArray import java.io.File // Mirrors your expo-sqlite DB schema exactly -data class WidgetListItem(val text: String, val checked: Boolean) +data class WidgetListItem(val text: String, val checked: Boolean, val originalIndex: Int = 0) data class WidgetList(val id: Int, val title: String, val items: List) object WidgetDbHelper { @@ -96,7 +96,7 @@ object WidgetDbHelper { val obj = arr.optJSONObject(i) ?: return@mapNotNull null val text = obj.optString("text", "") val checked = obj.optBoolean("checked", false) - WidgetListItem(text = text, checked = checked) + WidgetListItem(text = text, checked = checked, originalIndex = i) } } catch (_: Exception) { emptyList() diff --git a/components/ListForm.tsx b/components/ListForm.tsx index 052d8db..af57236 100644 --- a/components/ListForm.tsx +++ b/components/ListForm.tsx @@ -1,8 +1,10 @@ import { Button } from '@/components/ui/button'; +import { Icon } from '@/components/ui/icon'; import { Input } from '@/components/ui/input'; import { Text } from '@/components/ui/text'; import { useKeyboardOffset } from '@/hooks/useKeyboardOffset'; import { ListItem } from '@/lib/dataStorage'; +import { Trash2Icon } from 'lucide-react-native'; import { useCallback, useState } from 'react'; import { KeyboardAvoidingView, Platform, ScrollView, View } from 'react-native'; @@ -35,6 +37,10 @@ export function ListForm({ ); }, []); + const handleDeleteRow = useCallback((index: number) => { + setItems((current) => current.filter((_, i) => i !== index)); + }, []); + const handleSave = useCallback(async () => { const trimmedTitle = title.trim(); if (!trimmedTitle) return; @@ -70,14 +76,23 @@ export function ListForm({ showsVerticalScrollIndicator={false}> {items.map((item, index) => ( - handleUpdateRow(index, text)} - editable={!saving} - /> + + handleUpdateRow(index, text)} + editable={!saving} + /> + + ))}