Skip to content

feat: redesign settings, typography and the music page - #246

Merged
FoOcean merged 5 commits into
masterfrom
feat/ui-refresh
Oct 18, 2026
Merged

FoOcean merged 5 commits into
masterfrom
feat/ui-refresh

Conversation

@FoOcean

@FoOcean FoOcean commented Oct 18, 2026

Copy link
Copy Markdown
Collaborator

Pre-submission checklist

  • I have read CONTRIBUTING.md and completed the required checks
  • Local and CI checks pass
  • I have completed a self-review
  • I confirm that I haven't read the checkboxes and just ticked them all

Change type (select one)

  • feat New feature
  • fix Bug fix
  • docs Documentation or templates
  • style Formatting with no behavior change
  • refactor Code change that neither fixes a bug nor adds a feature
  • perf Performance improvement
  • test Test-related change
  • chore Build, CI, dependency, or tooling change
  • revert Revert
  • security Security fix

Scope (select all that apply)

  • Application core
  • UI style or layout
  • Application behavior
  • Dependency changes
  • Plugin API
  • CI/CD configuration
  • Documentation
  • Other (describe below)

Other: platform API additions: AudioProvider::output_devices / set_default_output, and WindowSystem::update_window_backdrop / set_text_input for the settings window. Dependency changes are new windows crate features only (Win32_Devices_FunctionDiscovery, Win32_System_Com_StructuredStorage, Win32_UI_Shell_PropertiesSystem).

Related issues

  • Refs: user feedback batch (no tracked issue)

Description

Summary

Redesigns the settings window, rebalances typography with real font weights and richer font options, restyles the music page with output-device and volume controls, adds the timer status orb, and fixes the spectrum stalling after an output device switch.

Motivation and context

  • Settings: the options were grouped by implementation rather than by what users look for, and the window style did not match the rest of the app.
  • Typography: text only had regular and bold (700). Microsoft YaHei has no medium or semibold, so every emphasized string jumped to full bold and some places read too heavy while small labels read too light. In addition, the CJK fallback passed zh-CN first, but Skia uses the last language tag, so Chinese text fell back to Yu Gothic and Microsoft JhengHei and mixed three fonts on one line.
  • Fonts: a custom font could only be a single file, with no weight control.
  • Music page: brought in line with the iOS expanded player, with requests to switch the output device and adjust volume from the island.
  • Timer: a running timer competed with music and widgets for compact space.
  • Spectrum: switching the output device while music played left the spectrum frozen.

Changes

Commits are self-contained and build in order.

  • fix(audio): the meter thread reset and re-found the target PID within one loop iteration, so the loopback reader never noticed a device change and kept reading a stream that stops delivering. Device changes now bump an epoch that reopens the capture; a watchdog reopens it when the player is audible but no packets arrive for 2 s; the audio workers run on dedicated threads so cpal's COM apartment no longer collides with MTA workers on reused tokio blocking threads (the logs showed RPC_E_CHANGED_MODE).
  • feat(audio): output_devices() lists active render endpoints with friendly name and form factor; set_default_output() switches via IPolicyConfig for all roles. AudioOutputs runs both on a worker thread.
  • feat(settings):
    • Window: opaque base with a floating glass sidebar (host backdrop), concentric continuous corners, traffic lights with an inactive maximize button, back/forward capsule, and a sidebar search over page titles and item labels (IME aware).
    • Pages: General is split into General, Appearance, Size & Position, Hide & Interaction, and Notifications & Alerts. Sidebar and onboarding icons are recolored, and four new sidebar icons come from the iOS icon set.
    • Controls: larger capsule switches, flat push buttons, popup selects, and a popup menu that scrolls, with a draggable gutter scrollbar, type-ahead, arrow keys, Enter and Esc.
    • Typography: text APIs take a FontWeight instead of bool. Latin uses the Segoe UI Variable wght axis, variable fonts use their own axis, and CJK weights the family lacks are synthesized with a size-calibrated stroke. Titles, buttons and numerals use semibold, labels and lyrics medium, body text regular.
    • Fonts: the font menu offers the system default, a font file (ttf/otf/ttc/otc) and every installed family. Regional families such as PingFang UI SC/TC/HK/MO/JA fold into one entry that follows the interface language (Windows locale for non-Chinese UIs). A weight offset is added, along with a recommended-font link.
  • feat(music):
    • Layout: five evenly spaced controls, gray side icons, a brighter progress track and gray secondary text.
    • Left button: shows the current output device and opens a device list that switches the default output. It scrolls to the current device, and its scrollbar sits in its own gutter and can be dragged.
    • Right button: follows the volume level with a crossfade between glyphs and opens a volume slider that also takes the mouse wheel.
  • feat(island): while music or widgets occupy the compact island, a running timer moves into a status orb beside it, sharing the camera and microphone indicator behavior.

Configuration

New keys font_family (optional, unset by default) and font_weight (light / regular / bold, default regular). Both fall back to serde defaults, so existing configs load unchanged. custom_font_path keeps its meaning and takes precedence over font_family.

Testing

  • cargo fmt --all -- --check, cargo clippy --workspace -- -D warnings, cargo build --release pass; each commit also passes cargo check.
  • Rendered in a WINISLAND_HOME sandbox: all settings pages in light and dark, the font menu, island scenes with the system font, a single-weight PingFang file and the PingFang UI variable family, and the music page with both panels.
  • To verify manually:
    1. Settings → Appearance → Font: pick PingFang UI (if installed) or any family and check weights across the island and settings.
    2. Expand the island on the music page and click the left icon; pick another output and confirm Windows switches to it.
    3. Click the right icon and drag the slider or scroll over it; the icon should change between 1, 2 and 3 waves and mute.
    4. While music plays, switch the output device from Windows and confirm the spectrum keeps moving.
  • Not verified here: steps 2 and 4 need a real device switch, which was left to manual testing.

UI changes

  • Settings: macOS-style window. The translucent sidebar floats above an opaque base, with search, grouped pages and a navigation capsule.
  • Typography: lighter overall hierarchy. Chinese renders in a single font, and medium and semibold now look different from bold.
  • Music page: matches the iOS layout. The device list fades in over the cover area while the playback controls stay visible. The volume slider crossfades in place of the progress bar and closes after 3 s idle.
  • Timer orb: pops out at half of the collapse animation and settles together with the island.

🤖 Generated with Claude Code

FoOcean and others added 5 commits October 18, 2026 03:44
The meter thread reset and re-found the target process within one loop
iteration, so the loopback reader never saw the change and kept reading a
stream that stops delivering after a device switch, leaving the spectrum
flat. Device changes now bump an epoch that reopens the capture, a stall
watchdog reopens it when the player is audible but no packets arrive, and
the audio workers run on dedicated threads so cpal's COM apartment no
longer collides with the MTA workers on reused blocking threads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds `AudioProvider::output_devices` and `set_default_output`. Devices
carry their friendly name and form factor; switching uses the
IPolicyConfig interface for every role. `AudioOutputs` runs both calls on
a worker thread so the UI thread never blocks on COM.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Settings:
- macOS-style window with an opaque base, a floating glass sidebar,
  concentric continuous corners, traffic lights with an inactive maximize
  button, a back/forward capsule and sidebar search across pages and items.
- General settings split into General, Appearance, Size & Position,
  Hide & Interaction and Notifications & Alerts, with recolored sidebar and
  onboarding icons.
- Larger capsule switches, flat push buttons, and a scrollable popup menu
  with a draggable gutter scrollbar, type-ahead, arrow keys, Enter and Esc.

Typography:
- Text APIs take a FontWeight instead of a bold flag. Latin text uses the
  Segoe UI Variable weight axis, variable fonts use their wght axis, and
  missing CJK weights are synthesized with a calibrated stroke.
- The fallback locale is now the last BCP 47 tag Skia reads, so Chinese no
  longer falls back to Yu Gothic and Microsoft JhengHei.
- Titles, buttons and numerals use semibold, labels and lyrics medium and
  body text regular; tiny widget values and notification details grow.

Fonts:
- The font menu lists the system default, a font file and installed
  families; regional variants such as PingFang UI SC/TC fold into one entry
  that follows the interface language. Adds a weight offset and a
  recommended PingFang UI link.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The expanded player follows the iOS layout: five evenly spaced controls,
gray side icons, a brighter progress track and gray secondary text.

The left button shows the current output device and opens a device list
that switches the default output; its scrollbar sits in its own gutter and
can be dragged. The right button reflects the volume level, crossfades
between levels and opens a volume slider that also responds to the mouse
wheel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When music, a plugin activity or compact widgets already occupy the
island, a running timer moves into the multitask orb on the right and
shows only its progress ring; clicking the orb opens the timer page. On
its own, the timer keeps the regular icon and countdown.

The orb now carries camera, microphone and timer together. When a
device indicator and the timer are both active, the orb widens into a
short pill over 420 ms with the timer on the left and the dots on the
right.

Orb motion is quicker overall. After the island collapses from the
expanded state, the orb starts separating once the collapse is halfway
and settles together with the island instead of waiting for the springs
to come to rest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@FoOcean
FoOcean merged commit ebf6760 into master Oct 18, 2026
3 checks passed
@github-project-automation github-project-automation Bot moved this from Needs Review to Merge in Winisland Pull Requests Oct 18, 2026
@FoOcean FoOcean mentioned this pull request Oct 19, 2026
5 of 22 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

1 participant