Skip to content

Split dateformat into date and time and overnote and note view#961

Merged
Crustack merged 5 commits intomainfrom
feat/842
Apr 3, 2026
Merged

Split dateformat into date and time and overnote and note view#961
Crustack merged 5 commits intomainfrom
feat/842

Conversation

@Crustack
Copy link
Copy Markdown
Owner

@Crustack Crustack commented Apr 3, 2026

Closes #842
Closes #930

  • Splits Datetime format setting into setting for overview and in note-view
  • Splits format setting into date and time format separately
  • Ensure hardcoded date formats instead of relying on phone's locale to address month/day confusion
  • Ensure for Reminders and Backup datetimes that date and time is shown (if one of them is set to none and "1 day ago" format is not used)
notallyx_issues_930_2.webm

Summary by CodeRabbit

  • New Features

    • Time format option (24-hour / AM/PM).
    • Separate date and time settings for Notes Overview and Note View.
    • New date format styles and a combined date+time picker in settings.
  • Changes

    • Removed the old “apply in note view” toggle; settings now expose distinct overview/note-view controls.
    • Date/time rendering updated to respect the new per-area preferences.
    • Translation coverage table refreshed with updated totals and percentages.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 3, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e722a369-40cc-41e6-8914-b1ea197672b1

📥 Commits

Reviewing files that changed from the base of the PR and between 0d30578 and 1ebd495.

📒 Files selected for processing (1)
  • app/src/main/java/com/philkes/notallyx/presentation/viewmodel/preference/Preference.kt

📝 Walkthrough

Walkthrough

Split date and time into separate overview and note-view preferences, introduced a TimeFormat enum and redesigned DateFormat with formatters, updated preferences, UI dialogs, adapters, view holders, and formatting helpers, removed the old apply-in-note-view toggle, and adjusted translations and documentation counts.

Changes

Cohort / File(s) Summary
Preference Model & Enums
app/src/main/java/com/philkes/notallyx/presentation/viewmodel/preference/Preference.kt, app/src/main/java/com/philkes/notallyx/presentation/viewmodel/preference/NotallyXPreferences.kt
Replaced single dateFormat + toggle with dateFormatOverview/timeFormatOverview and dateFormatNoteView/timeFormatNoteView; redesigned DateFormat (formatter lambdas + hints); added TimeFormat; added 3-source merge() overload; updated showDateCreated() and reload logic.
UI Extensions & Formatting Helpers
app/src/main/java/com/philkes/notallyx/presentation/UiExtensions.kt
displayFormattedTimestamp() now accepts timeFormat; removed older PrettyTime helpers and added Date.format(dateFormat, timeFormat, ensureFullFormat); added NotNullLiveData 3-source merge; updated Chip.setupReminderChip signature.
Settings UI & Preference Binding
app/src/main/java/com/philkes/notallyx/presentation/activity/main/fragment/settings/PreferenceBindingExtensions.kt, app/src/main/java/com/philkes/notallyx/presentation/activity/main/fragment/settings/SettingsFragment.kt
Removed dialog-with-toggle overload; added setupDateTimeFormat() and dialog layout; split settings into overview vs note-view observers and save separate date/time prefs; backup-last-run formatting uses overview prefs.
Activities & Fragments Using Formatting
app/src/main/java/com/philkes/notallyx/presentation/activity/.../NotallyFragment.kt, .../EditActivity.kt, .../PickNoteActivity.kt, .../RemindersActivity.kt
Call sites updated to pass respective dateFormat and timeFormat (overview or note view) into adapters and timestamp displays; minor wiring changes where preferences are read.
Adapters & View Holders
app/src/main/java/com/philkes/notallyx/presentation/view/main/BaseNoteAdapter.kt, .../BaseNoteVH.kt, .../reminder/ReminderAdapter.kt, .../reminder/ReminderVH.kt
Added timeFormat constructor parameter to adapters/view holders; updated timestamp and reminder-chip rendering to use explicit dateFormat + timeFormat (ensureFullFormat = true for reminders/confirmations).
Layout & View Resource Files
app/src/main/res/layout/dialog_datetime_format.xml, app/src/main/res/layout/fragment_settings.xml
Added dialog layout with DateSelectionBox and TimeSelectionBox; split fragment_settings include into DateFormatOverview and DateFormatNoteView.
Localized String Resources
app/src/main/res/values/strings.xml, app/src/main/res/values-*/strings.xml
Removed date_format_apply_in_note_view across locales; updated date_format_hint to reference datetime; added new keys for date/time overview/note-view and time formats; removed per-locale string entries.
Translation Coverage Documentation
TRANSLATIONS.md
Updated total items from 347 → 353 and adjusted translated counts/percentages for multiple languages.
CI Workflow
.github/workflows/update-translation-coverage.yaml
Restricted workflow push.branches to main.

Sequence Diagram

sequenceDiagram
    participant User as User
    participant Settings as SettingsFragment
    participant Dialog as DialogDatetimeFormatBinding
    participant Prefs as NotallyXPreferences
    participant Views as Activities/Adapters

    User->>Settings: open settings
    Settings->>Dialog: setupDateTimeFormat(overview/note)
    Dialog->>User: show date & time dropdowns
    User->>Dialog: select dateFormat, timeFormat
    User->>Dialog: confirm
    Dialog->>Prefs: save dateFormatX, timeFormatX
    Prefs->>Views: emit updated preferences
    Views->>Views: re-render timestamps using Date.format(dateFormat, timeFormat)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Poem

🐰
I nibble times and dates apart,
Four tidy prefs, a brand new art,
Dropdowns hum, adapters sing,
Timestamps hop with clearer spring!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main changes: splitting datetime format into separate date and time settings, and into overview and note-view settings.
Linked Issues check ✅ Passed All coding objectives from #842 and #930 are met: date/time formats are separated into distinct settings, applied globally across the app (overview and note-view), and the ability to hide dates in overview is provided via independent format selection.
Out of Scope Changes check ✅ Passed All changes align with the linked issues: preference refactoring, UI updates for date/time format selection, adapter updates to pass format preferences, and string resource updates are directly required to implement the feature.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/842

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
app/src/main/java/com/philkes/notallyx/presentation/activity/main/fragment/settings/SettingsFragment.kt (1)

633-651: Consider using destructured values instead of re-reading preferences.

The observer merges three LiveData sources but only uses the first destructured value (time). The date/time formats are then re-read from model.preferences instead of using the values from the merge. While functionally correct, this pattern is inconsistent—either use the merged values or simplify the observer to only observe lastExecutionPreference.

♻️ Option 1: Use destructured values
         lastExecutionPreference
             .merge(model.preferences.dateFormatOverview, model.preferences.timeFormatOverview)
-            .observe(viewLifecycleOwner) { (time, _, _) ->
+            .observe(viewLifecycleOwner) { (time, dateFormat, timeFormat) ->
                 binding.PeriodicBackupLastExecution.apply {
                     if (time != -1L) {
                         isVisible = true
                         text =
                             Date(time)
                                 .format(
-                                    model.preferences.dateFormatOverview.value,
-                                    model.preferences.timeFormatOverview.value,
+                                    dateFormat,
+                                    timeFormat,
                                     ensureFullFormat = true,
                                 )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/philkes/notallyx/presentation/activity/main/fragment/settings/SettingsFragment.kt`
around lines 633 - 651, The observer on lastExecutionPreference.merge(...)
currently destructures only the first value (time) and then re-reads
model.preferences.dateFormatOverview/value and timeFormatOverview/value; change
the lambda to destructure all three values (e.g., (time, dateFormatOverview,
timeFormatOverview)) and use those destructured values when formatting the Date
inside binding.PeriodicBackupLastExecution so you don't re-read
model.preferences; update the observer in SettingsFragment.kt where
lastExecutionPreference.merge(...) is observed to use the extracted date/time
format values.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@app/src/main/java/com/philkes/notallyx/presentation/activity/note/reminders/RemindersActivity.kt`:
- Around line 470-471: The delete dialog currently forces a hardcoded full
format via reminder.dateTime.format(ensureFullFormat = true), causing a mismatch
with how reminders are rendered elsewhere (e.g. ReminderVH); change the dialog
to use the same user-configured note-view formatting as ReminderVH by removing
the forced ensureFullFormat flag and delegating to the shared/standard date-time
formatter used by ReminderVH (or call the same format invocation that ReminderVH
uses) so the dialog shows the reminder timestamp in the user’s configured
note-view format.

In
`@app/src/main/java/com/philkes/notallyx/presentation/viewmodel/preference/Preference.kt`:
- Around line 366-396: The file-level SimpleDateFormat instances
(ISO_DATE_FORMAT, MM_DD_YY_FORMAT, DD_MM_YY_FORMAT, DD_MM_YY_FORMAT_GER,
TWENTY_FOUR_H_FORMAT, AM_PM_FORMAT) are not thread-safe and are used by the
DateFormat and TimeFormat enum format lambdas (and by the Date.format()
extension in UiExtensions.kt), so replace them with thread-safe usage: either
instantiate a new SimpleDateFormat inside each lambda/format call (create new
instances in the DateFormat and TimeFormat enum constructors or inside their
format lambdas) or, if targeting API 24+, switch to
java.time.format.DateTimeFormatter and java.time classes for immutable,
thread-safe formatting; update DateFormat.getText and any uses in Date.format()
to call the new per-call/thread-safe formatter APIs (reference DateFormat,
TimeFormat, ISO_DATE_FORMAT, MM_DD_YY_FORMAT, DD_MM_YY_FORMAT,
DD_MM_YY_FORMAT_GER, TWENTY_FOUR_H_FORMAT, AM_PM_FORMAT and the Date.format()
extension).

---

Nitpick comments:
In
`@app/src/main/java/com/philkes/notallyx/presentation/activity/main/fragment/settings/SettingsFragment.kt`:
- Around line 633-651: The observer on lastExecutionPreference.merge(...)
currently destructures only the first value (time) and then re-reads
model.preferences.dateFormatOverview/value and timeFormatOverview/value; change
the lambda to destructure all three values (e.g., (time, dateFormatOverview,
timeFormatOverview)) and use those destructured values when formatting the Date
inside binding.PeriodicBackupLastExecution so you don't re-read
model.preferences; update the observer in SettingsFragment.kt where
lastExecutionPreference.merge(...) is observed to use the extracted date/time
format values.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: aa2d7f10-b04e-417c-a55c-8175391bcd1e

📥 Commits

Reviewing files that changed from the base of the PR and between e4195ff and 3a73953.

⛔ Files ignored due to path filters (1)
  • app/translations.xlsx is excluded by !**/*.xlsx
📒 Files selected for processing (29)
  • TRANSLATIONS.md
  • app/src/main/java/com/philkes/notallyx/presentation/UiExtensions.kt
  • app/src/main/java/com/philkes/notallyx/presentation/activity/main/fragment/NotallyFragment.kt
  • app/src/main/java/com/philkes/notallyx/presentation/activity/main/fragment/settings/PreferenceBindingExtensions.kt
  • app/src/main/java/com/philkes/notallyx/presentation/activity/main/fragment/settings/SettingsFragment.kt
  • app/src/main/java/com/philkes/notallyx/presentation/activity/note/EditActivity.kt
  • app/src/main/java/com/philkes/notallyx/presentation/activity/note/PickNoteActivity.kt
  • app/src/main/java/com/philkes/notallyx/presentation/activity/note/reminders/RemindersActivity.kt
  • app/src/main/java/com/philkes/notallyx/presentation/view/main/BaseNoteAdapter.kt
  • app/src/main/java/com/philkes/notallyx/presentation/view/main/BaseNoteVH.kt
  • app/src/main/java/com/philkes/notallyx/presentation/view/main/reminder/ReminderAdapter.kt
  • app/src/main/java/com/philkes/notallyx/presentation/view/main/reminder/ReminderVH.kt
  • app/src/main/java/com/philkes/notallyx/presentation/viewmodel/preference/NotallyXPreferences.kt
  • app/src/main/java/com/philkes/notallyx/presentation/viewmodel/preference/Preference.kt
  • app/src/main/res/layout/dialog_datetime_format.xml
  • app/src/main/res/layout/fragment_settings.xml
  • app/src/main/res/values-cs/strings.xml
  • app/src/main/res/values-de/strings.xml
  • app/src/main/res/values-es/strings.xml
  • app/src/main/res/values-fr/strings.xml
  • app/src/main/res/values-it/strings.xml
  • app/src/main/res/values-pl/strings.xml
  • app/src/main/res/values-pt-rBR/strings.xml
  • app/src/main/res/values-ro/strings.xml
  • app/src/main/res/values-ru/strings.xml
  • app/src/main/res/values-uk/strings.xml
  • app/src/main/res/values-zh-rCN/strings.xml
  • app/src/main/res/values-zh-rTW/strings.xml
  • app/src/main/res/values/strings.xml
💤 Files with no reviewable changes (12)
  • app/src/main/res/values-fr/strings.xml
  • app/src/main/res/values-es/strings.xml
  • app/src/main/res/values-it/strings.xml
  • app/src/main/res/values-ro/strings.xml
  • app/src/main/res/values-uk/strings.xml
  • app/src/main/res/values-zh-rCN/strings.xml
  • app/src/main/res/values-cs/strings.xml
  • app/src/main/res/values-de/strings.xml
  • app/src/main/res/values-zh-rTW/strings.xml
  • app/src/main/res/values-ru/strings.xml
  • app/src/main/res/values-pt-rBR/strings.xml
  • app/src/main/res/values-pl/strings.xml

Comment on lines +470 to +471
.setMessage(
"${reminder.dateTime.format()}\n${reminder.repetition?.toText(this) ?: getString(R.string.reminder_no_repetition)}"
"${reminder.dateTime.format(ensureFullFormat = true)}\n${reminder.repetition?.toText(this) ?: getString(R.string.reminder_no_repetition)}"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Date.format(...) definition(s) =="
rg -n -C4 --type=kt '\bfun\s+Date\.format\s*\(' app/src/main/java

echo
echo "== Reminder timestamp call sites =="
rg -n -C2 --type=kt 'dateTime\.format\(' \
  app/src/main/java/com/philkes/notallyx/presentation/activity/note/reminders/RemindersActivity.kt \
  app/src/main/java/com/philkes/notallyx/presentation/view/main/reminder/ReminderVH.kt

Repository: Crustack/NotallyX

Length of output: 141


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Finding Date.format(...) definition(s) =="
find app/src/main/java -name "*.kt" -exec rg -l "fun.*Date\.format" {} \;
echo
rg -n -C4 "fun.*Date\.format" app/src/main/java

echo
echo "== Reminder timestamp call sites in RemindersActivity.kt =="
rg -n -C2 "dateTime\.format" app/src/main/java/com/philkes/notallyx/presentation/activity/note/reminders/RemindersActivity.kt

echo
echo "== Reminder timestamp call sites in ReminderVH.kt =="
rg -n -C2 "dateTime\.format" app/src/main/java/com/philkes/notallyx/presentation/view/main/reminder/ReminderVH.kt

Repository: Crustack/NotallyX

Length of output: 1816


Align the delete dialog with the configured note-view formats.

The delete confirmation dialog uses format(ensureFullFormat = true), which applies hardcoded defaults (DateFormat.DD_MM_YY_GER and TimeFormat.TWENTY_FOUR_H). Meanwhile, ReminderVH renders the same reminder timestamp with the user's configured note-view preferences. This creates a UX inconsistency where the same reminder appears in different formats across your app.

💡 Proposed change
-                "${reminder.dateTime.format(ensureFullFormat = true)}\n${reminder.repetition?.toText(this) ?: getString(R.string.reminder_no_repetition)}"
+                "${reminder.dateTime.format(
+                    preferences.dateFormatNoteView.value,
+                    preferences.timeFormatNoteView.value,
+                    ensureFullFormat = true,
+                )}\n${reminder.repetition?.toText(this) ?: getString(R.string.reminder_no_repetition)}"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.setMessage(
"${reminder.dateTime.format()}\n${reminder.repetition?.toText(this) ?: getString(R.string.reminder_no_repetition)}"
"${reminder.dateTime.format(ensureFullFormat = true)}\n${reminder.repetition?.toText(this) ?: getString(R.string.reminder_no_repetition)}"
.setMessage(
"${reminder.dateTime.format(
preferences.dateFormatNoteView.value,
preferences.timeFormatNoteView.value,
ensureFullFormat = true,
)}\n${reminder.repetition?.toText(this) ?: getString(R.string.reminder_no_repetition)}"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/philkes/notallyx/presentation/activity/note/reminders/RemindersActivity.kt`
around lines 470 - 471, The delete dialog currently forces a hardcoded full
format via reminder.dateTime.format(ensureFullFormat = true), causing a mismatch
with how reminders are rendered elsewhere (e.g. ReminderVH); change the dialog
to use the same user-configured note-view formatting as ReminderVH by removing
the forced ensureFullFormat flag and delegating to the shared/standard date-time
formatter used by ReminderVH (or call the same format invocation that ReminderVH
uses) so the dialog shows the reminder timestamp in the user’s configured
note-view format.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
app/src/main/java/com/philkes/notallyx/presentation/viewmodel/preference/Preference.kt (1)

366-394: Limit formatter helper visibility to avoid API surface creep.

ThreadLocalDateFormat and ThreadLocalDateInstance appear internal to this file; making them private prevents accidental external coupling.

Proposed diff
-class ThreadLocalDateFormat(private val format: String, private val locale: Locale) {
+private class ThreadLocalDateFormat(private val format: String, private val locale: Locale) {
@@
-class ThreadLocalDateInstance(private val style: Int) {
+private class ThreadLocalDateInstance(private val style: Int) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/philkes/notallyx/presentation/viewmodel/preference/Preference.kt`
around lines 366 - 394, The two helper classes ThreadLocalDateFormat and
ThreadLocalDateInstance are package-visible but only used internally here;
change their declarations to private (make the classes private) so they are not
exposed from this file, e.g., update the class headers for ThreadLocalDateFormat
and ThreadLocalDateInstance to be private to limit the API surface and prevent
external coupling while keeping their constructors and methods as-is.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@app/src/main/java/com/philkes/notallyx/presentation/viewmodel/preference/Preference.kt`:
- Around line 412-417: Replace the fixed millisecond subtraction in the enum
getText(context: Context): String implementations (the branches that handle NONE
vs "yesterday") with day-based arithmetic: create a small helper (e.g.,
getYesterdayCalendar() or getYesterdayDate()) that uses Calendar.getInstance(),
calls add(Calendar.DAY_OF_YEAR, -1) and returns the Date/Calendar/Instant
needed, and call that helper from both enum getText implementations instead of
Date(System.currentTimeMillis() - 86400000); ensure the helper is reused by the
other enum branch referenced in the review so DST transitions produce correct
"yesterday" values.

---

Nitpick comments:
In
`@app/src/main/java/com/philkes/notallyx/presentation/viewmodel/preference/Preference.kt`:
- Around line 366-394: The two helper classes ThreadLocalDateFormat and
ThreadLocalDateInstance are package-visible but only used internally here;
change their declarations to private (make the classes private) so they are not
exposed from this file, e.g., update the class headers for ThreadLocalDateFormat
and ThreadLocalDateInstance to be private to limit the API surface and prevent
external coupling while keeping their constructors and methods as-is.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 86c74e9d-fdf5-4260-a4b1-a97dc373036e

📥 Commits

Reviewing files that changed from the base of the PR and between 3a73953 and 0d30578.

📒 Files selected for processing (3)
  • .github/workflows/update-translation-coverage.yaml
  • app/src/main/java/com/philkes/notallyx/presentation/activity/note/reminders/RemindersActivity.kt
  • app/src/main/java/com/philkes/notallyx/presentation/viewmodel/preference/Preference.kt
✅ Files skipped from review due to trivial changes (1)
  • .github/workflows/update-translation-coverage.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/src/main/java/com/philkes/notallyx/presentation/activity/note/reminders/RemindersActivity.kt

@Crustack Crustack merged commit 5365b07 into main Apr 3, 2026
1 check was pending
@Crustack Crustack deleted the feat/842 branch April 3, 2026 15:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Hide Dates in Overview Separate date and time formats and apply globally

1 participant