The RefreshControl on DraggableFlatList never worked because the
library wraps its FlatList in a GestureDetector with Gesture.Pan(),
which intercepts vertical swipes before RefreshControl can detect
them — particularly with activationDistance=0 in position sort mode.
Replace with a toolbar refresh button (RefreshCw icon) on inbox and
list detail screens. The button uses an Animated spin during refresh,
matching the web UX. Removes all dead RefreshControl code and the
useless refreshControl prop.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Web: hide "Add subtask" button when depth >= 1 in TaskItem.
API: reject task creation if parentId points to a task that already
has a parentId (max depth validation).
Mobile: hide subtask section in task detail when viewing a subtask.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Web: add a RefreshCw button next to the list title in TaskList that
calls router.refresh() with a spin animation.
Mobile: add RefreshControl to DraggableFlatList on both inbox and
list detail screens, using the app's blue accent color.
Also deduplicate list insert values in sync/route.ts (review feedback).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The (app)/layout.tsx was calling cookieStore.set() which is forbidden in
Server Components under Next.js 16 (only allowed in Server Actions and
Route Handlers). This caused a 500 error immediately after Logto login.
Also includes: mobile sync client improvements, i18n updates, web API
rate limiting, Bearer token support for mobile clients, and Dockerfile
optimizations.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Long-press a subtask to edit its title inline. Tap X to delete
with confirmation. Tap still toggles completion.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Instead of removing the time filter entirely, let users choose the
widget display period (1 week, 2 weeks, 4 weeks, or all tasks) from
Settings. Default remains 2 weeks for backward compatibility.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace `finally` with `catch` in [id].tsx handleSave so goBack is
not called when updateTask/setTagsForTask fails
- Extract shared goBack helper into src/lib/navigation.ts
- Both [id].tsx and new.tsx now import goBack from the shared module
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace all router.back() calls with a goBack() helper that checks
router.canGoBack() first and falls back to router.replace('/') when
there is no screen to return to. In the task edit screen, change
catch to finally so the save button always resets its disabled state
even if updateTask/setTagsForTask throws.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Buttons (X, back, save, delete, export) had ~28px hit areas,
causing missed taps. Increased padding to p-2.5 + hitSlop for
~44px touch targets. Bump version to 1.2.4.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace manual keyboard listeners and RN KeyboardAvoidingView with
react-native-keyboard-controller which handles edge-to-edge correctly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
KeyboardAvoidingView does not work with edgeToEdgeEnabled on Android.
New approach: listen to Keyboard events, dynamically set spacer height
to actual keyboard height, and scrollToEnd when subtask input is focused.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
edge-to-edge mode disables classic adjustResize, so behavior must be
"padding" on both platforms to push content above the keyboard.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Set KeyboardAvoidingView behavior to undefined on Android to avoid
conflict with native adjustResize (was causing double-resize)
- Call syncWidgetData() at app startup to populate subtasks in widget cache
- Keyboard.addListener + adjustResize handles scroll correctly on Android
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace unreliable setTimeout scroll with Keyboard.addListener('keyboardDidShow')
- Track subtask input focus state to scroll only when relevant
- Increase bottom spacer from h-32 to h-80 for more scroll room
- Enlarge expand/collapse button (32px with background) and arrow (fontSize 18)
- Ensure subtasks array is always initialized in widget handler
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix keyboard hiding subtask input: use precise scrollTo with onLayout position instead of unreliable scrollToEnd (#6)
- Add expand/collapse button in widget for tasks with subtasks (#9)
- Subtasks are now toggleable directly from the widget
- Widget state (expanded tasks) persisted via AsyncStorage
- Update CLAUDE.md with widget docs, build/deploy process, and release workflow
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add saving guard to prevent duplicate task creation on rapid taps
- Add pending subtasks UI to new task screen with local add/remove
- Wrap both task screens in KeyboardAvoidingView with scrollToEnd on subtask focus
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Widget adapts to app theme (light/dark/system) via AsyncStorage
- Add "Check for updates" button querying Forgejo releases API
- Add "Contact us or report a bug" mailto link in settings
- Bump version to 1.0.1
Closes#1, closes#2, closes#3
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allow viewing and changing a task's list from the task detail page.
Uses the same chip-style selector with list icons and colors as the
new task screen.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Validate UUID format on all route params to prevent arbitrary DB queries
from malicious deep links. Truncate user input (titles, notes, names) to
safe lengths, clamp priority to [0,3], validate recurrence values, and
add schema validation on widget JSON data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Search icon in toolbar opens a text input that filters tasks by title
and notes in real-time. Drag-to-reorder is disabled while searching.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace static delete buttons with swipe gestures (left to delete, right
to complete) and add drag-to-reorder support using react-native-draggable-flatlist.
Inbox is pinned at top of lists tab with a GripVertical drag handle for
custom lists. Polling is paused during drag operations to prevent state conflicts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Scheduled task reminders via expo-notifications with configurable
offset (at time, 1h, 3h, 1 day before)
- Optional calendar sync via expo-calendar (creates/updates/removes
events in a dedicated Simpl-Liste calendar)
- ICS export with RRULE support for inbox, lists, and individual tasks
- New migration adding calendar_event_id to tasks table
- Settings UI for notifications toggle, reminder offset, and calendar sync
- Export buttons in inbox toolbar, list header, and task detail
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace inline list creation with a modal supporting color palette and
icon grid selection. Long-press to edit existing lists. Display chosen
icon/color in list rows, detail header, and task creation chips.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Tags: create/edit/delete tags with color picker modal, assign to tasks
- Sort: sort tasks by position, priority, due date, title, created date
- Filters: filter by status, priority, due date, tag
- Recurrence: daily/weekly/monthly/yearly with auto-creation on completion
- Fix removeTagFromTask bug (was deleting all tags instead of specific one)
- Tag editor redesigned as modal for better keyboard UX
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Clicking a list now shows its tasks instead of opening new task form
- Add list/[id] detail screen
- Replace crypto.randomUUID() with expo-crypto (Hermes compatibility)
- Add SQL transformer for Drizzle migration files
- Improve priority color visibility in dark mode (lighter variants)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>