Musynth ships with a single, carefully hand-tuned dark theme built around a deep navy palette with amber accents. On top of this static foundation, the Now Playing screen dynamically recolors itself to reflect the dominant hue extracted from the current album’s artwork — updating the status bar brightness, text color, icon tints, and blurred background with each track change. This page covers the static theme constants, the customized sub-themes, theDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/CesarArellano/Music-Player-App/llms.txt
Use this file to discover all available pages before exploring further.
AppBackground/AppScaffold composition pattern, and the dynamic color pipeline in full.
AppTheme.darkTheme — Color Constants
All color decisions are centralized in lib/theme/app_theme.dart. The base constants are:
| Constant | Value | Usage |
|---|---|---|
primaryColor | Color(0xFF003D71) | Bottom navigation bar background |
backgroundBase | Color(0xFF0C1D30) | Scaffold background (opaque, deep navy) |
surfaceColor | Color(0xFF112240) | Cards, bottom sheets, list surfaces |
accentColor | Colors.amber | FAB, scrollbar thumb, secondary color scheme |
lightTextColor | Colors.white54 | Subtitle text, unselected icons |
Customized Sub-Themes
AppTheme.darkTheme is built with ThemeData.dark().copyWith(...). Every sub-theme is set explicitly so no screen depends on Flutter’s default dark theme fallbacks.
ScrollbarThemeData — amber scrollbar thumb
ScrollbarThemeData — amber scrollbar thumb
AppBarTheme — transparent, white title
AppBarTheme — transparent, white title
AppBackground (the custom-painted gradient backdrop) show through the app bar region. scrolledUnderElevation: 0 prevents the “tint on scroll” elevation effect that would obscure the background.CardThemeData — surfaceColor, rounded corners
CardThemeData — surfaceColor, rounded corners
Clip.hardEdge ensures artwork images inside cards are clipped to the rounded corners without an additional ClipRRect wrapper.ListTileThemeData
ListTileThemeData
BottomNavigationBarThemeData — primaryColor background
BottomNavigationBarThemeData — primaryColor background
BottomSheetThemeData — surfaceColor, rounded top
BottomSheetThemeData — surfaceColor, rounded top
ShapeBorder required.DividerThemeData — subtle white12
DividerThemeData — subtle white12
backgroundBase and surfaceColor without being distracting.AppBackground and AppScaffold
Every screen in Musynth is wrapped in AppScaffold, a thin widget that passes AppBackground (a CustomPaint-based gradient blob painter) as the body of a standard Scaffold. AppBackground fills the entire screen by drawing a deep navy base color and six soft radial gradient blobs that create a depth illusion — no image asset is involved.
AppScaffold sets the inner Scaffold’s backgroundColor to Colors.transparent so AppBackground (painted as the Scaffold’s body) can fill the screen. AppBackground uses CustomPaint to draw an opaque deep-navy base color, making each screen fully opaque. During a route transition, the outgoing and incoming screens are both fully opaque — neither screen shows the route behind it. This prevents z-ordering artifacts during navigation.AppBackground layer, and every sub-theme override must be scoped inside that screen’s widget tree (e.g., via a local Theme widget). Never rely on a global background rendered outside the Navigator.
Dynamic Now Playing Colors
The Now Playing screen (SongPlayedScreen) overrides the inherited dark theme with colors derived from the currently playing album’s dominant color. The pipeline has three stages: extraction → caching → application.
Stage 1 — Native Dominant Color Extraction
WhenPlaybackStateCubit emits a new song, UICubit subscribes to the stream and calls searchDominantColorByAlbumId:
- Android:
androidx.palette— analyzes the decoded bitmap and returns the vibrant/dominant swatch - iOS: Core Image
CIAreaAverage— averages pixel values over the artwork region
SharedPreferences (via SharedPreferencesRepository.dominantColorCollection) so the cache survives app restarts. See Isolates → dominantColorCollection setter for how the JSON encoding is offloaded.
Stage 2 — Computed Color Properties in UIState
UIState exposes three derived properties computed from currentDominantColor:
0.4 was chosen empirically — colors above this value are bright enough that dark text reads better against them; below it, white text is preferable.
Stage 3 — SongPlayedScreen Local Theme Override
SongPlayedScreen.build() wraps the entire screen in a local Theme widget that overrides only the color-sensitive properties, leaving the rest of AppTheme.darkTheme intact:
AnnotatedRegion<SystemUiOverlayStyle> above this Theme sets the system status bar icon brightness to match:
Background Blur — ImageFiltered, Not BackdropFilter
The Now Playing background blurs the artwork image using ImageFiltered wrapping an Image.file, not BackdropFilter:
BackdropFilter samples everything behind its layer, including whatever route is transitioning in or out. During the open/close slide animation this would blur the home screen behind the Now Playing screen — a visible artefact. ImageFiltered blurs only its own child (Image.file), so no route behind it is affected.Container with dominantColor.withValues(alpha: 0.8) is stacked on top of the blurred image, tinting the background with the dominant hue for a cohesive look.