Skip to content

Fix icon rendering, DB reload processing, and planner bugs#23

Open
geokoko wants to merge 25 commits intomasterfrom
fix/icons-planner-reload-bugs
Open

Fix icon rendering, DB reload processing, and planner bugs#23
geokoko wants to merge 25 commits intomasterfrom
fix/icons-planner-reload-bugs

Conversation

@geokoko
Copy link
Copy Markdown
Owner

@geokoko geokoko commented Mar 17, 2026

Summary

  • Icon rendering: Use setGraphic() with Noto Emoji font labels for all icon/emoji characters across all panels, fixing rendering failures on systems without per-glyph font fallback (e.g. Kubuntu 24.04)
  • DB reload post-processing: Re-run markDelayedTasks and processAllDelayedGoals after a Google Drive DB download so overdue state is correct without requiring an app restart
  • Postponed recurring tasks: Exclude POSTPONED status from findActiveRecurring() so postponed courses stop showing as missed
  • Re-plan dropdown: Add Task.appliesToDate() for date-aware recurring task filtering, and fix ComboBox cell factory to use null instead of empty strings (eliminates phantom empty boxes)
  • Drive sync hardening: Atomic file replacement (same-filesystem temp file), post-download CHECKPOINT SYNC, explicit H2 SHUTDOWN on exit to prevent data loss
  • Three-option exit dialog: Push to Drive and Exit, Save Locally and Exit, Exit without Saving — Drive is never silently overwritten (shutdownSaveEnabled defaults to false)
  • Local save button: Explicit Save Locally in Profile panel for on-demand disk flush
  • Single-instance enforcement: File lock prevents duplicate app windows and concurrent H2 access
  • GNOME desktop integration: Correct StartupWMClass to match JavaFX actual WM_CLASS, preventing separate dock icon
  • GNOME dialog sizing: Force explicit dimensions on dialogs/stages that GNOME Mutter sizes too small
  • Planner goal query fix: Remove auto-carry-forward clause that caused re-planning one goal to pull ALL delayed goals, and caused achieved delayed goals to vanish from the completed section
  • Null-safety fixes: Guards for search filters, reminder toString, date picker edge cases
  • UI polish: Button icon overlap fixes, empty combo-box dropdown cleanup, re-plan filtering improvements

Pre-Landing Review

Pre-Landing Review: 2 issues — 2 auto-fixed (H2 SHUTDOWN always runs on exit, debug diagnostics removed)

Test plan

  • All 8 tests pass
  • Verify icon rendering on Kubuntu 24.04 (not planned)
  • Verify postponed recurring tasks no longer appear under Missed recurring tasks
  • Verify re-plan dropdown filtering and no empty boxes
  • Download DB from Drive and confirm panels refresh with correct delayed/overdue state -> partially works, DB CAN be fetched and data can be loaded properly, but the frontend button "Download From Drive" must be pressed twice for the new data to show up in frontend (which is not the expected behavior)
  • Manual testing: exit dialog options, single-instance lock, GNOME dock grouping, dialog sizing, goal re-plan, achieved goals display

Copilot AI review requested due to automatic review settings March 17, 2026 01:15
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Updates StudySync’s JavaFX UI and Drive reload behavior to improve cross-platform icon rendering and fix planner/recurring-task edge cases, especially on systems without reliable per-glyph font fallback.

Changes:

  • Standardize icon rendering by moving emoji/symbol glyphs into setGraphic() using Noto Emoji labels across multiple panels and badges.
  • After Google Drive DB download/reload, re-run delayed-task and delayed-goal processing so overdue state updates immediately.
  • Adjust recurring-task logic: exclude POSTPONED from “active recurring,” and add Task.appliesToDate() for date-aware filtering in the re-plan dropdown; fix ComboBox cell factory to clear text with null.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/main/java/com/studysync/presentation/ui/components/TaskStyleUtils.java Adds iconLabel() helper and updates badge rendering to use setGraphic() with Noto Emoji.
src/main/java/com/studysync/presentation/ui/components/TaskManagementPanel.java Switches status/error icon rendering to setGraphic() for better emoji reliability.
src/main/java/com/studysync/presentation/ui/components/StudyPlannerPanel.java Updates many UI glyphs to graphics, fixes ComboBox cell clearing, tweaks session handling and error display.
src/main/java/com/studysync/presentation/ui/components/ProfileViewPanel.java Converts several Drive/profile UI icons to graphics; adjusts Drive status messaging.
src/main/java/com/studysync/presentation/ui/components/CalendarViewPanel.java Moves header/tab/button glyphs to graphics and applies emoji font for small glyph labels.
src/main/java/com/studysync/presentation/ui/StudySyncUI.java Re-runs delayed task/goal startup processing after DB reload from Drive and improves reload overlay rendering.
src/main/java/com/studysync/integration/drive/GoogleDriveSettingsLoader.java Ensures default paths resolve to absolute paths for deterministic Drive IO.
src/main/java/com/studysync/integration/drive/GoogleDriveService.java Makes Drive upload safer by aborting on failed H2 checkpoint; conditionally skips shutdown upload if checkpoint fails.
src/main/java/com/studysync/integration/drive/GoogleDriveGateway.java Adds diagnostic logging (file size/mtime) before uploading DB to Drive.
src/main/java/com/studysync/domain/service/StudyService.java Filters delayed goals eligible for replanning using Task.appliesToDate(today) for recurring tasks.
src/main/java/com/studysync/domain/entity/Task.java Adds appliesToDate() and updates findActiveRecurring() to exclude POSTPONED tasks.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@geokoko
Copy link
Copy Markdown
Owner Author

geokoko commented Mar 20, 2026

Downloaded up-to-date DB from Drive on Ubuntu 24.04 LTS. Calendar Panel does not refresh to the latest version.

geokoko and others added 20 commits March 25, 2026 06:26
Abort upload when CHECKPOINT SYNC fails instead of uploading stale data,
resolve Drive settings path to absolute to prevent CWD-dependent mismatch,
fix double startSession() call that desynchronised in-memory/DB state,
and add exception handling around session save in the UI.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…pport

JavaFX CSS font-family does not perform per-glyph fallback like browsers,
so emoji/symbol characters fail to render on systems missing the right
font (e.g. Kubuntu 24.04). Fix by separating icon glyphs into dedicated
Label nodes using setGraphic() with the bundled Noto Emoji font, keeping
regular text in the default system font.

Adds TaskStyleUtils.iconLabel() helper and updates all panels:
StudyPlannerPanel, CalendarViewPanel, ProfileViewPanel,
TaskManagementPanel, and the reload overlay in StudySyncUI.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
After downloading a new database from Google Drive, the reload listener
only reset caches and refreshed panels but did not re-run the startup
processing steps (markDelayedTasks, processAllDelayedGoals). This meant
overdue tasks were not marked DELAYED and delayed goals were not
processed until the next app restart.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tasks with POSTPONED status were still returned by findActiveRecurring(),
causing them to appear as missed in the study planner even though the
user intentionally paused them.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add Task.appliesToDate() to check if a recurring task is scheduled on
  a given date based on its recurrence pattern and anchor
- Filter re-plan dropdown to hide recurring-task goals when the task
  already applies today (it will naturally re-occur)
- Fix ComboBox cell factory to use setText(null)/setGraphic(null) for
  empty items instead of empty strings, preventing phantom empty boxes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract duplicate ComboBox cell factory into shared Callback variable
- Cache dateNavLabel icon as instance field to avoid re-creating on
  every updateDisplay() call
- Narrow catch(Exception) in appliesToDate() to specific exception types
  and add warning log for invalid recurring patterns

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace surrogate-pair emoji (U+1F512, U+1F510) and extended arrows
(U+2B06, U+2B07) on Drive sync buttons with basic Unicode symbols
(arrows, cross mark) that Noto Emoji reliably renders. Also limit
re-plan ComboBox visible row count to item count to prevent phantom
empty row in dropdown.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of date-checking recurring patterns, simply exclude any delayed
goal whose parent task already appears in today's tasks section. This
covers both recurring and non-recurring tasks — if the task is visible
today, its goals are already accessible directly and don't need
re-planning.

Removes the now-unused Task.appliesToDate() method.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…abel

- Move the warning symbol out of the Drive status text string and into
  setGraphic() so it renders via Noto Emoji like all other icons
- Replace stacking error labels in the end-session dialog with a single
  reusable label that updates its text on repeated failures

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace all remaining inline emoji and surrogate pair characters with
setGraphic(iconLabel(...)) using basic Unicode symbols rendered via
Noto Emoji font. Covers ProjectManagementPanel, ReflectionDiaryPanel,
and the last surrogate pair in StudyPlannerPanel.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…picker

- TaskService.matchesCategory(): NPE when task.getCategory() is null
- TaskService.searchTasksAdvanced(): same null category issue
- ProjectService.searchProjects(): same pattern
- TaskReminder.toString(): NPE when computeReminderDate() returns null
- ReflectionDiaryPanel.onDateChanged(): NPE if datePicker value is null
- StudySyncUI: close icon InputStream via try-with-resources

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Root cause: CSS `.button { -fx-content-display: center; }` forced all
button graphics to render centered, overlapping with the button text.
Changed to `left` so icons render beside text. Also converted planner
prev/next nav buttons from fontEmoji-on-text to setGraphic pattern, and
used inline style for the CalendarView "Next" button (CSS overrides
setContentDisplay).

For re-plan dropdown: added CSS rule to collapse empty combo-box-popup
list cells (zero height + transparent) so phantom rows are invisible.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the two-option exit dialog with three choices:
- "Push to Drive & Exit" — checkpoint + upload + exit
- "Save Locally & Exit" — checkpoint + exit (no upload)
- "Exit without Saving" — exit immediately, no DB flush

Default shutdownSaveEnabled to false so Drive is never silently
overwritten by @PreDestroy. Add saveLocally() method and a
"Save Locally" button in the Profile panel for explicit disk flush.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Acquire an exclusive file lock on ~/.local/share/studysync/.studysync.lock
at startup. If another StudySync process holds the lock, print a message
to stderr and exit immediately — preventing duplicate windows and DB
corruption from concurrent H2 access.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Set -Dglass.appClassName=StudySync in the launcher script so JavaFX
reports "StudySync" as the X11 WM_CLASS. Update StartupWMClass in
the .desktop entry to match. This prevents GNOME from showing the
app as a separate dock icon instead of grouping it with its launcher.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Set StartupWMClass to the actual WM_CLASS that JavaFX reports:
"com.studysync.application.StudySyncJavaFXApp" (verified via xprop).
The previous glass.appClassName approach didn't override JavaFX's
default. Remove the unused JVM flag from the launcher.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
GNOME's Mutter ignores JavaFX DialogPane pref/min size hints, causing
sub-windows to open at their minimum content size. Fix by explicitly
setting width/height on the dialog window via onShown handler, and
setting explicit dimensions on the Profile stage. KDE is unaffected.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Review fixes:
- Always SHUTDOWN H2 engine on exit regardless of save choice,
  preventing DB corruption from racy JVM shutdown hooks. The
  "Exit without Saving" option now only skips the Drive upload,
  not the disk flush.
- Remove skipShutdownCheckpoint flag (unnecessary with the above).
- Remove logDbSnapshot diagnostic method and its call sites — was
  debug-only code left in production.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove the auto-carry-forward clause from findByTaskIdForDate and
findUnlinkedForDate. Delayed goals now only appear if explicitly
re-planned (replanned_for_date = today) or originally scheduled
(date = today).

The old clause caused two bugs:
1. Re-planning one goal pulled ALL delayed goals for that task
2. Achieved delayed goals vanished (achieved=TRUE excluded by clause)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@geokoko geokoko force-pushed the fix/icons-planner-reload-bugs branch from 8b5ee17 to 22a1e07 Compare March 25, 2026 04:46
geokoko and others added 3 commits March 26, 2026 03:17
…ving

Goals are never deleted from the database. Overdue goals (14+ days) are
now marked as FAILED instead of being physically removed, preserving
them for historical logging. User-initiated "delete" also soft-deletes
by setting the failed flag.

Each task card in Task Management now has a "Goal History" toggle that
shows all goals ever linked to that task — achieved, active, delayed,
and failed — with summary statistics.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Codex review flagged that soft-deleting an already-achieved goal left
both achieved=true and failed=true, causing it to still count as a
completion in ProfileViewPanel, hasAchievedGoalForTask(), and
findAchievedTaskDatePairs(). Fix: reset achieved=false when marking
failed, and add failed=FALSE filters to all achievement-based queries.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…em vanish

Goals re-planned to a specific date disappeared from all views once that
date passed, because queries only match on date or replanned_for_date
equal to the display date. Now processAllDelayedGoals() marks these
goals as failed immediately when the replan date passes, so they appear
in goal history with proper failed status.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
geokoko and others added 2 commits March 27, 2026 03:10
…iled

- Calendar delete is now permanent (hard delete from DB), not soft-delete
- Added "Mark as Failed" button on calendar for explicit soft-deletion
- Calendar shows all goals for their planned date including failed ones,
  with distinct red styling and status indicator for failed goals
- Added findAllByDate/findAllByDateIncludingDelayed queries that include
  failed goals, used exclusively by calendar view
- Split deleteStudyGoal (hard delete) from markGoalAsFailed (soft-delete)
- Failed and delayed goals count against the profile goal completion rate
- Fixes all Codex-identified blind spots: unlinked failed goals are now
  visible on the calendar for the day they were originally planned

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
feat: goal history per task + soft-delete goals
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.

3 participants