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"
* [Client] Show live connection latency in the status bar
Add a permanent status-bar label fed by ConnectionController's
pingStatsUpdated: shows the latest round-trip time, hides while
disconnected or without samples, and carries a tooltip with
Last/Median/95th percentile/Maximum over the rolling sample window
(mirrored into the accessible description). The server tab gets the
same stats as its tooltip.
Took 2 minutes
Took 2 minutes
Took 1 minute
Took 48 seconds
Took 25 seconds
Took 4 minutes
* [Client] Graph connection latency history in the status bar
Add LatencyGraphWidget, a size-agnostic bar sparkline over the rolling
sample window: heights scale to the window's own range while colors map
onto an absolute quality ramp, so a steady good ping stays green. Embed
it in the new LatencyStatusWidget together with the textual ping
readout and feed both through ConnectionController's forwarded signals;
the whole area hides while disconnected or without samples.
Took 9 minutes
Took 14 seconds
* [Client] Show latency details when clicking the ping display
Clicking the status bar ping area opens a popup with a larger instance
of the latency graph plus the numeric statistics, selectable and
mirrored into the accessible name. Qt::Popup closes it on any outside
click; contents refresh live while open.
Took 33 seconds
* Fixup from core commit
Took 6 minutes
Took 5 seconds
Took 5 minutes
* Lint.
Took 12 minutes
* Consolidate.
Took 6 minutes
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* [Server/Client/Protocol] Reporting users + moderation queue functionality
Took 6 minutes
Took 3 minutes
Took 8 seconds
Took 11 minutes
Took 12 minutes
Took 7 minutes
Took 15 seconds
Took 2 minutes
Took 1 minute
Took 30 seconds
Took 16 seconds
* CI Fix
Took 6 minutes
* CI Fix
Took 6 minutes
* [Protocol] Add moderation investigation commands
Adds the protocol layer for the moderation investigation suite:
- Command_GetUserSessions/GetUserAlts/GetModeratorLastLogins/ResetUserPassword/RemoveUserAvatar (1013-1017)
- Response extensions 1215-1219 with ServerInfo messages for sessions, alts, and staff logins
- last_login on Response_ReportUserInfo and warning_il on Response_WarnList
Took 2 minutes
* [Utility] Add warning categories parser with infraction levels
Parses the server's 'officialwarnings' setting (comma-separated, optional
'|IL' suffix) into WarningCategory structs so the client can display the
infraction level of each warning category. Includes GTest coverage.
* [Server] Add moderation investigation tools
Implements the server side of the moderation suite:
- getUserSessions/getUserAlts/getModeratorLastLogins/removeUserAvatar DB methods
- Handlers for all five new commands with audit records (PASSWORD_RESET,
REMOVE_USER_AVATAR); password resets return a generated temporary password
- cmdGetWarnList now reports per-category infraction levels from the
officialwarnings setting; cmdReportUserInfo reports last_login
- Update servatrice.ini.example with the warning taxonomy
- Password/avatar mutations report RespNameNotFound when the user does not exist
* [Client] Add moderation tab with investigate, password reset, and avatar removal
- New Moderation tab: search a user to show account info, alternate
accounts, login sessions, and staff last logins; actions to reset the
user's password (shows the generated temporary password) and remove the
user's avatar
- 'Investigate user' entry in the user context menu opens the tab pre-loaded
for that user
- Warning dialog shows the infraction level of each warning category
- Tab wired into TabSupervisor with a moderator-gated menu action, shortcut,
and tabs.ini persistence (default closed)
* [Server/Client/Protocol] Address PR #7091 review: security, bug, and perf fixes
Security:
- Promote RESET_USER_PASSWORD to admin-only dispatch (was moderator-accessible)
- Reject password reset on users with equal/higher privilege than caller
- Notify affected user via Event_NotifyUser::CUSTOM when password is reset
- Add server-side category whitelist for reports
- Drop reporter name fallback in comment/details authorization (ID-only)
- Force password change: new DB column + login enforcement + client disconnect
Bugs:
- XSS via QTextEdit::append() → insertPlainText() in report tab and utils
- allNotified initialized to true even with empty recipients list
- Warning combo box: use currentData() instead of baked-in display text
- Report resolution now records who resolved (resolved_by column + audit)
Performance:
- IP-correlation subquery: add 6-month window + LIMIT 200
- getUserSessions: clamp limit to 500
Non-blocking:
- Palette-aware colors in report_utils.cpp (dark/light mode)
- Report list pagination: offset/limit fields + total_count in response
- SessionCommand enum gap comment for reserved values 1201-1203
Schema: 36→37 (force_password_change), 37→38 (resolved_by)
Took 12 minutes
Took 16 seconds
* Fix macOs pedantry
Took 5 minutes
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* [Client] Send game invites from the user context menu via a private message
The user context menu gains an "Invite to Game" submenu listing the
inviteable games in the room (the inviter's own games, honoring the
buddy-only setting). Picking one opens a private message to the target
user with a cockatrice://joingame link naming the game, so the target
gets a clickable invite instead of a raw URL. Multi-game rooms offer a
picker; a single inviteable game sends directly. Sending a message to
an offline user no longer swallows the draft — it reports that the
user is offline and keeps the typed text.
Took 50 seconds
Took 3 minutes
* [Client] Extract sendPrivateMessage() to fix invite message draft overwrite
sendInviteMessage() was calling sayEdit->setText(text) then sendMessage(),
which overwrites any text the user had typed. Extract the command-building
and sending logic into a new sendPrivateMessage(const QString &text) method
that takes the text directly. sendMessage() now calls it after its guards
and clears sayEdit; sendInviteMessage() calls it directly without touching
the input field at all.
Took 33 minutes
* Rename method, address comments.
Took 5 minutes
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* [Client] Route cockatrice:// link clicks from chat to the intent chain
A cockatrice:// link clicked in chat is currently handed to the OS (or
does nothing in-process). Clicks now emit a cockatriceLinkActivated signal
that travels ChatView -> Tab -> TabSupervisor -> MainWindow, which feeds
the URL through the same IntentUrlParser the OS activation path uses, so
the join runs entirely in-process. card/user schemes and all other links
behave as before.
* [Client] Route cockatrice:// link clicks from the in-game chat to the intent chain
* [Client] Reuse one IntentUrlParser instance for cockatrice:// links
Took 59 seconds
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* [Tabs] Add a setting to define startup tab on application launch.
Took 29 minutes
* Naming and sizing
Took 4 minutes
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* [CI] Remove Qt5
Took 10 minutes
Took 9 minutes
* Revert CI failure and fix up comments
Took 4 minutes
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* [Application] Add single instance guard and mime types.
Took 2 hours 39 minutes
Took 18 minutes
Took 5 minutes
Took 12 seconds
Took 11 seconds
* Rework
Took 30 minutes
Took 50 seconds
* Only enforce single instance if launched with arguments.
Took 5 minutes
* Prototype intents
Took 53 minutes
Took 6 seconds
* Connect/disconnect and join game/room intents.
Took 3 hours 14 minutes
Took 2 seconds
Took 15 seconds
* Fix include.
Took 1 minute
Took 23 seconds
Took 2 seconds
* Mac handling.
Took 10 minutes
Took 12 seconds
Took 3 minutes
* Lint.
Took 3 minutes
* Rebase.
Took 3 minutes
Took 17 seconds
* Implement UrlSchemeEventFilter
Took 10 minutes
Took 7 seconds
* Qt Moc
Took 3 minutes
* Modern PList.
Took 21 minutes
Took 1 minute
* Debug output.
Took 6 minutes
Took 19 minutes
* Watch file:// prefix.
Took 15 minutes
Took 7 seconds
* Better handler.
Took 6 minutes
* Don't store reference in member
Took 5 minutes
* Move impl to cpp, fix lifetime issues.
Took 11 minutes
Took 2 minutes
* Better single-instance handoff, url intent harded
copy game link context-menu
Polish for installers
Took 35 minutes
Took 8 seconds
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* [Room] Additionally show a tab for friends and ignored users instead of just all online users.
Took 21 minutes
Took 12 minutes
* [Room][UserList] Introduce style delegate for user list
- Allow users to set a card name and parameters as their background banner
- Allow mods to white/blacklist cards
- Allow toggling back to the old display style
Took 7 minutes
Took 28 seconds
Took 2 minutes
Took 2 minutes
* Right checkstate.
Took 14 minutes
Took 2 minutes
* Utility for test.
Took 9 minutes
Took 8 seconds
Took 2 seconds
* Lint.
Took 10 minutes
* Algorithm for sql schema migration
Took 13 minutes
* Use {prefix}, bound card name, return errors.
Took 27 seconds
* Convert queue to while loop.
Took 19 seconds
* Hover popup.
Took 36 minutes
Took 1 minute
* More granular signals, popup for user info.
Took 25 minutes
Took 8 seconds
Took 16 minutes
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* TabArchidekt and Archidekt API integration.
Took 37 seconds
Took 4 minutes
Took 40 seconds
Took 4 minutes
* Lint.
* Lont.
* Search bar, fancier display, resolve providerId
* Delegate click to base.
* Be explicit for pedantic compilers.
* Liiint.
* Leave them default I guess
* Leave them default I guess
* Small fixes.
* New utility display widgets.
* New style for deck listing.
* Lint.
* Lont.
* Scale things.
* Delegate paint to base.
* Use default Archidekt preview image for decks without featured.
* Consistent sizes.
* Increase font size, qt version guard.
* More version guards.
* Clean up filter layout, use mana symbols.
* Set content margins.
* Refresh on filter change.
* Lint.
* Better elision.
* Query actual new endpoints, new query parameters.
* Doxygen, reorder fields in constructor, readability.
* Update page size doc to min size.
* Update initial min deck size value.
* Add label to page selection.
* Okay, so, people upload a lot of 1 card decks frequently.
* Whoops.
* Add a selection combobox for sorting logic.
* Debounce and limit searches.
* Include.
* Lint.
* Don't imply that Archidekt supports multiple cards/commander names.
* Let's not lambda it and slot it instead.
* Overload.
* Add button to home tab.
Took 8 minutes
* Adjust to selection model change.
Took 5 minutes
* Cleanup auto-generated comments.
Took 8 minutes
* Remember card sizes.
Took 1 minute
* Initialize with correct size.
Took 3 minutes
* Use correct placeholders.
Took 2 minutes
* Style lint.
Took 16 minutes
* Parse double-faced cards correctly.
* Parse double-faced cards correctly.
* Allow TabArchidekt to use VDE group/sort/display buttons
* Lint.
* Indicate that things are clickable.
* Min treshold for nicer display.
* Lint.
* We have good labels at home.
* We do a little linting.
* Qt version guards.
* Qt5 is the devil.
* Update comments.
* Lint comments.
* More doxys.
* One more doxy.
* Lint.
* Update.
* Small fixes.
Took 7 minutes
Took 13 seconds
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* [Cleanup] Unused #includes
Took 44 minutes
* [Cleanup] More unused #includes
Took 55 minutes
* [Cleanup] Include QSet
Took 4 minutes
* [Cleanup] Include QDebug in deck_list.cpp
Took 3 minutes
* [Cleanup] Include protocol stuff in servatrice_database_interface.h
Took 3 minutes
* [Cleanup] Include QDialogButtonBox
Took 8 minutes
* [Cleanup] Include QUrl
Took 8 minutes
* [Cleanup] Include QTextOption in header.
Took 3 minutes
* [Cleanup] Include QMap in user_list_manager.h
Took 8 minutes
* [Cleanup] Adjust qjson
Took 8 minutes
* [Cleanup] include button box.
Took 3 minutes
* [Cleanup] Redo fwd declarations.
* [Cleanup] Redo last removed fwd declarations.
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* Fix local variable double declaration.
Took 44 seconds
* Mark functions as [[nodiscard]]
Took 31 minutes
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* A DeckLoader is not a DeckList.
Took 2 hours 39 minutes
* Explicitly initialize base class in copy constructor?
Took 3 minutes
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* Deck loader is a gui class.
Took 31 minutes
Took 3 minutes
* Deck Loader is responsible for printing.
Took 8 minutes
Took 2 seconds
* Style proxy.
Took 14 minutes
Took 6 minutes
Took 1 minute
* Don't need to include QBrush anymore.
Took 3 minutes
Took 7 seconds
* Includes for printer.
Took 5 minutes
* Nuke getDeckList()
Took 9 minutes
* Adjust to rebase.
Took 35 seconds
* Lint.
Took 3 minutes
* Braces for one line return statements.
Took 13 minutes
Took 50 seconds
* Enum for model columns.
Took 9 minutes
* One more single line if.
Took 1 minute
* Another style lint on a sunday night
Took 5 minutes
* Move enum to namespace.
Took 3 minutes
* Fix a critical blocker.
Took 5 minutes
* Update docs.
Took 3 minutes
* Doxygen and namespace enums.
Took 2 minutes
Took 15 seconds
* Adjust to namespace.
Took 4 minutes
Took 1 minute
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* Move models to own library.
Took 35 minutes
Took 22 minutes
* Adjust CMakeLists
Took 20 seconds
* Reformat CMakeLists.
Took 2 minutes
* Revert "Reformat CMakeLists."
This reverts commit db5982ad1c.
Took 55 seconds
* Lint an include
Took 17 minutes
Took 9 seconds
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>