The remote public decks model verbatim-copied updateColorMatches' switch,
down to the ExactMatch normalization and the fact that Includes/Excludes do
not normalize case. Extract colorIdentityMatches() next to the FilterMode
enum and call it from both so the subtle rule cannot drift.
retranslateUi unconditionally rewrote the empty label to the 'nothing
published' variant, stomping the 'no decks match your filters' choice
rebuildGrid had made, and a visible loading message stayed in the old
language. Let retranslateUi pick the same variant rebuildGrid does and
re-show the status so it retranslates.
retranslateUi was never called from the constructor, so the tooltips set
there were absent until a language change. Call it before the first refresh,
and give the icon-only refresh button an accessible name for screen readers.
The column reported the effective state while publishing toggles the node's
own bit, so a private deck inside a public folder already read 'Public' and
toggling appeared to do nothing (and toggling again silently unpublished
it). The cell now shows 'Public (inherited)' for that case and the tooltip
explains why.
Deck names and usernames come from other users' records and Qt renders
QLabel tooltips as AutoText, so a name like '<h1><table>...' parsed as
markup. Escape and bound the deck-name tooltip and escape the username
interpolated into the title label.
loading only cleared in decksReceived, but the ping sweep can drop a pending
command without ever emitting finished, leaving the tab stuck on 'Loading
public decks...' and the refresh button permanently inert. A single-shot
timer started per refresh clears the latch and reports a timeout; the latch
also clears when the client disconnects.
Each rejected node stacked its own modal dialog, so publishing a ten-deck
selection against a rejecting server made the user dismiss ten dialogs one
at a time. Failures are now collected while the batch is in flight and shown
as a single summary when the visibility refresh timer fires; a reply that
lands outside an active batch still reports right away.
A dropped visibility reply used to leave the pendingVisibilityChanges
counter permanently positive, so the Public/Private column never refreshed
again and nothing reset it on disconnect. A restartable single-shot timer
with a boolean guard re-reads the tree whenever publishes quiet down and is
stopped on disconnect, so a lost reply costs one stale refresh instead of
killing the column for the session.
The server now derives the banner card and tags from the uploaded deck
list itself, so Command_DeckUpload only carries the client-computed color
identity. Drop the reserved banner/tag setters from the editor and storage
uploads, send the color identity on remote saves, and read tags from the
now-repeated ServerInfo_DeckStorage_TreeItem field.
Add a public-decks tab that lists decks published by other users using the
server's deck visibility feature, previewing each deck's banner card, color
identity, tags and upload time without downloading the deck list until the
user opens it.
- Add a public-decks tab with a shared-settings widget and a remote model
that fetches the target user's decks and refreshes both automatically and
on user request, with a loading indicator and a server-error message
instead of a blank tab when the fetch fails or the connection drops
- Render each deck as a focusable preview tile whose banner, color identity,
tags and upload time follow the existing Preview settings, with the deck
name announced as the tile's accessible name and Space/Enter opening the
deck, mirroring the shared-deck preview tile
- Show a message box when opening a public deck fails or arrives corrupted
- Publish and unpublish decks from the server storage toolbar and context
menu, toggling the deck's own visibility bit (what the server persists)
rather than the inherited effective state, and batch the visibility
refresh until the last in-flight change is acknowledged
- Add the Show Upload Time setting so the tile's upload stamp can be hidden
like the other preview details
- Update the retranslateUi wiring for the new public-decks tab and rename
the share action tooltip from "Deck share" to "Share link"
QTimeZone::UTC (the Initialization enum) only exists since Qt 6.7, so
Debian 12 and Ubuntu 24.04 (Qt 6.4) fail to compile the share-link expiry
handling in the share dialog and the two deck-storage tabs. Mirror the
existing games_model guard and fall back to Qt::UTC on older Qt.
Gate every share entry point on login, de-duplicate the share-link and
color-identity logic behind DeckShareUtils and an injected querier, and
replace the silent tray/status-bar notices with always-visible dialogs.
- abstract_tab_deck_editor: explain that sharing requires a connection
instead of silently doing nothing when logged out
- tab_deck_storage: disable the share action on disconnect, reject
folder/deck mixes and the root folder with clear warnings, re-enable
Create on every entry/response so a dropped connection cannot leave
the button disabled
- tab_deck_storage_visual: same login gate for the context-menu entry,
visible success/error dialogs, and a symmetric in-flight guard
- getDeckColorIdentity now takes a CardDatabaseQuerier, dropping the
CardDatabaseManager singleton access and enabling unit tests
* [Themes] Add identity default palettes for the image themes
The Fabric, Leather, Plasma and VelvetMarble themes shipped only zone art and no palette, so their chrome fell back to the bare OS palette. Each theme now ships light and dark curated defaults written in the palette editor's own conventions, with [AppColors] so the home-tab buttons keep the theme's identity over static backgrounds.
- Add palette-default-light.toml / palette-default-dark.toml for the four themes; scheme resolution follows the OS since the themes declare no color scheme.
- Tint the window/base/button chrome and bevels towards each theme's identity: navy cloth (Fabric), black-brown with brass accents (Leather), electric violet with cyan sparks (Plasma), charcoal velvet with slate marble (VelvetMarble).
- Fill [AppColors] AccentStrong / AccentSoft per theme so the home-tab button gradient matches instead of falling back to the default greens.
- Derive Disabled and Inactive groups with the same conventions as PaletteGenerator::fromAccent.
* [Themes] Add home backgrounds for the image themes
* [Themes] Ship Fusion style + scheme backgrounds for the image themes
Address PR review:
- Add theme.cfg ([Style] Name = Fusion, ColorScheme = System) to Fabric,
Leather, Plasma and VelvetMarble so their curated palettes actually apply.
Without it the native style paints button chrome from the OS (windowsvista
on Windows has no dark mode), making the dark palettes' light ButtonText
unreadable on light buttons.
- Leverage the scheme-variant asset resolution: register home-dark.png and
home-light.png in resources and add them to the qrc so the built-in home
background also flips with the palette instead of staying static.
- Fix Leather [Palette.Inactive] Accent, which copied the Active Highlight
color instead of the theme accent (dark #4a5f8f -> #c9995a, light
#34508c -> #a5712f) in both palette files.
* [Themes] Align light plasma home background with the dark variant
Recolored the Plasma light home background to mirror the dark one:
brighter violet/cyan blooms, vivid azure spark arcs, and higher accent
saturation against the same pale-lavender key. Brightness is unchanged
so it still reads as a light scheme.
* [Home] Add option to disable the home tab background dim
Adds a 'Dim the home tab background' checkbox to the Home tab settings
page (Appearance). When unchecked, HomeWidget skips the translucent
black overlay it paints over the whole background. Default is on,
preserving current behavior; the home tab repaints live on change.
* Update leather backgrounds
* Update velvet marble backgrounds
* Update light plasma background
* Update light fabric background
* WIP [UI] Theme-aware onboarding banner with frosted light mode
Banner colours now derive from palette tokens at ~60fps (tick-driven,
equality-guarded setters) so scheme switches and live accent-picker
previews apply instantly:
- dark stages: byte-for-byte the original treatment (near-black stage
from window hue, Highlight accent, white centre halo, vignette 0.62)
- light stages: pastel accent-hue wash instead of a neutral grey copy,
brightness-lifted accent for additive glow legibility, deep-Highlight
halo (uGlowColor) instead of white blowout, gentler vignette
(uVignetteMin 0.88) so corners don't go muddy
- black logo silhouette variant selected on light stages
- theme picker preseeded with brand green (brand_colors.h single source)
WIP notes for next session:
- real-pixel wizard screenshot check still pending (headless capture
exists: Xvfb :77 + isolated XDG_DATA_HOME; shader vs fallback pixel
analysis not finished)
- user plans separately: promote Fusion to default theme, Default -> system
* [Themes] Align Fusion accent tokens with the SVG brand gradient
Align AccentStrong (#139740) and AccentSoft (#c9fd62) and the linked
Link/Accent roles with cockatrice.svg's linearGradient4265-7-8 stops so the
identity gradient used by the logo emulation matches the static art the icon
shipped.
* [Onboarding] Draw the banner logo as a static gradient plate
Replace the black/white logo tint switch with a ShaderEffect plate that
repaints the SVG's brand gradient (light AccentSoft -> dark AccentStrong
along the baked-in userSpaceOnUse axis) clipped to the full-color logo's
alpha silhouette, with the white highlight path overlaid on top — matching
the home widget's QPainter composite. The plate is static: no glow or
breathing. Brand colors flow from BannerShaderConfig's new brandStrong/
brandSoft pair instead of the removed logoDark flag, and the background
motifs get a touch more accent so the mark keeps its coloured surround.
* [Home] Draw the featured logo as a theme gradient composite
Repaint cockatrice.svg in Qt instead of showing the baked-in static art:
fill the full-color logo's alpha silhouette with the same brand gradient the
banner plate uses (light AccentSoft grading to dark AccentStrong along the
SVG's userSpaceOnUse axis), then overlay the white highlight path. Renders
an explicit QPixmap so the mark stays crisp at the 200px display size, and
re-seeds it on theme/palette/appearance changes so it never goes stale.
* [Resources] Drop the unused black logo asset
No consumer remains after the banner's logoDark toggle was replaced by the
static gradient plate (unit-tested in d7529e0c6a), so remove
cockatrice-logo-black.svg and its qrc entry.
* [Onboarding] Seed the theme picker from the theme's identity accent
Replace the hardcoded brand-green preseed with the shipped theme's own
AccentStrong (Plasma seeds violet, Fusion green), resolved from the default
palette so auto/user-generated palettes can't mask it, and re-seed whenever
the theme changes so the swatch never goes stale. Also consult the shipped
palette in maybeAutoGeneratePalette so scheme flips don't regenerate a fresh
palette over curated theme colors.
* Regenerate zone assets for Fabric, Leather, VelvetMarble themes
Align zone textures with each theme's palette identity:
- Fabric: linen weave in navy/steel tones (was generic green/blue/red/gray)
- Leather: grain texture in warm brown/amber tones
- VelvetMarble: smooth charcoal marble veining (replaces .jpg with .png)
All zones now have dark + light scheme variants for OS color scheme
adaptation. Plasma zones deferred to separate iteration.
* Regenerate Plasma zone assets: horizontal-hand layout, seamless tiling
Bake each zone's phase from its true world position in the horizontal-hand
layout (player 0, stack 172, table 280, hand 172+406) so the diagonal sheen
continues continuously across zone boundaries. All zones share one
mathematically tileable (1,1) diagonal at frequency 3; playerzone gets a
distinct blue-violet identity and the light scheme gets extra contrast.
* Regenerate VelvetMarble zones: classic Perlin marble, seamless tiling
* Regenerate VelvetMarble zones: domain-warped fractal veins, stone grain
* Promote Fusion to default theme, rename Default to System
Fresh installs and new profiles now default to the Fusion (dark) theme
instead of the platform-native theme. The old "Default" theme is
renamed "System" to better describe its purpose — using the OS-native
Qt style (windowsvista, macOS, etc.).
Existing users who had "Default" selected are automatically migrated
to "System" so they keep their platform-native styling. Users with
an empty or invalid theme name now fall back to Fusion.
* Move checkbox.
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>