feat(shell): dynamic background shows through content area + livelier ambient
Smoke round 2 (owner feedback: content area was an opaque black slab, motion
imperceptible, ambient≈blurred).
- Content-area sweep: 27 content-view roots go transparent when the app
background is active (was opaque Theme.surface-main covering the background) —
Home/Discover/Album/Artist/Search-adjacent/Favorites/Playlist/LocalLibrary/
MyQBZ/managers/etc. Content well (AppShell) transparent too.
- SongCard (NPB classic), search input box, cortinilla panel go translucent so
they stop reading as opaque slabs over the background.
- ambient.wgsl: much faster + bigger blob travel + stronger domain warp +
brighter/more saturated so the flow is obviously moving and clearly distinct
from the blurred-art mode.
- Defaults: dim 0.35, surface-alpha 0.5.
Checkpoint during smoke iteration (owner-requested). Base: 76ea5a82.
cc
This commit is contained in:
33 files changed
+94
-70
No files matched your search
@@ -186,7 +186,7 @@ export component AlbumPageView inherits Rectangle {
|
||||
// the page layout, so this cannot form a binding loop.
|
||||
property <length> atmo-height: page.y + header-divider.y;
|
||||
|
||||
background: Theme.surface-main;
|
||||
background: ShellState.app-background-active ? transparent : Theme.surface-main;
|
||||
|
||||
flick := Flickable {
|
||||
// Full-width: the gradient + page background bleed edge-to-edge so
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
import { Theme } from "../foundation/semantic-colors.slint";
|
||||
import { Typography } from "../foundation/typography.slint";
|
||||
import { LocalAlbumState, LocalAlbumActions, LocalAlbumVersion, NowPlayingState, NavState, DragState, UiFocusState } from "../state.slint";
|
||||
import { LocalAlbumState, LocalAlbumActions, LocalAlbumVersion, NowPlayingState, NavState, DragState, UiFocusState, ShellState } from "../state.slint";
|
||||
import { NavButtons } from "../shell/NavButtons.slint";
|
||||
import { CircleAction } from "../primitives/CircleAction.slint";
|
||||
import { QbzIcon } from "../primitives/QbzIcon.slint";
|
||||
@@ -148,7 +148,7 @@ export component LocalAlbumView inherits Rectangle {
|
||||
// Navigate to the artist (the NAME — local/Plex artists have no id; the
|
||||
// source-aware open-artist routes a name to the LocalLibrary Artists tab).
|
||||
callback open-artist(string);
|
||||
background: Theme.surface-main;
|
||||
background: ShellState.app-background-active ? transparent : Theme.surface-main;
|
||||
|
||||
// Homologated 1:1 with the Qobuz AlbumPageView: whole-page Flickable, the
|
||||
// same header proportions + action row, the toolbar (quality badge + track
|
||||
|
||||
@@ -172,7 +172,7 @@ export component ArtistPageView inherits Rectangle {
|
||||
NetworkSidebarState.open = !root.net-cramped;
|
||||
}
|
||||
|
||||
background: Theme.surface-main;
|
||||
background: ShellState.app-background-active ? transparent : Theme.surface-main;
|
||||
|
||||
// Single page-wide Flickable — the gradient header + body row
|
||||
// (main content + sidebar-slot placeholder) all live inside it so
|
||||
|
||||
@@ -27,7 +27,7 @@ export component ArtistReleasesView inherits Rectangle {
|
||||
ArtistReleasesState.sort-by == "title-asc" ? 3 :
|
||||
ArtistReleasesState.sort-by == "title-desc" ? 4 : 0;
|
||||
|
||||
background: Theme.surface-main;
|
||||
background: ShellState.app-background-active ? transparent : Theme.surface-main;
|
||||
|
||||
VerticalLayout {
|
||||
spacing: 0px;
|
||||
|
||||
@@ -118,7 +118,7 @@ export component AwardAlbumsView inherits Rectangle {
|
||||
property <length> album-h: 266px;
|
||||
property <length> gap: 24px;
|
||||
|
||||
background: Theme.surface-main;
|
||||
background: ShellState.app-background-active ? transparent : Theme.surface-main;
|
||||
|
||||
VerticalLayout {
|
||||
spacing: 0px;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
import { Theme } from "../foundation/semantic-colors.slint";
|
||||
import { Typography } from "../foundation/typography.slint";
|
||||
import { AwardState, AwardActions, NavState, DragState } from "../state.slint";
|
||||
import { AwardState, AwardActions, NavState, DragState, ShellState } from "../state.slint";
|
||||
import { QbzIcon } from "../primitives/QbzIcon.slint";
|
||||
import { CircleAction } from "../primitives/CircleAction.slint";
|
||||
import { LoadingSpinner } from "../primitives/LoadingSpinner.slint";
|
||||
@@ -34,7 +34,7 @@ export component AwardView inherits Rectangle {
|
||||
callback open-artist(string);
|
||||
callback media-action(string, string, string);
|
||||
|
||||
background: Theme.surface-main;
|
||||
background: ShellState.app-background-active ? transparent : Theme.surface-main;
|
||||
|
||||
page-flickable := Flickable {
|
||||
// Don't scroll while a track is being dragged out (keeps the row's
|
||||
|
||||
@@ -29,7 +29,7 @@ export component DiscoverBrowseView inherits Rectangle {
|
||||
property <length> list-row-h: 64px;
|
||||
property <length> list-row-gap: 4px;
|
||||
|
||||
background: Theme.surface-main;
|
||||
background: ShellState.app-background-active ? transparent : Theme.surface-main;
|
||||
|
||||
VerticalLayout {
|
||||
spacing: 0px;
|
||||
|
||||
@@ -160,7 +160,7 @@ export component HomeView inherits Rectangle {
|
||||
// the link.
|
||||
callback discover-view-all(string, string);
|
||||
|
||||
background: Theme.surface-main;
|
||||
background: ShellState.app-background-active ? transparent : Theme.surface-main;
|
||||
|
||||
// The view remounts on every navigation to Home (AppShell's `if` mount),
|
||||
// so this is the "Home regained focus" hook: Rust re-reads the LOCAL
|
||||
|
||||
@@ -79,7 +79,7 @@ export component PlaylistBrowseView inherits Rectangle {
|
||||
// 36px tag bar when the tag set is non-empty.
|
||||
property <length> header-h: PlaylistBrowseState.tags.length > 0 ? 92px : 56px;
|
||||
|
||||
background: Theme.surface-main;
|
||||
background: ShellState.app-background-active ? transparent : Theme.surface-main;
|
||||
|
||||
VerticalLayout {
|
||||
spacing: 0px;
|
||||
|
||||
@@ -28,7 +28,7 @@ export component RecentAlbumsView inherits Rectangle {
|
||||
property <length> album-h: 266px;
|
||||
property <length> gap: 24px;
|
||||
|
||||
background: Theme.surface-main;
|
||||
background: ShellState.app-background-active ? transparent : Theme.surface-main;
|
||||
|
||||
VerticalLayout {
|
||||
spacing: 0px;
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
GenreFilterActions,
|
||||
AlphaJump,
|
||||
NavState,
|
||||
ShellState,
|
||||
} from "../state.slint";
|
||||
import { AlbumCollectionView } from "../discover/AlbumCollectionView.slint";
|
||||
import { PlaylistCard } from "../discover/PlaylistCard.slint";
|
||||
@@ -382,7 +383,7 @@ export component FavoritesView inherits Rectangle {
|
||||
property <length> artist-h: 200px;
|
||||
property <length> gap: 24px;
|
||||
|
||||
background: Theme.surface-main;
|
||||
background: ShellState.app-background-active ? transparent : Theme.surface-main;
|
||||
|
||||
VerticalLayout {
|
||||
spacing: 0px;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
import { Theme } from "../foundation/semantic-colors.slint";
|
||||
import { Typography } from "../foundation/typography.slint";
|
||||
import { Radius } from "../foundation/radius.slint";
|
||||
import { LabelState, LabelActions, TrackItem, DragState, NavState, BulkAction } from "../state.slint";
|
||||
import { LabelState, LabelActions, TrackItem, DragState, NavState, BulkAction, ShellState } from "../state.slint";
|
||||
import { QbzIcon } from "../primitives/QbzIcon.slint";
|
||||
import { TrackRow } from "../primitives/TrackRow.slint";
|
||||
import { CircleAction } from "../primitives/CircleAction.slint";
|
||||
@@ -44,7 +44,7 @@ export component LabelPageView inherits Rectangle {
|
||||
// Popular Tracks progressive reveal: 5 -> 20 -> 50 (Tauri's steps).
|
||||
property <int> preview-count: 5;
|
||||
|
||||
background: Theme.surface-main;
|
||||
background: ShellState.app-background-active ? transparent : Theme.surface-main;
|
||||
|
||||
page-flickable := Flickable {
|
||||
// Don't scroll while a track is being dragged out (keeps the row's
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
import { Theme } from "../foundation/semantic-colors.slint";
|
||||
import { Typography } from "../foundation/typography.slint";
|
||||
import { Radius } from "../foundation/radius.slint";
|
||||
import { LabelState, LabelActions, NavState } from "../state.slint";
|
||||
import { LabelState, LabelActions, NavState, ShellState } from "../state.slint";
|
||||
import { AlbumCollectionView } from "../discover/AlbumCollectionView.slint";
|
||||
import { QbzIcon } from "../primitives/QbzIcon.slint";
|
||||
import { QbzSelect } from "../primitives/QbzSelect.slint";
|
||||
@@ -27,7 +27,7 @@ export component LabelReleasesView inherits Rectangle {
|
||||
|
||||
property <length> list-row-gap: 4px;
|
||||
|
||||
background: Theme.surface-main;
|
||||
background: ShellState.app-background-active ? transparent : Theme.surface-main;
|
||||
|
||||
flick := Flickable {
|
||||
viewport-width: self.width;
|
||||
|
||||
@@ -31,7 +31,7 @@ import { TrackRow } from "../primitives/TrackRow.slint";
|
||||
import { ToggleButton } from "../primitives/ToggleButton.slint";
|
||||
import { MultiSelectBar } from "../primitives/MultiSelectBar.slint";
|
||||
import { TooltipState } from "../state.slint";
|
||||
import { UiFocusState } from "../state.slint";
|
||||
import { UiFocusState, ShellState } from "../state.slint";
|
||||
import { SegmentedTabBar, SegTab } from "../primitives/SegmentedTabBar.slint";
|
||||
import { ListView } from "std-widgets.slint";
|
||||
|
||||
@@ -702,7 +702,7 @@ component FilterChip inherits Rectangle {
|
||||
}
|
||||
|
||||
export component LocalLibraryView inherits Rectangle {
|
||||
background: Theme.surface-main;
|
||||
background: ShellState.app-background-active ? transparent : Theme.surface-main;
|
||||
|
||||
VerticalLayout {
|
||||
spacing: 0px;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
import { Theme } from "../foundation/semantic-colors.slint";
|
||||
import { Typography } from "../foundation/typography.slint";
|
||||
import { LocationViewState, LocationViewActions, LocationArtistItem, NavState } from "../state.slint";
|
||||
import { LocationViewState, LocationViewActions, LocationArtistItem, NavState, ShellState } from "../state.slint";
|
||||
import { QbzIcon } from "../primitives/QbzIcon.slint";
|
||||
import { LoadingSpinner } from "../primitives/LoadingSpinner.slint";
|
||||
import { ListScrollbar } from "../primitives/ListScrollbar.slint";
|
||||
@@ -82,7 +82,7 @@ export component ArtistsByLocationView inherits Rectangle {
|
||||
property <length> card-height: 210px;
|
||||
property <length> card-gap: 20px;
|
||||
|
||||
background: Theme.surface-main;
|
||||
background: ShellState.app-background-active ? transparent : Theme.surface-main;
|
||||
|
||||
flick := Flickable {
|
||||
viewport-width: self.width;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
import { Theme } from "../foundation/semantic-colors.slint";
|
||||
import { Typography } from "../foundation/typography.slint";
|
||||
import { Radius } from "../foundation/radius.slint";
|
||||
import { MixState, DragState, NavState, BulkAction } from "../state.slint";
|
||||
import { MixState, DragState, NavState, BulkAction, ShellState } from "../state.slint";
|
||||
import { QbzIcon } from "../primitives/QbzIcon.slint";
|
||||
import { TrackRow } from "../primitives/TrackRow.slint";
|
||||
import { LoadingSpinner } from "../primitives/LoadingSpinner.slint";
|
||||
@@ -69,7 +69,7 @@ export component MixView inherits Rectangle {
|
||||
? @linear-gradient(135deg, #7f1d1d 0%, #ef4444 50%, #fb923c 100%)
|
||||
: @linear-gradient(135deg, #1f2937 0%, #4b5563 50%, #fbbf24 100%);
|
||||
|
||||
background: Theme.surface-main;
|
||||
background: ShellState.app-background-active ? transparent : Theme.surface-main;
|
||||
|
||||
flick := Flickable {
|
||||
interactive: !DragState.active;
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
MusicianActions,
|
||||
MusicianAppearanceItem,
|
||||
NavState,
|
||||
ShellState,
|
||||
} from "../state.slint";
|
||||
import { QbzIcon } from "../primitives/QbzIcon.slint";
|
||||
import { LoadingSpinner } from "../primitives/LoadingSpinner.slint";
|
||||
@@ -89,7 +90,7 @@ export component MusicianPageView inherits Rectangle {
|
||||
property <length> card-height: 270px;
|
||||
property <length> card-gap: 24px;
|
||||
|
||||
background: Theme.surface-main;
|
||||
background: ShellState.app-background-active ? transparent : Theme.surface-main;
|
||||
|
||||
flick := Flickable {
|
||||
viewport-width: self.width;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
import { Theme } from "../foundation/semantic-colors.slint";
|
||||
import { Typography } from "../foundation/typography.slint";
|
||||
import { MyQbzState, MyQbzActions, MixtapeCardItem, NavState } from "../state.slint";
|
||||
import { MyQbzState, MyQbzActions, MixtapeCardItem, NavState, ShellState } from "../state.slint";
|
||||
import { ExpandableSearch } from "../primitives/ExpandableSearch.slint";
|
||||
import { QbzSelect } from "../primitives/QbzSelect.slint";
|
||||
import { ListScrollbar } from "../primitives/ListScrollbar.slint";
|
||||
@@ -31,7 +31,7 @@ export component CollectionsView inherits Rectangle {
|
||||
: MyQbzState.col-kind-filter == "artist_collection" ? 2
|
||||
: 0;
|
||||
|
||||
background: Theme.surface-main;
|
||||
background: ShellState.app-background-active ? transparent : Theme.surface-main;
|
||||
|
||||
flick := Flickable {
|
||||
viewport-width: self.width;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
import { Theme } from "../foundation/semantic-colors.slint";
|
||||
import { Typography } from "../foundation/typography.slint";
|
||||
import { Radius } from "../foundation/radius.slint";
|
||||
import { MyQbzDetailState, MyQbzDetailActions, MixtapeDetailItem, TrackItem, NavState } from "../state.slint";
|
||||
import { MyQbzDetailState, MyQbzDetailActions, MixtapeDetailItem, TrackItem, NavState, ShellState } from "../state.slint";
|
||||
import { QbzIcon } from "../primitives/QbzIcon.slint";
|
||||
import { CircleAction } from "../primitives/CircleAction.slint";
|
||||
import { ToggleButton } from "../primitives/ToggleButton.slint";
|
||||
@@ -593,7 +593,7 @@ export component MixtapeDetailView inherits Rectangle {
|
||||
property <length> grid-min-w: 150px;
|
||||
property <length> grid-gap: 20px;
|
||||
|
||||
background: Theme.surface-main;
|
||||
background: ShellState.app-background-active ? transparent : Theme.surface-main;
|
||||
|
||||
// ===================== LOADING =====================================
|
||||
if MyQbzDetailState.loading: HorizontalLayout {
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import { Theme } from "../foundation/semantic-colors.slint";
|
||||
import { Typography } from "../foundation/typography.slint";
|
||||
import { MyQbzState, MyQbzActions, MixtapeCardItem, NavState } from "../state.slint";
|
||||
import { MyQbzState, MyQbzActions, MixtapeCardItem, NavState, ShellState } from "../state.slint";
|
||||
import { ExpandableSearch } from "../primitives/ExpandableSearch.slint";
|
||||
import { QbzSelect } from "../primitives/QbzSelect.slint";
|
||||
import { ListScrollbar } from "../primitives/ListScrollbar.slint";
|
||||
@@ -31,7 +31,7 @@ export component MixtapesView inherits Rectangle {
|
||||
: MyQbzState.mix-sort == "updated" ? 3
|
||||
: 0;
|
||||
|
||||
background: Theme.surface-main;
|
||||
background: ShellState.app-background-active ? transparent : Theme.surface-main;
|
||||
|
||||
flick := Flickable {
|
||||
viewport-width: self.width;
|
||||
|
||||
@@ -158,7 +158,7 @@ component BulkIconBtn inherits Rectangle {
|
||||
}
|
||||
|
||||
export component OfflineManagerView inherits Rectangle {
|
||||
background: Theme.surface-main;
|
||||
background: ShellState.app-background-active ? transparent : Theme.surface-main;
|
||||
|
||||
VerticalLayout {
|
||||
padding: 24px;
|
||||
|
||||
@@ -9,10 +9,10 @@ import { Theme } from "../foundation/semantic-colors.slint";
|
||||
import { Typography } from "../foundation/typography.slint";
|
||||
import { QbzIcon } from "../primitives/QbzIcon.slint";
|
||||
import { SecondaryButton } from "../primitives/SecondaryButton.slint";
|
||||
import { OfflineState, NavState, SettingsState } from "../state.slint";
|
||||
import { OfflineState, NavState, SettingsState, ShellState } from "../state.slint";
|
||||
|
||||
export component OfflinePlaceholder inherits Rectangle {
|
||||
background: Theme.surface-main;
|
||||
background: ShellState.app-background-active ? transparent : Theme.surface-main;
|
||||
|
||||
// 2 = induced offline (OfflineState.mode semantics: 0 online / 1 real / 2 induced).
|
||||
property <bool> induced: OfflineState.mode == 2;
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
PmTreeRow,
|
||||
NavState,
|
||||
UiFocusState,
|
||||
ShellState,
|
||||
} from "../state.slint";
|
||||
import { QbzIcon } from "../primitives/QbzIcon.slint";
|
||||
import { LoadingSpinner } from "../primitives/LoadingSpinner.slint";
|
||||
@@ -1080,7 +1081,7 @@ export component PlaylistManagerView inherits Rectangle {
|
||||
: @image-url("../assets/icons/layout-grid.svg"))
|
||||
: @image-url("../assets/icons/layout-grid.svg");
|
||||
|
||||
background: Theme.surface-main;
|
||||
background: ShellState.app-background-active ? transparent : Theme.surface-main;
|
||||
|
||||
VerticalLayout {
|
||||
spacing: 0px;
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Theme } from "../foundation/semantic-colors.slint";
|
||||
import { Typography } from "../foundation/typography.slint";
|
||||
import { Radius } from "../foundation/radius.slint";
|
||||
import { PlaylistState, PlaylistActions, PinnedActions, DragState, NavState, OfflineState, BulkAction, SettingsState } from "../state.slint";
|
||||
import { PlaylistSuggestionsState, PlaylistSuggestionsActions, PlaylistSuggestionRow, TooltipState } from "../state.slint";
|
||||
import { PlaylistSuggestionsState, PlaylistSuggestionsActions, PlaylistSuggestionRow, TooltipState, ShellState } from "../state.slint";
|
||||
import { QbzIcon } from "../primitives/QbzIcon.slint";
|
||||
import { CircleAction } from "../primitives/CircleAction.slint";
|
||||
import { TrackRow } from "../primitives/TrackRow.slint";
|
||||
@@ -418,7 +418,7 @@ export component PlaylistView inherits Rectangle {
|
||||
root.reorder-drop-playlist = "";
|
||||
}
|
||||
|
||||
background: Theme.surface-main;
|
||||
background: ShellState.app-background-active ? transparent : Theme.surface-main;
|
||||
|
||||
page := VerticalLayout {
|
||||
// Fill PlaylistView so the ListView's vertical-stretch has
|
||||
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
PurchaseDetailState,
|
||||
PurchaseDetailActions,
|
||||
PurchaseDetailTrack,
|
||||
ShellState,
|
||||
} from "../state.slint";
|
||||
|
||||
// ── One detail track row (bespoke, §2.2.5) ──────────────────────────────────
|
||||
@@ -210,7 +211,7 @@ component DetailTrackRow inherits Rectangle {
|
||||
}
|
||||
|
||||
export component PurchaseDetailView inherits Rectangle {
|
||||
background: Theme.surface-main;
|
||||
background: ShellState.app-background-active ? transparent : Theme.surface-main;
|
||||
|
||||
// ── REACTIVE RELOAD (§A.3) ──────────────────────────────────────────────
|
||||
// Fire a fresh load whenever the bound album id changes (and on first
|
||||
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
PurchaseTrackGroup,
|
||||
PurchaseFormatItem,
|
||||
UiFocusState,
|
||||
ShellState,
|
||||
} from "../state.slint";
|
||||
|
||||
// ── A toolbar dropdown button (group / sort) — the favorites toolbar look ──
|
||||
@@ -1306,7 +1307,7 @@ export component PurchasesView inherits Rectangle {
|
||||
callback open-artist(string);
|
||||
callback media-action(string, string, string);
|
||||
|
||||
background: Theme.surface-main;
|
||||
background: ShellState.app-background-active ? transparent : Theme.surface-main;
|
||||
|
||||
// Outside-press dismissal for any open menu (§2.1.16): a full-area
|
||||
// TouchArea behind the content that closes `open-menu` on a press that
|
||||
|
||||
@@ -27,7 +27,7 @@ import { Theme } from "../foundation/semantic-colors.slint";
|
||||
import { Radius } from "../foundation/radius.slint";
|
||||
import { Layout } from "../foundation/layout.slint";
|
||||
import { Typography } from "../foundation/typography.slint";
|
||||
import { SearchState, SearchActions, CortinillaRow, CortinillaSection, ShellState } from "../state.slint";
|
||||
import { SearchState, SearchActions, CortinillaRow, CortinillaSection, ShellState, AppearanceState } from "../state.slint";
|
||||
import { ListScrollbar } from "../primitives/ListScrollbar.slint";
|
||||
|
||||
// A single SlimCard-style result row inside the cortinilla — 40x40 thumbnail
|
||||
@@ -307,7 +307,9 @@ export component Cortinilla inherits Rectangle {
|
||||
hover-ta := TouchArea {
|
||||
changed has-hover => { root.panel-hovered = self.has-hover; }
|
||||
panel-box := Rectangle {
|
||||
background: Theme.surface-main;
|
||||
background: ShellState.app-background-active
|
||||
? Theme.surface-main.with-alpha(AppearanceState.app-background-surface-alpha)
|
||||
: Theme.surface-main;
|
||||
border-radius: Radius.sm;
|
||||
border-width: 1px;
|
||||
border-color: Theme.border-muted;
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
import { Theme } from "../foundation/semantic-colors.slint";
|
||||
import { Typography } from "../foundation/typography.slint";
|
||||
import { Radius } from "../foundation/radius.slint";
|
||||
import { BlacklistState, BlacklistActions, UiFocusState } from "../state.slint";
|
||||
import { BlacklistState, BlacklistActions, UiFocusState, ShellState } from "../state.slint";
|
||||
import { QbzIcon } from "../primitives/QbzIcon.slint";
|
||||
import { ListScrollbar } from "../primitives/ListScrollbar.slint";
|
||||
import { LoadingSpinner } from "../primitives/LoadingSpinner.slint";
|
||||
@@ -246,7 +246,7 @@ component AlbumRow inherits Rectangle {
|
||||
}
|
||||
|
||||
export component BlacklistManagerView inherits Rectangle {
|
||||
background: Theme.surface-main;
|
||||
background: ShellState.app-background-active ? transparent : Theme.surface-main;
|
||||
|
||||
// Local modal flag (Clear-All confirmation). Lives in the view; the
|
||||
// confirm only fires BlacklistActions.clear-all on the danger button.
|
||||
|
||||
@@ -91,27 +91,29 @@ fn fs_main(in: VsOut) -> @location(0) vec4<f32> {
|
||||
var uv = in.uv;
|
||||
uv.x = uv.x * aspect;
|
||||
|
||||
// Slow clock. Long periods → a background that morphs over ~20-40s, never
|
||||
// strobes. `level_smooth` adds a barely-there breathe (kept small on purpose).
|
||||
let t = u.time * 0.04;
|
||||
let breathe = 1.0 + 0.06 * u.level_smooth;
|
||||
// Clock. FAST enough that the flow is clearly visible in seconds (blob
|
||||
// orbits are ~10-18s) — a subtle drift reads as "not moving". `level_smooth`
|
||||
// adds a gentle breathe on top when audio is flowing.
|
||||
let t = u.time * 0.5;
|
||||
let breathe = 1.0 + 0.10 * u.level_smooth;
|
||||
|
||||
// Gentle domain warp so the blobs don't move on rigid circles.
|
||||
// Stronger domain warp so the blobs flow like fluid, not on rigid circles.
|
||||
let warp = vec2<f32>(
|
||||
fbm(uv * 1.6 + vec2<f32>(t, 0.0)),
|
||||
fbm(uv * 1.6 + vec2<f32>(0.0, t * 0.9)),
|
||||
fbm(uv * 1.8 + vec2<f32>(t * 0.6, t * 0.2)),
|
||||
fbm(uv * 1.8 + vec2<f32>(-t * 0.25, t * 0.55)),
|
||||
);
|
||||
let p = uv + (warp - 0.5) * 0.35;
|
||||
let p = uv + (warp - 0.5) * 0.55;
|
||||
|
||||
// Three album-colored blobs drifting on long-period sinusoids.
|
||||
let cA = vec2<f32>(0.30 * aspect + 0.22 * aspect * sin(t * 0.7),
|
||||
0.35 + 0.20 * cos(t * 0.53));
|
||||
let cB = vec2<f32>(0.72 * aspect + 0.20 * aspect * sin(t * 0.6 + 2.1),
|
||||
0.62 + 0.22 * cos(t * 0.47 + 1.3));
|
||||
let cC = vec2<f32>(0.52 * aspect + 0.24 * aspect * cos(t * 0.5 + 4.0),
|
||||
0.28 + 0.18 * sin(t * 0.63 + 3.2));
|
||||
// Three album-colored blobs sweeping across most of the screen (big travel
|
||||
// so the motion is obvious), each on its own period so they never lock.
|
||||
let cA = vec2<f32>((0.35 + 0.34 * sin(t * 0.41)) * aspect,
|
||||
0.42 + 0.30 * cos(t * 0.33));
|
||||
let cB = vec2<f32>((0.66 + 0.32 * sin(t * 0.37 + 2.1)) * aspect,
|
||||
0.58 + 0.34 * cos(t * 0.29 + 1.3));
|
||||
let cC = vec2<f32>((0.50 + 0.36 * cos(t * 0.31 + 4.0)) * aspect,
|
||||
0.34 + 0.30 * sin(t * 0.44 + 3.2));
|
||||
|
||||
let r = 0.55 * breathe;
|
||||
let r = 0.62 * breathe;
|
||||
let wA = blob(p, cA, r);
|
||||
let wB = blob(p, cB, r * 0.92);
|
||||
let wC = blob(p, cC, r * 0.85);
|
||||
@@ -119,15 +121,20 @@ fn fs_main(in: VsOut) -> @location(0) vec4<f32> {
|
||||
|
||||
var col = (u.primary.rgb * wA + u.secondary.rgb * wB + u.accent.rgb * wC) / wSum;
|
||||
|
||||
// Vertical falloff → a touch darker at the very top/bottom edges, so chrome
|
||||
// Push saturation/contrast a touch so the album hues read as a living
|
||||
// gradient rather than a muddy average.
|
||||
let luma = dot(col, vec3<f32>(0.299, 0.587, 0.114));
|
||||
col = mix(vec3<f32>(luma), col, 1.25);
|
||||
|
||||
// Vertical falloff → a touch darker at the very top/bottom edges so chrome
|
||||
// (titlebar, player bar) sits on calmer color. Kept subtle.
|
||||
let vshade = 1.0 - 0.18 * pow(abs(in.uv.y - 0.5) * 2.0, 2.0);
|
||||
let vshade = 1.0 - 0.16 * pow(abs(in.uv.y - 0.5) * 2.0, 2.0);
|
||||
col = col * vshade;
|
||||
|
||||
// Overall brightness pull-down: this is a BACKGROUND. The Slint scrim adds
|
||||
// the real legibility dim; this just keeps the base from ever glaring on a
|
||||
// white-heavy album palette.
|
||||
col = col * 0.62;
|
||||
// Overall brightness: brighter than before — the content area now shows the
|
||||
// full background, and the Slint scrim (QBZ_BG_DIM) provides the legibility
|
||||
// dim, so the base can stay vivid without glaring.
|
||||
col = clamp(col, vec3<f32>(0.0), vec3<f32>(1.0)) * 0.82;
|
||||
|
||||
// A whisper of grain to avoid banding on the smooth gradient.
|
||||
let grain = (vnoise(in.uv * u.resolution * 0.5) - 0.5) * 0.015;
|
||||
|
||||
@@ -325,8 +325,12 @@ export component AppShell inherits Rectangle {
|
||||
- (ShellState.npb-mode == 2 ? Layout.header-height : Layout.player-bar-height)
|
||||
- 8px;
|
||||
vertical-stretch: 1;
|
||||
// Fully transparent when the background is active so the
|
||||
// dynamic background shows through the content area (the
|
||||
// views inside also go transparent); the root scrim keeps
|
||||
// text legible. Opaque theme surface otherwise.
|
||||
background: ShellState.app-background-active
|
||||
? Theme.surface-main.with-alpha(AppearanceState.app-background-surface-alpha)
|
||||
? transparent
|
||||
: Theme.surface-main;
|
||||
border-radius: Radius.md;
|
||||
clip: true;
|
||||
|
||||
@@ -716,7 +716,9 @@ export component HeaderBar inherits Rectangle {
|
||||
border-radius: 6px;
|
||||
border-width: 1px;
|
||||
border-color: Theme.border-subtle;
|
||||
background: Theme.surface-elevated;
|
||||
background: ShellState.app-background-active
|
||||
? Theme.surface-elevated.with-alpha(AppearanceState.app-background-surface-alpha)
|
||||
: Theme.surface-elevated;
|
||||
|
||||
// Magnifier — absolutely positioned on the left so it does NOT take
|
||||
// layout space; the text/placeholder center against the full input
|
||||
|
||||
@@ -12,7 +12,7 @@ import { Typography } from "../foundation/typography.slint";
|
||||
import { QbzIcon } from "../primitives/QbzIcon.slint";
|
||||
import { QualityBadgeFull } from "../primitives/QualityBadgeFull.slint";
|
||||
import { LoadingSpinner } from "../primitives/LoadingSpinner.slint";
|
||||
import { NowPlayingState, SettingsState, TooltipState, ArtPreviewState } from "../state.slint";
|
||||
import { NowPlayingState, SettingsState, TooltipState, ArtPreviewState, ShellState } from "../state.slint";
|
||||
|
||||
// Clickable artist/album link. Elides and shares the row width through a
|
||||
// stretch factor (the artist gets the larger share) so neither can be pushed
|
||||
@@ -184,7 +184,11 @@ export component SongCard inherits Rectangle {
|
||||
- (root.has-stamp ? root.stamp-w + 4px : 0px)
|
||||
- (root.show-art ? root.art-size + root.art-text-gap : 0px));
|
||||
|
||||
background: root.glass ? Theme.surface-elevated : transparent;
|
||||
// Transparent when the app-wide background is active so the card blends into
|
||||
// the (already translucent) player bar instead of showing an opaque slab.
|
||||
background: ShellState.app-background-active
|
||||
? transparent
|
||||
: (root.glass ? Theme.surface-elevated : transparent);
|
||||
border-radius: root.glass ? 8px : 0px;
|
||||
// No border — keeps the album art flush with the card (Tauri parity).
|
||||
drop-shadow-blur: root.glass ? 8px : 0px;
|
||||
|
||||
@@ -3252,8 +3252,8 @@ export global AppearanceState {
|
||||
// session without recompiling, then baked to constants. `dim` = extra dark
|
||||
// scrim over the background for legibility; `surface-alpha` = translucency
|
||||
// of the shell chrome when the background is active.
|
||||
in-out property <float> app-background-dim: 0.28;
|
||||
in-out property <float> app-background-surface-alpha: 0.55;
|
||||
in-out property <float> app-background-dim: 0.35;
|
||||
in-out property <float> app-background-surface-alpha: 0.5;
|
||||
|
||||
// Callbacks. Unwired in this replica — the Rust side may bind them
|
||||
// later. Kept generic (key + value) so the controller can dispatch.
|
||||
|
||||
Reference in new issue
Block a user