island: an idle pill while no player is open
the island is always there now: with no player it shows a pill with a drawn music note and 'Nothing playing', in the cover gradient with the pink glow. click-through, static (draws once). checked on all 4 monitors
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
A Dynamic-Island-style media widget for Amane (Rust Wayland shell library), running on Hyprland. It sits as a small pill at the top centre of the screen and opens into a now-playing card.
|
||||
|
||||
- **Pill:** cover thumbnail, title, 7 live bars from the shown player's own sound (lows left, highs right, growing up and down from the middle), or a pause sign.
|
||||
- **Pill:** cover thumbnail, title, 7 live bars from the shown player's own sound (lows left, highs right, growing up and down from the middle), or a pause sign. With no player open, an idle pill: a music note and "Nothing playing".
|
||||
- **Card:** a still CD of the cover ringed by 40 cava "candles", title and artist, a seekable time bar, previous / play-pause / next.
|
||||
- **Player switcher** ("VIA …" chip): every MPRIS player; picking one pins it, otherwise the island follows whichever plays.
|
||||
- **Output switcher:** moves only the shown player's audio to another device.
|
||||
|
||||
+35
-9
@@ -4,7 +4,7 @@ use std::thread;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use amane::{
|
||||
Animation, Arc, Argument, Blend, Bus, Canvas, Cap, Center, Color, Column, Easing, End, Full, Gradient,
|
||||
Animation, Arc, Argument, Blend, Bus, Canvas, Cap, Center, Circle, Color, Column, Easing, End, Full, Gradient,
|
||||
Image, InputArea, Layer, LayerWindow, Line, Media, MediaPlayer, Monitor, Padding, Palette, Parent, Path,
|
||||
Pointer, Rectangle, Row, Scroll, ScrollArea, Service, Shadow, Shape, SpaceBetween, Stack,
|
||||
Start, Text, Vertical, Weight, Widget, Workspaces, Zone, children, shapes,
|
||||
@@ -267,15 +267,21 @@ pub fn view(monitor: &Monitor) -> LayerWindow {
|
||||
.space(Zone::Ignore)
|
||||
.namespace("magic-island");
|
||||
|
||||
/*
|
||||
* no player: an empty window that lets every click through, never visible(false).
|
||||
* hyprland 0.56 configures a layer surface before its first commit, so a window
|
||||
* that starts hidden gets a size anyway: amane then logs "no child to draw" and,
|
||||
* with nothing ever drawn, waits for frame callbacks that never come, and the
|
||||
* island never showed up once a player started
|
||||
*/
|
||||
let Some(player) = shown(&media, island.selected.as_deref()) else {
|
||||
return window.click_through().child(Rectangle::new().width(0.0).height(0.0));
|
||||
/*
|
||||
* nothing playing: a quiet pill, so the island is always there. never
|
||||
* visible(false): hyprland 0.56 configures a layer surface before its first
|
||||
* commit, so a window that starts hidden gets a size anyway, amane logs "no
|
||||
* child to draw" and waits for frame callbacks an undrawn surface never gets
|
||||
*/
|
||||
return window.click_through().child(
|
||||
Rectangle::new()
|
||||
.width(Parent)
|
||||
.height(Parent)
|
||||
.padding(Padding { top: TOP_GAP, right: 0.0, bottom: 0.0, left: 0.0 })
|
||||
.align_child(Center, Start)
|
||||
.child(idle(&backdrop_colors(&palette))),
|
||||
);
|
||||
};
|
||||
|
||||
let (grow, pill, reveal) = phases(if opened_here { island.open.value() } else { 0.0 });
|
||||
@@ -589,6 +595,19 @@ pub fn faded(color: Color, alpha: u8) -> Color {
|
||||
Color::rgba(color.red(), color.green(), color.blue(), alpha)
|
||||
}
|
||||
|
||||
// the island while no player is open: a music note and "Nothing playing", glowing like the pill
|
||||
fn idle(colors: &[Color; 3]) -> Rectangle {
|
||||
Rectangle::new()
|
||||
.width(COMPACT_W)
|
||||
.height(COMPACT_H)
|
||||
.radius(Full)
|
||||
.fill(backdrop(colors, 255))
|
||||
.border(1.0, EDGE)
|
||||
.shadow(Shadow::drop(PINK).opacity(0.3).blur(22.0))
|
||||
.align_child(Center, Center)
|
||||
.child(Row::new(children![icon(Glyph::Note, 15.0, PINK), Text::new("Nothing playing").size(12.0).color(DIM)]).gap(8.0).align(Center))
|
||||
}
|
||||
|
||||
// the pill: cover, title, the player's live levels
|
||||
fn compact(player: &MediaPlayer, playing: bool, art: &str, levels: &[f32]) -> Rectangle {
|
||||
Rectangle::new()
|
||||
@@ -1405,6 +1424,7 @@ enum Glyph {
|
||||
Muted,
|
||||
Bluetooth,
|
||||
Chevron,
|
||||
Note,
|
||||
}
|
||||
|
||||
// drawn, not typed, so the island looks the same whatever fonts are installed
|
||||
@@ -1473,6 +1493,12 @@ fn bold_icon(glyph: Glyph, size: f32, color: Color, weight: f32) -> Canvas {
|
||||
Glyph::Chevron => shapes![
|
||||
Path::new().move_to(0.12 * s, 0.32 * s).line_to(0.5 * s, 0.7 * s).line_to(0.88 * s, 0.32 * s).stroke(1.5, color).cap(Cap::Round)
|
||||
],
|
||||
// an eighth note: round head, stem, a curved flag
|
||||
Glyph::Note => shapes![
|
||||
Circle::new().center(0.32 * s, 0.74 * s).radius(0.17 * s).fill(color),
|
||||
Line::new().from(0.47 * s, 0.74 * s).to(0.47 * s, 0.12 * s).stroke(thin, color).cap(Cap::Round),
|
||||
Path::new().move_to(0.47 * s, 0.12 * s).quad_to(0.62 * s, 0.3 * s, 0.84 * s, 0.38 * s).stroke(thin, color).cap(Cap::Round),
|
||||
],
|
||||
};
|
||||
|
||||
Canvas::new().width(size).height(size).shapes(shapes)
|
||||
|
||||
Reference in New Issue
Block a user