Added Dynamic Themes depending on collision status and time.#130
Conversation
|
Skipping CodeAnt AI review — this PR is a back-merge between long-lived branches ( If you want to analyze this anyway (e.g. you resolved conflicts with new logic), comment |
📝 WalkthroughWalkthroughAdds an automatic, condition-driven dynamic background system with six animated themes, lazy loading, reduced-motion and tab-visibility handling, layout integration, and translucent UI surfaces. ChangesDynamic background system
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant MainLayout
participant DynamicBackground
participant useBackgroundTheme
participant backgroundEngine
participant ThemeComponent
MainLayout->>DynamicBackground: render background layer
DynamicBackground->>useBackgroundTheme: read theme and animation state
useBackgroundTheme->>backgroundEngine: evaluate weather, collision, and daylight conditions
backgroundEngine-->>useBackgroundTheme: return prioritized theme
DynamicBackground->>ThemeComponent: lazy-load selected component
ThemeComponent-->>MainLayout: render animated background
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
| const currentTheme = useMemo( | ||
| () => resolveAutoTheme(weatherQuery.data, collisionsQuery.data), | ||
| [weatherQuery.data, collisionsQuery.data] | ||
| ); |
There was a problem hiding this comment.
isDaytime() is read inside this memo, but time is not a dependency. If API responses remain structurally unchanged when the app crosses 06:00 or 18:00, the memo keeps the previous theme until some query data actually changes.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src/hooks/useBackgroundTheme.ts
Line: 29-32
Comment:
**Day/Night Theme Stays Stale**
`isDaytime()` is read inside this memo, but time is not a dependency. If API responses remain structurally unchanged when the app crosses 06:00 or 18:00, the memo keeps the previous theme until some query data actually changes.
How can I resolve this? If you propose a fix, please make it concise.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| export function isDaytime(): boolean { | ||
| const hour = new Date().getUTCHours(); | ||
| return hour >= 6 && hour < 18; | ||
| } |
There was a problem hiding this comment.
UTC Drives Local Daylight Theme
The fixed UTC window makes day and night incorrect for users outside UTC. For example, a user in Tokyo receives the day theme from 15:00 until 03:00 local time instead of during local daylight hours.
| export function isDaytime(): boolean { | |
| const hour = new Date().getUTCHours(); | |
| return hour >= 6 && hour < 18; | |
| } | |
| export function isDaytime(): boolean { | |
| const hour = new Date().getHours(); | |
| return hour >= 6 && hour < 18; | |
| } |
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src/utils/backgroundEngine.ts
Line: 85-88
Comment:
**UTC Drives Local Daylight Theme**
The fixed UTC window makes day and night incorrect for users outside UTC. For example, a user in Tokyo receives the day theme from 15:00 until 03:00 local time instead of during local daylight hours.
```suggestion
export function isDaytime(): boolean {
const hour = new Date().getHours();
return hour >= 6 && hour < 18;
}
```
How can I resolve this? If you propose a fix, please make it concise.| const currentTheme = useMemo( | ||
| () => resolveAutoTheme(weatherQuery.data, collisionsQuery.data), | ||
| [weatherQuery.data, collisionsQuery.data] | ||
| ); |
There was a problem hiding this comment.
Manual Override Cannot Be Applied
currentTheme is always derived from live conditions, and this hook exposes no override value or setter. As a result, the manual theme selection described for the top bar cannot take precedence over automatic selection or persist across renders.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src/hooks/useBackgroundTheme.ts
Line: 29-32
Comment:
**Manual Override Cannot Be Applied**
`currentTheme` is always derived from live conditions, and this hook exposes no override value or setter. As a result, the manual theme selection described for the top bar cannot take precedence over automatic selection or persist across renders.
How can I resolve this? If you propose a fix, please make it concise.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| export function useBackgroundTheme() { | ||
| const prefersReducedMotion = useReducedMotion(); | ||
| const weatherQuery = useWeatherStatus(); | ||
| const collisionsQuery = useCollisions({ size: 50 }); |
There was a problem hiding this comment.
This fetch examines only the first 50 unfiltered collisions, while the server orders them by numeric risk score and the theme checks categorical risk and status. If a CRITICAL or pending HIGH collision falls outside that page, the dashboard shows a non-alert theme even though a qualifying conjunction exists.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src/hooks/useBackgroundTheme.ts
Line: 27
Comment:
**Collision Alert Uses One Page**
This fetch examines only the first 50 unfiltered collisions, while the server orders them by numeric risk score and the theme checks categorical risk and status. If a `CRITICAL` or pending `HIGH` collision falls outside that page, the dashboard shows a non-alert theme even though a qualifying conjunction exists.
How can I resolve this? If you propose a fix, please make it concise.| @keyframes meteor-streak { | ||
| 0% { opacity: 0; transform: rotate(-25deg) translateX(0); } | ||
| 5% { opacity: 1; } | ||
| 15% { opacity: 0.8; } | ||
| 25% { opacity: 0; transform: rotate(-25deg) translateX(100%); } | ||
| 100% { opacity: 0; transform: rotate(-25deg) translateX(100%); } | ||
| } |
There was a problem hiding this comment.
The keyframes replace each meteor's complete inline transform with rotate(-25deg). Meteors configured at -15°, -35°, and -20° therefore snap to -25° during animation and lose their distinct trajectories.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src/styles/index.css
Line: 337-343
Comment:
**Meteor Angles Are Overwritten**
The keyframes replace each meteor's complete inline transform with `rotate(-25deg)`. Meteors configured at -15°, -35°, and -20° therefore snap to -25° during animation and lose their distinct trajectories.
How can I resolve this? If you propose a fix, please make it concise.| @keyframes orbit-rotate { | ||
| 0% { transform: rotateX(70deg) rotateZ(0deg); } | ||
| 100% { transform: rotateX(70deg) rotateZ(360deg); } | ||
| } |
There was a problem hiding this comment.
These keyframes replace the complete transforms supplied by the collision component. The rings configured at 65° and 75°, with different starting Z rotations, both animate at 70° and lose the intended layered orbit geometry.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src/styles/index.css
Line: 350-353
Comment:
**Orbit Tilts Are Overwritten**
These keyframes replace the complete transforms supplied by the collision component. The rings configured at 65° and 75°, with different starting Z rotations, both animate at 70° and lose the intended layered orbit geometry.
How can I resolve this? If you propose a fix, please make it concise.| const [isTabActive, setIsTabActive] = useState(true); | ||
| const animating = !prefersReducedMotion && isTabActive; |
There was a problem hiding this comment.
Hidden Mount Starts Animations
isTabActive starts as true without checking document.hidden. When the layout first mounts in an already-hidden tab, every enabled background animation starts until a later visibility event updates this state, defeating the resource-saving gate.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src/hooks/useBackgroundTheme.ts
Line: 34-35
Comment:
**Hidden Mount Starts Animations**
`isTabActive` starts as `true` without checking `document.hidden`. When the layout first mounts in an already-hidden tab, every enabled background animation starts until a later visibility event updates this state, defeating the resource-saving gate.
How can I resolve this? If you propose a fix, please make it concise.| <AnimatePresence mode="wait"> | ||
| <motion.div | ||
| key={currentTheme} | ||
| className="absolute inset-0" | ||
| initial={{ opacity: 0 }} | ||
| animate={{ opacity: 1 }} | ||
| exit={{ opacity: 0 }} | ||
| transition={{ duration: 1.2, ease: 'easeInOut' }} | ||
| > | ||
| <Suspense fallback={<FallbackLoader />}> | ||
| {ThemeComponent && <ThemeComponent animating={animating} />} | ||
| </Suspense> |
There was a problem hiding this comment.
Theme Switch Shows Loading Frame
With mode="wait", the next lazy theme is not mounted until the old theme finishes its 1.2-second exit. If its chunk is not cached, the dark fallback then replaces the background while loading, producing a visible blank step between themes on slower connections.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src/components/DynamicBackground/DynamicBackground.tsx
Line: 58-69
Comment:
**Theme Switch Shows Loading Frame**
With `mode="wait"`, the next lazy theme is not mounted until the old theme finishes its 1.2-second exit. If its chunk is not cached, the dark fallback then replaces the background while loading, producing a visible blank step between themes on slower connections.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Pull request overview
Adds a dynamic animated dashboard background system that selects a space-themed theme based on live conditions (space weather + collision risk) and time-of-day, and integrates it behind the main app layout.
Changes:
- Introduces a theme evaluation engine (
evaluateTheme) plus a React hook to compute the active background theme. - Adds a lazily loaded
DynamicBackgroundcomponent and multiple theme-specific background renderers (Day/Night/Aurora/Solar Storm/Meteor/Collision Alert). - Updates several UI surfaces to be more translucent / blurred so the background can show through.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/src/utils/backgroundEngine.ts | Adds theme definitions, priority model, and theme evaluation logic. |
| frontend/src/hooks/useBackgroundTheme.ts | Adds hook that queries weather/collisions and computes the current theme + animation gating. |
| frontend/src/components/DynamicBackground/DynamicBackground.tsx | Adds background host with lazy-loaded theme components and crossfade transitions. |
| frontend/src/components/DynamicBackground/DayBackground.tsx | Implements day-mode background visuals. |
| frontend/src/components/DynamicBackground/NightBackground.tsx | Implements night-mode background visuals. |
| frontend/src/components/DynamicBackground/AuroraBackground.tsx | Implements aurora-mode background visuals. |
| frontend/src/components/DynamicBackground/SolarStormBackground.tsx | Implements solar-storm-mode background visuals. |
| frontend/src/components/DynamicBackground/MeteorBackground.tsx | Implements meteor-shower-mode background visuals. |
| frontend/src/components/DynamicBackground/CollisionAlertBackground.tsx | Implements collision-alert-mode background visuals. |
| frontend/src/styles/index.css | Adds new keyframes and reduced-motion handling for background animations. |
| frontend/src/components/layouts/MainLayout.tsx | Mounts the dynamic background behind the app shell and adjusts shell translucency. |
| frontend/src/pages/Dashboard.tsx | Adjusts hero section styling to allow background to show through. |
| frontend/src/pages/CollisionCenter.tsx | Adjusts panel opacity/blur for background visibility. |
| frontend/src/pages/Satellites.tsx | Adjusts drawer border/background opacity for background visibility. |
| frontend/src/pages/AIAgents.tsx | Adjusts execution log panel translucency to match new background layering. |
| frontend/src/pages/NotFound.tsx | Removes fixed background class to allow background/layering to show. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <header className="h-12 backdrop-blur-xl bg-bg-deep-space/70 border-b border-border-panel/60 flex justify-between items-center px-4 md:px-6 w-full sticky top-0 z-30"> | ||
| {/* Command Search & Mobile Toggle */} | ||
| <div className="flex items-center gap-2 sm:gap-4 flex-1"> |
| export function useBackgroundTheme() { | ||
| const prefersReducedMotion = useReducedMotion(); | ||
| const weatherQuery = useWeatherStatus(); | ||
| const collisionsQuery = useCollisions({ size: 50 }); | ||
|
|
||
| const currentTheme = useMemo( | ||
| () => resolveAutoTheme(weatherQuery.data, collisionsQuery.data), | ||
| [weatherQuery.data, collisionsQuery.data] | ||
| ); | ||
|
|
||
| const [isTabActive, setIsTabActive] = useState(true); | ||
| const animating = !prefersReducedMotion && isTabActive; | ||
|
|
||
| useEffect(() => { | ||
| const handleVisibility = () => { | ||
| setIsTabActive(!document.hidden); | ||
| }; | ||
| document.addEventListener('visibilitychange', handleVisibility); | ||
| return () => | ||
| document.removeEventListener('visibilitychange', handleVisibility); | ||
| }, []); |
| export const DynamicBackground: React.FC = () => { | ||
| const { currentTheme, animating } = useBackgroundTheme(); | ||
| const ThemeComponent = themeComponents[currentTheme]; | ||
|
|
||
| return ( | ||
| <div className="fixed inset-0 z-0 pointer-events-none" aria-hidden="true"> | ||
| <AnimatePresence mode="wait"> | ||
| <motion.div | ||
| key={currentTheme} | ||
| className="absolute inset-0" | ||
| initial={{ opacity: 0 }} | ||
| animate={{ opacity: 1 }} | ||
| exit={{ opacity: 0 }} | ||
| transition={{ duration: 1.2, ease: 'easeInOut' }} | ||
| > |
| // Check weather status for solar storm / aurora / meteor | ||
| if (conditions.weatherStatus) { | ||
| const ws = conditions.weatherStatus; | ||
|
|
||
| // Solar storm: elevated active storm or flare count |
| @keyframes meteor-streak { | ||
| 0% { opacity: 0; transform: rotate(-25deg) translateX(0); } | ||
| 5% { opacity: 1; } | ||
| 15% { opacity: 0.8; } | ||
| 25% { opacity: 0; transform: rotate(-25deg) translateX(100%); } | ||
| 100% { opacity: 0; transform: rotate(-25deg) translateX(100%); } | ||
| } |
| @keyframes orbit-rotate { | ||
| 0% { transform: rotateX(70deg) rotateZ(0deg); } | ||
| 100% { transform: rotateX(70deg) rotateZ(360deg); } | ||
| } |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
frontend/src/styles/index.css (1)
355-361: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winReduced-motion override selector is app-wide, not scoped to the dynamic background.
[aria-hidden="true"] *matches descendants of anyaria-hidden="true"element anywhere in the app, not just the background layers. This could unintentionally zero out transitions/animations on unrelated decorativearia-hiddenelements elsewhere in the codebase.Suggested scoping
`@media` (prefers-reduced-motion: reduce) { - [aria-hidden="true"] * { + .dynamic-bg * { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; } }Add the
dynamic-bgclass to the root wrapper inDynamicBackground.tsx.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@frontend/src/styles/index.css` around lines 355 - 361, Scope the reduced-motion selector to the dynamic background by adding the dynamic-bg class to the root wrapper in DynamicBackground.tsx, then update the media-query selector in the stylesheet to target only descendants of that class with aria-hidden="true".frontend/src/components/DynamicBackground/DynamicBackground.tsx (1)
40-50: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winTighten
themeComponentskey type toBackgroundThemefor compile-time coverage.Typed as
Record<string, ...>, so adding a new value toBackgroundThemeswithout a matching entry here fails silently at runtime (ThemeComponentbecomesundefined) rather than at compile time.THEME_PRIORITYinbackgroundEngine.tsalready uses the stricterRecord<BackgroundTheme, number>pattern — mirror it here.Suggested fix
+import { BackgroundThemes, type BackgroundTheme } from '`@/utils/backgroundEngine`'; -import { BackgroundThemes } from '`@/utils/backgroundEngine`'; const themeComponents: Record< - string, + BackgroundTheme, React.LazyExoticComponent<React.FC<{ animating: boolean }>> > = {🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@frontend/src/components/DynamicBackground/DynamicBackground.tsx` around lines 40 - 50, Update the themeComponents declaration to use BackgroundTheme as its Record key type, matching the stricter THEME_PRIORITY typing pattern in backgroundEngine.ts. Keep the existing lazy component value type and all theme mappings unchanged so missing BackgroundThemes are reported at compile time.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@frontend/src/hooks/useBackgroundTheme.ts`:
- Around line 24-51: Update useBackgroundTheme to accept the persisted theme
preference and apply it when resolving currentTheme, allowing
Auto/Default/manual selections to override the weather and collision-derived
theme. Preserve the existing animation and visibility behavior, and thread the
preference through the existing theme resolution or override mechanism rather
than ignoring it.
In `@frontend/src/utils/backgroundEngine.ts`:
- Around line 3-10: Update evaluateTheme to add a METEOR_SHOWER candidate using
the available meteor-shower activity field on weatherStatus, following the
existing solar-storm and aurora condition patterns. Place this condition before
the COLLISION_ALERT check and preserve the defined theme priority so automatic
evaluation can return BackgroundThemes.METEOR_SHOWER.
- Around line 85-88: Update isDaytime() to use the user's local hour via
getHours() instead of UTC hours, while preserving the existing 6-inclusive
through 18-exclusive daytime window.
---
Nitpick comments:
In `@frontend/src/components/DynamicBackground/DynamicBackground.tsx`:
- Around line 40-50: Update the themeComponents declaration to use
BackgroundTheme as its Record key type, matching the stricter THEME_PRIORITY
typing pattern in backgroundEngine.ts. Keep the existing lazy component value
type and all theme mappings unchanged so missing BackgroundThemes are reported
at compile time.
In `@frontend/src/styles/index.css`:
- Around line 355-361: Scope the reduced-motion selector to the dynamic
background by adding the dynamic-bg class to the root wrapper in
DynamicBackground.tsx, then update the media-query selector in the stylesheet to
target only descendants of that class with aria-hidden="true".
🪄 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 Plus
Run ID: 4a909153-5edc-4019-97ff-43d79097c70e
📒 Files selected for processing (16)
frontend/src/components/DynamicBackground/AuroraBackground.tsxfrontend/src/components/DynamicBackground/CollisionAlertBackground.tsxfrontend/src/components/DynamicBackground/DayBackground.tsxfrontend/src/components/DynamicBackground/DynamicBackground.tsxfrontend/src/components/DynamicBackground/MeteorBackground.tsxfrontend/src/components/DynamicBackground/NightBackground.tsxfrontend/src/components/DynamicBackground/SolarStormBackground.tsxfrontend/src/components/layouts/MainLayout.tsxfrontend/src/hooks/useBackgroundTheme.tsfrontend/src/pages/AIAgents.tsxfrontend/src/pages/CollisionCenter.tsxfrontend/src/pages/Dashboard.tsxfrontend/src/pages/NotFound.tsxfrontend/src/pages/Satellites.tsxfrontend/src/styles/index.cssfrontend/src/utils/backgroundEngine.ts
| export function useBackgroundTheme() { | ||
| const prefersReducedMotion = useReducedMotion(); | ||
| const weatherQuery = useWeatherStatus(); | ||
| const collisionsQuery = useCollisions({ size: 50 }); | ||
|
|
||
| const currentTheme = useMemo( | ||
| () => resolveAutoTheme(weatherQuery.data, collisionsQuery.data), | ||
| [weatherQuery.data, collisionsQuery.data] | ||
| ); | ||
|
|
||
| const [isTabActive, setIsTabActive] = useState(true); | ||
| const animating = !prefersReducedMotion && isTabActive; | ||
|
|
||
| useEffect(() => { | ||
| const handleVisibility = () => { | ||
| setIsTabActive(!document.hidden); | ||
| }; | ||
| document.addEventListener('visibilitychange', handleVisibility); | ||
| return () => | ||
| document.removeEventListener('visibilitychange', handleVisibility); | ||
| }, []); | ||
|
|
||
| return { | ||
| currentTheme, | ||
| animating, | ||
| prefersReducedMotion: !!prefersReducedMotion, | ||
| }; | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
rg -n "localStorage" frontend/src -g '*.ts' -g '*.tsx'
rg -n "BackgroundThemes\.|useBackgroundTheme" frontend/src/components -g '*.tsx' -A3 -B3Repository: 7-Blocks/Kepler
Length of output: 2456
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== useBackgroundTheme =="
sed -n '1,220p' frontend/src/hooks/useBackgroundTheme.ts
echo
echo "== background-related components/hooks =="
rg -n "BackgroundThemes|useBackgroundTheme|theme|localStorage|auto" frontend/src/components frontend/src/hooks frontend/src/utils -g '*.ts' -g '*.tsx' -g '*.js' -g '*.jsx' -A4 -B4
echo
echo "== potential theme selector files =="
fd -i "theme" frontend/src
fd -i "background" frontend/srcRepository: 7-Blocks/Kepler
Length of output: 42599
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== all theme-related symbols =="
rg -n "useBackgroundTheme|resolveAutoTheme|BackgroundThemes|set.*Theme|theme.*set|localStorage|Auto" frontend/src -g '*.ts' -g '*.tsx' -A3 -B3
echo
echo "== inspect background engine and hook =="
sed -n '1,220p' frontend/src/utils/backgroundEngine.ts
sed -n '1,220p' frontend/src/hooks/useBackgroundTheme.ts
echo
echo "== inspect dynamic background component =="
sed -n '1,220p' frontend/src/components/DynamicBackground/DynamicBackground.tsxRepository: 7-Blocks/Kepler
Length of output: 26854
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== repo-wide localStorage usage =="
rg -n "localStorage" . -g '*.ts' -g '*.tsx' -g '*.js' -g '*.jsx' -g '*.md' -A2 -B2
echo
echo "== repo-wide theme selector terms =="
rg -n "Auto|Default|manual.*theme|theme.*selector|selector.*theme|background theme" frontend . -g '*.ts' -g '*.tsx' -g '*.js' -g '*.jsx' -g '*.md' -A3 -B3Repository: 7-Blocks/Kepler
Length of output: 188
Pass the saved theme preference into useBackgroundTheme. currentTheme is always recomputed from weather/collision data, so a user-selected Auto/Default/manual preference can’t override the background here. Thread the persisted choice into this hook (or an override layer) so the selector can take effect.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@frontend/src/hooks/useBackgroundTheme.ts` around lines 24 - 51, Update
useBackgroundTheme to accept the persisted theme preference and apply it when
resolving currentTheme, allowing Auto/Default/manual selections to override the
weather and collision-derived theme. Preserve the existing animation and
visibility behavior, and thread the preference through the existing theme
resolution or override mechanism rather than ignoring it.
| export const BackgroundThemes = { | ||
| DAY: 'day', | ||
| NIGHT: 'night', | ||
| SOLAR_STORM: 'solar-storm', | ||
| AURORA: 'aurora', | ||
| METEOR_SHOWER: 'meteor-shower', | ||
| COLLISION_ALERT: 'collision-alert', | ||
| } as const; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Meteor Shower theme is unreachable — evaluateTheme never produces it.
METEOR_SHOWER is defined and prioritized, and DynamicBackground.tsx maps it to a component, but no branch in evaluateTheme ever pushes a METEOR_SHOWER candidate. Per issue #94, Meteor Shower is one of the six required automatic themes, so this acceptance criterion is currently unmet — the theme is dead code that can only ever be reached via a (not-shown) manual override.
Suggested fix direction
// Check collisions for high-risk conjunctions
if (conditions.collisions && conditions.collisions.length > 0) {Add a meteor-shower condition (e.g. based on a meteor_shower_active/similar field on weatherStatus, if the API exposes one) before the collision check, mirroring the solar-storm/aurora pattern.
Also applies to: 22-29, 31-83
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@frontend/src/utils/backgroundEngine.ts` around lines 3 - 10, Update
evaluateTheme to add a METEOR_SHOWER candidate using the available meteor-shower
activity field on weatherStatus, following the existing solar-storm and aurora
condition patterns. Place this condition before the COLLISION_ALERT check and
preserve the defined theme priority so automatic evaluation can return
BackgroundThemes.METEOR_SHOWER.
| export function isDaytime(): boolean { | ||
| const hour = new Date().getUTCHours(); | ||
| return hour >= 6 && hour < 18; | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
isDaytime() uses UTC hours, breaking day/night theming for non-UTC users.
getUTCHours() with a fixed 6–18 window means the Day/Night theme boundary is only correct for users in UTC+0. For most timezones the app will show "Day" background during local night and vice versa, defeating the "time of day" requirement from issue #94.
Suggested fix
export function isDaytime(): boolean {
- const hour = new Date().getUTCHours();
+ const hour = new Date().getHours();
return hour >= 6 && hour < 18;
}📝 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.
| export function isDaytime(): boolean { | |
| const hour = new Date().getUTCHours(); | |
| return hour >= 6 && hour < 18; | |
| } | |
| export function isDaytime(): boolean { | |
| const hour = new Date().getHours(); | |
| return hour >= 6 && hour < 18; | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@frontend/src/utils/backgroundEngine.ts` around lines 85 - 88, Update
isDaytime() to use the user's local hour via getHours() instead of UTC hours,
while preserving the existing 6-inclusive through 18-exclusive daytime window.
Description
Added a dynamic background system for the dashboard that switches between space-themed animations based on live conditions like space weather, collision risk, and time of day. There's also a manual override dropdown in the top bar.
Related Issue
Fixes #94
Checklist
Screenshots / Screen Recordings
More themes, as specified in the issue to create. Just check them out.
Breaking Changes
No breaking changes. The background sits behind all existing UI and doesn't affect any current functionality.
ECSoC26 Submission
ECSoC26-L1– BeginnerECSoC26-L2– IntermediateECSoC26-L3– AdvancedSummary by CodeRabbit
New Features
Style
Greptile Summary
This PR adds condition-driven animated backgrounds to the dashboard. The main changes are:
Confidence Score: 4/5
Time-based selection, collision coverage, and per-element animation transforms can produce incorrect backgrounds and need fixes before merging.
frontend/src/hooks/useBackgroundTheme.ts, frontend/src/utils/backgroundEngine.ts, and frontend/src/styles/index.css
Important Files Changed
Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart TD W[Weather query] --> H[useBackgroundTheme] C[Collision query] --> H T[Current time] --> H H --> E[evaluateTheme] E --> D[DynamicBackground] D --> L[Lazy theme component] L --> A[CSS animation layer] D --> M[MainLayout background]Prompt To Fix All With AI
Reviews (1): Last reviewed commit: "More Theme Ambience Fixes" | Re-trigger Greptile