Fix notifications and loading state #28
Labels
No labels
Compat/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
gtfs.zone/coloring-book#28
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
The current setup has two overlapping feedback systems (
NotificationSystemandLoadingStateManager) both firing during feed load, producing duplicate messages and visual inconsistency. The notification system also uses emojis and hardcoded light-mode CSS classes that break in dark themes. The plan: enforce a clean ownership split —NotificationSystemhandles transient bottom-left toasts exclusively (DaisyUI-styled, no emojis),LoadingStateManageris trimmed to a lean progress-only indicator for feed loads, and a later phase moves ZIP/CSV parsing to a Web Worker so large feeds don't freeze the UI. This branch should be rebased on top of42-show-map-and-feed-infobefore starting, since #42 removesmapController.showLoading()calls fromui.tsthat this work also touches.Relevant Context
Files:
src/modules/notification-system.ts—NotificationSystemclass; hardcoded light-mode colors (bg-red-50etc.), emoji icons, container positionedfixed top-4 right-4src/modules/loading-state-manager.ts—LoadingStateManager; has progress tracking (startLoading,updateProgress,finishLoading) plus abusedshowError/Warning/Successmethods that repurpose the banner for result messagessrc/modules/gtfs-parser.ts:530–681—parseFile()drivesloadingStateManagerprogress (10%→100%) and callsloadingStateManager.showSuccess/showErroron completion; also callsloadingStateManager.showWarningfor unknown filessrc/modules/ui.ts:223–407—loadGTFSFile()andloadGTFSFromURL()each callnotifications.showLoading()at the start, thennotifications.showSuccess/showError()at the end — duplicating what gtfs-parser already does via the loading managersrc/index.ts— constructs all modules; callsnotifications.initialize()to attach the container to the DOMArchitectural invariant:
loadingStateManageris used exclusively bygtfs-parser.tsfor feed load progress. No other module calls it. This means we can safely narrow its scope and rename it.#42 compatibility: Branch
42-show-map-and-feed-inforemovesmapController.showLoading(),hideMapOverlay(), and export button enable/disable fromui.ts. It also makes the file list always show all sections. No direct conflict with notification changes, but the map overlay is confirmed gone — don't rely on it in the new design.Phase 1 — Notification System Visual Cleanup
Remove emojis, fix dark-mode styling, move container to bottom-left. No behavior changes.
colorMapclasses (bg-red-50 border-red-200 text-red-800etc.) with DaisyUI alert semantic classes (alert alert-error,alert alert-warning,alert alert-success,alert alert-info) inNotificationSystem.renderNotification()iconMapwith emoji characters; replace with short text type labels or DaisyUI SVG alert icons<span class="loading loading-spinner">DaisyUI spinner is sufficientfixed top-4 right-4tofixed bottom-4 left-4z-50is fine;42-show-map-and-feed-infohas map controls atz-40.alert) to avoid layout fighting DaisyUI's own flex styles; addrole="alert"to match docsshowLoadinga 30s fallback auto-hide so nothing can get permanently stuckCommits:
fix(notifications): use DaisyUI semantic colors, remove emojis, move to bottom-leftfix(notifications): use DaisyUI alert structure with SVG icons, always expirefix: use cleaner bg color— removed per-typealert-*variant classes; plainalertwith DaisyUI default styling reads much better in practiceGotcha: DaisyUI v5 alert classes use
alert alert-error(two classes). Confirmed v5.5.14 installed, consistent with existing usage throughout the codebase.Slide animation direction is
translateX(-100%)(slide left) to match the bottom-left position.Phase 2 — Clean Split: Progress Bar vs. Notification Toasts
Enforce non-overlapping ownership.
LoadingStateManager= progress only. All result messages go throughNotificationSystem.showError(),showWarning(),showSuccess(), andforceHideLoading()fromLoadingStateManagergtfs-parser.tsparseFile(): removeloadingStateManager.showSuccess()call (~line 665) andloadingStateManager.showError()call (~line 676) — let callers handle result messagesgtfs-parser.tsparseFile(): removeloadingStateManager.showWarning()for unknown files (~line 646); instead addunknownFilesto the return type and return it soui.tscan show a warning toastui.tsloadGTFSFile(): remove thenotifications.showLoading()toast (~line 232) — the top progress banner is the sole loading indicator; keep theshowSuccess/showErrorcalls at the endui.tsloadGTFSFromURL()(~line 339)ui.ts, afterparseFile()resolves, check the returnedunknownFilesand callnotifications.showWarning()if non-emptyui.ts(~line 246) — the progress bar status text handles this contextuallyLoadingStateManager→FeedProgressIndicator(class, file, export, all imports) to reflect its narrowed purposegrep -r "loadingStateManager"to catch all remaining call sitesCommit:
refactor(loading): clean split between progress indicator and notification toastsDiscoveries:
database-fallback-manager.tsalso calledloadingStateManager.showSuccess/showErrorfor the DB reset flow — not mentioned in the plan. Fixed by importingnotificationsthere and routing those two calls through it.loading-state-manager.tswas kept as a re-export shim so the rename is non-breaking at the module level.parseFromURLwas also updated to return{ unknownFiles }so the URL load path inui.tscan show the same warning toast.Phase 3 — Manual Testing Checkpoint
No code changes. Verify before continuing:
Phase 4 — Web Worker for Feed Parsing
Move ZIP extraction and CSV parsing off the main thread so large feeds don't freeze the UI.
src/workers/gtfs-parser.worker.ts; Vite handles worker bundling vianew Worker(new URL('../workers/gtfs-parser.worker.ts', import.meta.url), { type: 'module' }){ type: 'parse', buffer: ArrayBuffer }{ type: 'progress', progress: number, status: string }|{ type: 'done', data: WorkerParsedResult }|{ type: 'error', message: string }JSZip.loadAsync(),Papa.parse(), type coercion (processParsedData); emitprogressmessages at the same percentage points whereupdateProgress()was calledWorkerParsedResultas the structured data for each file (table name → rows array + raw CSV blob), matching whatparseFile()currently assembles intothis.gtfsDataGTFSParser.parseFile(): convertFile | BlobtoArrayBufferviafile.arrayBuffer(), transfer to worker withworker.postMessage(buffer, [buffer])(zero-copy transfer), awaitdoneorerrorprogressmessage: callfeedProgressIndicator.updateProgress()done: main thread callssetupVirtual()for each table andgtfsDatabase.saveTableBlob()— these must stay on main threaderror: throw so the existing error path inui.tscatches it and shows the error toastCommit:
feat(parser): move ZIP/CSV parsing to Web WorkerDiscoveries: The worker imports
gtfs-file-registry.tsdirectly (pure Zod-based module, no DOM) forALL_GTFS_FILES,isSupportedFile, andmakeHeaderOnlyCSV.GTFSDatabaseRecordis defined locally in the worker as a plain type alias to avoid importing the idb-dependentgtfs-database.ts. Worker is spawned fresh per parse call and terminated afterdone/error.Phase 5 — Manual Testing Checkpoint
Original Issue
Lets make a niiice robust global loading and notification state thingy. Lets make it not cover up all the controls when we get a notification 😆
Maybe do a little research into the best editor notifications... Maybe powerline haha
Lets take the opportunity to move towards using service workers, maybe