Commit 25be2cb
feat: calendar multi select (#227)
* docs: Add multi-select batch operations plan
Addresses GitHub issue #182 - Feature: Multi-select events for batch
snooze operations.
The plan covers:
- UX flow for entering/exiting selection mode via long-press
- Selection state management in EventListAdapter
- Integration with existing search and filter chips
- Technical design for UI components and ApplicationController changes
- Implementation phases broken into 5 stages
- Testing strategy including unit, Robolectric, and instrumentation tests
Co-authored-by: wharris <wharris@upscalews.com>
* docs: Clarify multi-select scope and add future enhancements section
- Clarify that initial implementation is Active tab only in Modern UI
- Add explicit Scope section listing what's in/out of scope
- Remove Upcoming/Dismissed from open questions (moved to future)
- Add Future Enhancements section covering:
- Upcoming tab: batch pre-snooze, pre-dismiss, pre-mute
- Dismissed tab: batch restore
- Shared selection infrastructure for code reuse
Co-authored-by: wharris <wharris@upscalews.com>
* docs: Clarify Snooze All/Dismiss All filtering differences
- Note that only Snooze All/Change All supports search/filter integration
- Dismiss All does NOT support filtering (dismisses all non-recent events)
- Multi-select provides first way to batch dismiss specific events
- Add 'Relationship to Existing Features' section in Scope
- Note that multi-select dismiss ignores recency threshold
Co-authored-by: wharris <wharris@upscalews.com>
* docs: Remove batch dismiss from initial scope, add to future enhancements
Multi-select will initially only support batch snooze/change operations.
Batch dismiss is moved to future enhancements, to be implemented alongside
batch restore on the Dismissed tab for a complete workflow.
Changes:
- Remove dismiss from in-scope features
- Update UI mockups to only show snooze button
- Remove dismissSelectedEvents from ApplicationController examples
- Remove dismiss-related string resources
- Add 'Active Events Tab - Batch Dismiss' to Future Enhancements
- Note that batch dismiss should pair with batch restore
Co-authored-by: wharris <wharris@upscalews.com>
* feat: Add multi-select for batch snooze operations
Implements GitHub issue #182 - Multi-select events for batch snooze.
Changes:
- EventListAdapter: Add selection mode state, SelectionModeCallback interface,
selection methods (enterSelectionMode, exitSelectionMode, toggleSelection,
selectAllVisible, getSelectedEvents), checkbox binding, disable swipe in
selection mode
- event_card_compact.xml: Add hidden checkbox for selection indicator
- fragment_event_list.xml: Add selection action bar (top) with close button,
count text, select all; add bottom bar with snooze button
- ActiveEventsFragment: Implement SelectionModeCallback, handle long-press to
enter selection mode, setup selection UI, back press handling
- MainActivityModern: Add onSelectionModeChanged to hide toolbar/FAB/chips
- ApplicationController: Add snoozeSelectedEvents method for batch snooze
- SnoozeAllActivity: Support multi-select mode via INTENT_SELECTED_EVENT_KEYS
- strings.xml: Add multi-select related strings
Features:
- Long-press event card to enter selection mode
- Tap cards to toggle selection
- Select All button selects visible events
- Selection persists through filter/search changes
- Hidden selected count shows when events filtered out
- Snooze Selected opens snooze dialog for selected events only
Co-authored-by: wharris <wharris@upscalews.com>
* test: Add tests for multi-select functionality
Add Robolectric tests for:
- EventListAdapterSelectionTest: Tests for selection mode state management,
enterSelectionMode, exitSelectionMode, toggleSelection, selectAllVisible,
selection persistence through filter changes, hidden count calculations
- ActiveEventsFragmentRobolectricTest: Tests for selection UI visibility
- ApplicationControllerCoreRobolectricTest: Tests for snoozeSelectedEvents
including selected-only snooze, empty set handling, invalid keys,
isChange behavior
Co-authored-by: wharris <wharris@upscalews.com>
* fix: Use @testing-library/react instead of deprecated react-hooks
@testing-library/react-hooks is deprecated and doesn't fully support
React 18+. The renderHook and act functions are now built into
@testing-library/react since version 13.1+.
This fixes flaky test failures due to act() environment warnings.
Co-authored-by: wharris <wharris@upscalews.com>
* fix: Implement onItemLongClick in all EventListCallback implementors
MainActivityLegacy and UpcomingEventsFragment now implement the
onItemLongClick method added to EventListCallback interface.
Both return false as multi-select is only for Active events in Modern UI.
Co-authored-by: wharris <wharris@upscalews.com>
* fix: Remove invalid isTask and isMuted params from test
EventAlertRecord doesn't have isTask or isMuted as constructor params.
isMuted is derived from flags field.
Co-authored-by: wharris <wharris@upscalews.com>
* fix: Use correct isSpecial criteria in selection tests
isSpecial is determined by instanceStartTime == Long.MAX_VALUE,
not by negative eventId. Updated tests to use the correct criteria.
Co-authored-by: wharris <wharris@upscalews.com>
* style: Improve multi-select snooze button and labels
- Make snooze button more prominent (full width, tinted background)
- Update titles to say 'selected events' for clarity
- Distinguishes multi-select from filter-based snooze all
Co-authored-by: wharris <wharris@upscalews.com>
* feat: Show filter context in multi-select snooze dialog
When both multi-select and filters are active, the snooze dialog
now shows: '2 selected from 5 matching: filter description'
This helps users understand the context of their selection relative
to the active filters/search.
Co-authored-by: wharris <wharris@upscalews.com>
* fix: Exit selection mode when switching tabs
When switching tabs while in multi-select mode, the toolbar and FAB
were not being restored. Now we properly exit selection mode and
restore the UI when navigating away from the Active tab.
Co-authored-by: wharris <wharris@upscalews.com>
* fix: Add long-click listeners to date/time text views
Date and time text views had click listeners that consumed touch events,
preventing long-press from triggering selection mode. Now long-press
works consistently across the entire event card.
Co-authored-by: wharris <wharris@upscalews.com>
* fix: to bundle
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>1 parent 5562d89 commit 25be2cb
15 files changed
Lines changed: 1745 additions & 54 deletions
File tree
- android/app/src
- main
- java/com/github/quarck/calnotify
- app
- ui
- res
- layout
- values
- test/java/com/github/quarck/calnotify
- app
- ui
- docs/dev_todo
- src/lib/components/ui/__tests__
Lines changed: 34 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
958 | 958 | | |
959 | 959 | | |
960 | 960 | | |
| 961 | + | |
| 962 | + | |
| 963 | + | |
| 964 | + | |
| 965 | + | |
| 966 | + | |
| 967 | + | |
| 968 | + | |
| 969 | + | |
| 970 | + | |
| 971 | + | |
| 972 | + | |
| 973 | + | |
| 974 | + | |
| 975 | + | |
| 976 | + | |
| 977 | + | |
| 978 | + | |
| 979 | + | |
| 980 | + | |
| 981 | + | |
| 982 | + | |
| 983 | + | |
| 984 | + | |
| 985 | + | |
| 986 | + | |
| 987 | + | |
| 988 | + | |
| 989 | + | |
| 990 | + | |
| 991 | + | |
| 992 | + | |
| 993 | + | |
| 994 | + | |
961 | 995 | | |
962 | 996 | | |
963 | 997 | | |
| |||
Lines changed: 137 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
| 31 | + | |
31 | 32 | | |
32 | 33 | | |
33 | 34 | | |
| 35 | + | |
34 | 36 | | |
35 | 37 | | |
36 | 38 | | |
| |||
56 | 58 | | |
57 | 59 | | |
58 | 60 | | |
59 | | - | |
| 61 | + | |
60 | 62 | | |
61 | 63 | | |
62 | 64 | | |
| |||
67 | 69 | | |
68 | 70 | | |
69 | 71 | | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
70 | 78 | | |
71 | 79 | | |
72 | 80 | | |
| |||
94 | 102 | | |
95 | 103 | | |
96 | 104 | | |
| 105 | + | |
97 | 106 | | |
98 | 107 | | |
99 | 108 | | |
| |||
104 | 113 | | |
105 | 114 | | |
106 | 115 | | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
107 | 119 | | |
108 | 120 | | |
109 | 121 | | |
| |||
128 | 140 | | |
129 | 141 | | |
130 | 142 | | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
131 | 214 | | |
132 | 215 | | |
133 | 216 | | |
| |||
239 | 322 | | |
240 | 323 | | |
241 | 324 | | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
242 | 335 | | |
243 | 336 | | |
244 | 337 | | |
| |||
294 | 387 | | |
295 | 388 | | |
296 | 389 | | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
297 | 429 | | |
298 | 430 | | |
299 | 431 | | |
300 | 432 | | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
301 | 437 | | |
302 | 438 | | |
303 | 439 | | |
| |||
0 commit comments