chore/code-quality-cleanup #24

Merged
uwayss merged 12 commits from chore/code-quality-cleanup into main 2026-08-30 21:30:52 +00:00
Owner

Code quality cleanup and some bug fixes

Code quality cleanup and some bug fixes
IntervalSwitcher was replaced by SegmentedControl and is no longer
imported anywhere; it also re-declared TimeInterval alongside types.ts.
DateScroller held a FlatList ref it never read.

The comments removed here either name what the next line does, describe
a shape the code will supposedly grow into, or record when a number last
changed - which is what the history is for.

Also drops the leading path-header comments from plugins/, which eaca123
removed from src/ but not here, and the blank lines that removal left at
the top of four files in constants/.
A release build has no console attached, so a log left in app code is
debug residue that never gets read. error and warn stay allowed: those
do surface in crash tooling. The rule sits in the ts/tsx block so the
config plugins and scripts/bundle.cjs keep printing to the terminal.

Removes the eight calls in notificationService that this makes fatal,
and replaces lightColor with the notification color from app.json - the
value it held came from the expo-notifications docs example and matched
nothing in the palette.
tsconfig sets noImplicitAny, but six explicit anys opted back out of it.

settingsData gains SettingsActions, so a typo in an action name is a
compile error rather than an undefined call at tap time, and
AnyModalSettingsItem, which lets SettingsScreen drop both casts in
handleItemPress. Two narrow assertions remain in SettingsOptionModal
where TypeScript cannot correlate stateKey with options across the
union; a comment says so.

StatsScreen gains PrayerStats and StatsResult. The four repeated stat
blocks now build from PRAYER_STATUS_IDS, and interval is renamed to
selectedInterval so the setter no longer shadows the global setInterval.

Names the two magic numbers these files carried: the modal's dismiss
delay and the fixed graph window.
isColorLight measured colors.light[key] while the segment was painted
with theme.colors[key], so on the dark theme the contrast decision was
made against a color that was not on screen. Measure the one actually
painted.

The two themes give missed different values, which is where this would
have shown first.
DAYS was a module constant, so its labels were translated once at import
time. i18n.locale is only set from stored settings when initialize()
runs, which happens later, so the abbreviations froze in the device
locale and ignored every language change afterwards. Build them during
render instead.

The "how many times per {{interval}}?" prompt interpolated
type.replace('ly', ''), which is the English "month" or "year" in all six
languages - Arabic was gluing its definite article onto it, giving
"في الmonth". Replace the placeholder with a full sentence per interval,
since the noun does not decline the same way across these languages.
The parent picker listed every deed, including the one being edited.
Choosing itself stranded it: the home screen hides any deed that has a
parent, and nothing else lists it, so it disappeared from the app with
only the deed manager left to reach it. Longer cycles did the same.

Exclude the edited deed and everything beneath it. The sweep repeats
until it stops finding new members rather than assuming a parent appears
before its children in the list.
The two fields disagreed about what made a goal valid: the unit field
required a value and a non-empty unit, but the value field stored a goal
as soon as it had a number. Entering a target and skipping the unit
saved {value: 5, unit: ''}, which renders as "5 / 5 " everywhere
progress is shown.

Commit both fields through one helper so they cannot drift apart again.
Log dates are written with formatISO as a local calendar day, but read
back with new Date(), which parses a bare YYYY-MM-DD as UTC midnight.
East of Greenwich that is merely the same day at an odd hour; west of it
the date lands on the previous local day, so logs on the edge of a range
were counted into the wrong interval or dropped from the graph.

parseISO reads a date-only string as local midnight, which is what
formatISO wrote.
addOrUpdateLog copied the array with a spread and then assigned into the
element. The spread is shallow, so that wrote through to the same log
object the previous state still referenced: the value changed underneath
anything holding the old array, and readers comparing references saw no
change at all.

Log ids came from Date.now(), which collided whenever two logs were
written in the same millisecond. A deed has at most one log per day, so
deed and date already identify the entry - the same scheme demoData
already uses. Nothing reads log.id; logs are always found by deedId and
date.
resetData put settings back to the defaults, which include language 'en',
but left i18n.locale and I18nManager pointing at the old language. State
and screen disagreed: settings read English while every string stayed in
the previous language.

Apply the locale the way initialize() does. As in setLanguage, forceRTL
only takes effect on the next launch, so a reset out of Arabic or Persian
leaves the layout mirrored until then.
The switcher sat inside renderContent, which returns early with a
spinner, so changing the interval removed the control that had just been
used. A mis-tap could not be corrected until the recalculation finished.

Move it into the screen body, above the part that swaps for a spinner.
isLoading went with it: it only ever restated displayData === null, and
testing displayData directly narrows the type for the branch below.
docs: record that the activity graph is independent of the switcher
All checks were successful
Checks / checks (pull_request) Successful in 22s
277379b6a1
The spec said the switcher filters "the entire screen" and that the
graph's X-axis follows the selected interval. The code has never done
this, and on reflection it should not: the graph exists to scroll back
through history and fits about ten days on screen, so following the
switcher would cap Weeks at seven days of scrollback - less than it
shows now - and make Years hundreds of columns deep.

Describe what the graph actually does, note what showing longer ranges
would require, and say that the switcher stays usable while the figures
under it reload.
uwayss merged commit 8ae4f798c1 into main 2026-08-30 21:30:52 +00:00
uwayss deleted branch chore/code-quality-cleanup 2026-08-30 21:30:53 +00:00
uwayss referenced this pull request from a commit 2026-08-30 21:30:54 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
uwayss/muhsin!24
No description provided.