Commit 5e6cb41
authored
feat: upcoming events aka events view look ahead 92 11 (#173)
* docs: inital plan
* docs: plan update
* docs: pre snooze and such
* docs: plan update
* docs: time picker
* docs: plan update
* docs: plan update
* docs: plan update
* docs: bugs fixs
* docs: implementation order
* docs: bug bot
* feat: milestone 1
* feat: new ui on by default easy way back to old one
* fix: build break
* fix: bug bot
ListPreference values read with wrong type causes crash
High Severity
The upcomingEventsCutoffHour and upcomingEventsFixedHours settings use
getInt() to read values, but the corresponding ListPreference elements
in misc_preferences.xml store values as strings. When a user changes
these settings via the UI, SharedPreferences.getInt() will throw a
ClassCastException. The existing codebase pattern for ListPreference
values (e.g., keepHistoryDays) correctly uses
getString(...).toIntOrNull() ?: default instead
* fix: floating action button layout
* feat: upcoming test activity
* fix: bug bot
MonitorStorage resource leak in UpcomingEventsFragment
Medium Severity
The MonitorStorage instance created in loadEvents() is passed to
UpcomingEventsProvider but is never closed. MonitorStorage implements
Closeable and holds database resources. Each call to loadEvents()
(triggered by swipe refresh or resume) leaks a storage instance. The
codebase pattern uses .use { } for proper resource cleanup with
closeable storages.
Undo callback crashes if fragment is detached
Medium Severity
The requireContext() call inside the UndoState Runnable is evaluated
when the Runnable executes (on Undo tap), not when it's created. Since
UndoManager stores this Runnable globally, if the user dismisses an
event, switches tabs (detaching the fragment), and then taps "Undo" on
the still-visible Snackbar, requireContext() will throw
IllegalStateException. The existing MainActivity pattern safely uses
this (the Activity context). The context should be captured before
creating the Runnable.
Fragments missing data update broadcast registration causes stale UI
Medium Severity
In new navigation mode, MainActivity.onDataUpdated() returns early with
comment "fragments handle their own data updates" but the fragments
(ActiveEventsFragment, UpcomingEventsFragment, DismissedEventsFragment)
don't register any BroadcastReceiver for DATA_UPDATED_BROADCAST. When
events are modified externally (e.g., dismissed via notification
action), the fragment UI shows stale data until the user manually pulls
to refresh or switches tabs. The fragments only load data in onResume()
and pull-to-refresh, missing live updates.
* fix: linter error
* fix: maybe TestActivity
* fix: a classic bug
* fix: crash on list tap
* fix: disable swipe on milestone 1 and fix legacy view tests
* fix: bug bot
Lazy settings access in background block may crash
Medium Severity
The settings property uses lazy { Settings(requireContext()) } but is
only accessed inside the background block in loadEvents(). If the user
quickly switches tabs after onResume() schedules background work, the
fragment may detach before the background thread runs. When the lazy
initializer executes requireContext() on the background thread, it
throws IllegalStateException because the fragment is no longer attached.
Unlike ActiveEventsFragment which initializes settings synchronously in
onViewCreated(), this fragment has no synchronous access path to
initialize the lazy property while attached.
* fix: bug bot
Fragment callbacks use unsafe requireContext() call
Medium Severity
The onItemRemoved and onItemRestored callbacks use requireContext()
which throws IllegalStateException if the fragment is detached. These
callbacks are triggered by ItemTouchHelper.onSwiped() after swipe
animations complete, which can occur after the user navigates away.
Other methods in the same fragments correctly use the safe pattern val
ctx = context ?: return (e.g., onItemDismiss at line 215), but these
callbacks don't follow the same pattern. This inconsistency could cause
crashes during rapid navigation.
Popup menu callback uses unsafe requireContext() call
Low Severity
The onItemClick method creates a PopupMenu and registers a
setOnMenuItemClickListener lambda that calls requireContext() at line
139. This lambda executes asynchronously when the user selects a menu
item. If the fragment becomes detached between showing the popup
and the user clicking "Restore" (e.g., during a configuration
change), requireContext() will throw IllegalStateException. The
safe pattern context ?: return with an early return in the lambda
would prevent this crash.
* docs: dependency injection patterns
* docs: fragment tweak
* fix: di for testing
* refactor: sorting stuff
* fix: make sure we aren't missing old stuff also new tests
* test: UpcomingEventsFragmentTest
* fix: build
* fix: build some tests pass
* test: fix
* fix: instrument test build
* fix: build
* fix: bug bot
Missing context null check causes crash on fragment detachment
Medium Severity
onItemClick and onItemSnooze use requireContext() which throws
IllegalStateException if the fragment is detached. Other callbacks in
this same file (onItemDismiss, onItemRemoved, onItemRestored) correctly
use val ctx = context ?: return. The sister fragments
UpcomingEventsFragment and DismissedEventsFragment also use the safe
pattern consistently. If a configuration change occurs while a user tap
is being processed, the app will crash.
* fix: maybe UpcomingEventsFragment with roboeletric
* test: maybe fix
* test: seperate test
* fix: UITestFixture
* feat: search and different page titles
* test: search1 parent 9f094cb commit 5e6cb41
57 files changed
Lines changed: 6673 additions & 78 deletions
File tree
- android/app
- src
- androidTest/java/com/github/quarck/calnotify
- dismissedeventsstorage
- eventsstorage
- testutils
- ui
- main
- java/com/github/quarck/calnotify
- calendarmonitor
- calendar
- dismissedeventsstorage
- eventsstorage
- monitorstorage
- ui
- upcoming
- res
- drawable
- layout
- values
- xml
- test/java/com/github/quarck/calnotify
- testutils
- ui
- upcoming
- docs
- dev_completed
- dev_todo
- testing
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
274 | 274 | | |
275 | 275 | | |
276 | 276 | | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
277 | 281 | | |
278 | 282 | | |
279 | 283 | | |
| |||
309 | 313 | | |
310 | 314 | | |
311 | 315 | | |
| 316 | + | |
| 317 | + | |
312 | 318 | | |
313 | 319 | | |
314 | 320 | | |
| |||
Lines changed: 146 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
Lines changed: 192 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 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 | + | |
0 commit comments