Skip to content

Commit 90fccb5

Browse files
authored
Merge pull request #539 from levitatingpineapple/responsive-brightness-slider
Brightness Slider
2 parents 71eafb2 + da2fca3 commit 90fccb5

File tree

4 files changed

+101
-159
lines changed

4 files changed

+101
-159
lines changed

src/modules/settings/brightness.rs

Lines changed: 46 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,18 @@ use crate::{
66
brightness::{BrightnessCommand, BrightnessService},
77
},
88
theme::AshellTheme,
9+
utils::remote_value,
910
};
1011
use iced::{
11-
Alignment, Element, Length, Subscription, Task,
12-
futures::stream,
13-
widget::{MouseArea, container, row, slider, text},
12+
Alignment, Element, Subscription, Task,
13+
mouse::ScrollDelta,
14+
widget::{MouseArea, Text, container, row, slider, text},
1415
};
1516

1617
#[derive(Debug, Clone)]
1718
pub enum Message {
1819
Event(ServiceEvent<BrightnessService>),
19-
Change(u32),
20-
MenuOpened,
21-
ResetUserAdjusting,
20+
Changed(remote_value::Message<u32>),
2221
ConfigReloaded(SettingsFormat),
2322
}
2423

@@ -30,96 +29,54 @@ pub enum Action {
3029
pub struct BrightnessSettings {
3130
config: SettingsFormat,
3231
service: Option<BrightnessService>,
33-
ui_percentage: u32,
34-
is_user_adjusting: bool,
35-
reset_timer_active: bool,
3632
}
3733

3834
impl BrightnessSettings {
3935
pub fn new(config: SettingsFormat) -> Self {
4036
Self {
4137
config,
4238
service: None,
43-
ui_percentage: 50,
44-
is_user_adjusting: false,
45-
reset_timer_active: false,
4639
}
4740
}
4841

49-
fn calculate_scroll_brightness(
50-
current_percentage: u32,
51-
max_value: u32,
52-
delta: iced::mouse::ScrollDelta,
53-
) -> Message {
54-
let delta = match delta {
55-
iced::mouse::ScrollDelta::Lines { y, .. } => y,
56-
iced::mouse::ScrollDelta::Pixels { y, .. } => y,
57-
};
58-
// brightness is always changed by one less than expected
59-
let new_percentage = if delta > 0.0 {
60-
(current_percentage + 5 + 1).min(100)
61-
} else {
62-
current_percentage.saturating_sub(5 + 1)
63-
};
64-
let new_brightness = new_percentage * max_value / 100;
65-
Message::Change(new_brightness)
42+
fn on_scroll(current: u32, max: u32) -> impl Fn(ScrollDelta) -> Message {
43+
move |delta| {
44+
let y = match delta {
45+
ScrollDelta::Lines { y, .. } => y,
46+
ScrollDelta::Pixels { y, .. } => y,
47+
};
48+
let step = (5 * max / 100).max(1);
49+
let new = if y > 0.0 {
50+
(current + step).min(max)
51+
} else {
52+
current.saturating_sub(step)
53+
};
54+
Message::Changed(remote_value::Message::RequestAndTimeout(new))
55+
}
6656
}
6757

6858
pub fn update(&mut self, message: Message) -> Action {
6959
match message {
7060
Message::Event(event) => match event {
7161
ServiceEvent::Init(service) => {
72-
self.ui_percentage = service.current * 100 / service.max;
7362
self.service = Some(service);
7463
Action::None
7564
}
7665
ServiceEvent::Update(data) => {
7766
if let Some(service) = self.service.as_mut() {
7867
service.update(data);
79-
// Only update UI if the difference is significant and user isn't actively adjusting
80-
if !self.is_user_adjusting {
81-
let new_percentage = service.current * 100 / service.max;
82-
if (new_percentage as i32 - self.ui_percentage as i32).abs() > 2 {
83-
self.ui_percentage = new_percentage;
84-
}
85-
}
8668
}
8769
Action::None
8870
}
8971
_ => Action::None,
9072
},
91-
Message::Change(value) => {
92-
self.is_user_adjusting = true;
93-
self.reset_timer_active = true;
94-
self.ui_percentage = value * 100
95-
/ if let Some(service) = &self.service {
96-
service.max
97-
} else {
98-
100
99-
};
100-
match self.service.as_mut() {
101-
Some(service) => Action::Command(
102-
service
103-
.command(BrightnessCommand::Set(value))
104-
.map(Message::Event),
105-
),
106-
_ => Action::None,
107-
}
108-
}
109-
Message::MenuOpened => {
73+
Message::Changed(message) => {
11074
if let Some(service) = self.service.as_mut() {
111-
Action::Command(
112-
service
113-
.command(BrightnessCommand::Refresh)
114-
.map(Message::Event),
115-
)
116-
} else {
117-
Action::None
75+
if let Some(value) = message.value() {
76+
let _ = service.command(BrightnessCommand(value));
77+
}
78+
return Action::Command(service.current.update(message).map(Message::Changed));
11879
}
119-
}
120-
Message::ResetUserAdjusting => {
121-
self.is_user_adjusting = false;
122-
self.reset_timer_active = false;
12380
Action::None
12481
}
12582
Message::ConfigReloaded(format) => {
@@ -129,27 +86,25 @@ impl BrightnessSettings {
12986
}
13087
}
13188

132-
pub fn slider(&'_ self, theme: &AshellTheme) -> Option<Element<'_, Message>> {
89+
pub fn slider<'a>(&'a self, theme: &AshellTheme) -> Option<Element<'a, Message>> {
13390
self.service.as_ref().map(|service| {
134-
let max = service.max;
135-
let current_percentage = self.ui_percentage;
13691
row!(
13792
container(icon_mono(StaticIcon::Brightness))
13893
.center_x(32.)
13994
.center_y(32.)
14095
.clip(true),
14196
MouseArea::new(
142-
slider(0..=100, current_percentage, move |v| {
143-
Message::Change(v * max / 100)
144-
})
145-
.step(1_u32)
146-
.width(Length::Fill),
97+
Element::<'a, remote_value::Message<u32>>::from(
98+
slider(
99+
0..=service.max,
100+
service.current.value(),
101+
remote_value::Message::Request,
102+
)
103+
.on_release(remote_value::Message::Timeout),
104+
)
105+
.map(Message::Changed)
147106
)
148-
.on_scroll(move |delta| Self::calculate_scroll_brightness(
149-
current_percentage,
150-
max,
151-
delta
152-
)),
107+
.on_scroll(Self::on_scroll(service.current.value(), service.max))
153108
)
154109
.align_y(Alignment::Center)
155110
.spacing(theme.space.xs)
@@ -162,26 +117,22 @@ impl BrightnessSettings {
162117
theme: &'a AshellTheme,
163118
) -> Option<Element<'a, Message>> {
164119
self.service.as_ref().map(|service| {
165-
let percentage = self.ui_percentage;
166-
let max_value = service.max;
167-
168-
let scroll_handler =
169-
move |delta| Self::calculate_scroll_brightness(percentage, max_value, delta);
120+
let scroll_handler = Self::on_scroll(service.current.value(), service.max);
170121

171122
match self.config {
172123
SettingsFormat::Icon => {
173124
let icon = icon_mono(StaticIcon::Brightness);
174125
MouseArea::new(icon).on_scroll(scroll_handler).into()
175126
}
176127
SettingsFormat::Percentage | SettingsFormat::Time => {
177-
MouseArea::new(text(format!("{}%", percentage)))
128+
MouseArea::new(Self::percent_text(service))
178129
.on_scroll(scroll_handler)
179130
.into()
180131
}
181132
SettingsFormat::IconAndPercentage | SettingsFormat::IconAndTime => {
182133
let icon = icon_mono(StaticIcon::Brightness);
183134
MouseArea::new(
184-
row!(icon, text(format!("{}%", percentage)))
135+
row!(icon, Self::percent_text(service))
185136
.spacing(theme.space.xxs)
186137
.align_y(Alignment::Center),
187138
)
@@ -193,19 +144,13 @@ impl BrightnessSettings {
193144
}
194145

195146
pub fn subscription(&self) -> Subscription<Message> {
196-
Subscription::batch([
197-
BrightnessService::subscribe().map(Message::Event),
198-
if self.reset_timer_active {
199-
Subscription::run_with_id(
200-
0,
201-
stream::once(async {
202-
tokio::time::sleep(std::time::Duration::from_millis(500)).await;
203-
Message::ResetUserAdjusting
204-
}),
205-
)
206-
} else {
207-
Subscription::none()
208-
},
209-
])
147+
BrightnessService::subscribe().map(Message::Event)
148+
}
149+
150+
pub fn percent_text<'a>(service: &BrightnessService) -> Text<'a> {
151+
let percent = (service.current.value() * 100)
152+
.checked_div(service.max)
153+
.unwrap_or(0); // Always show 0%, if max_brightness happens to be 0
154+
text(format!("{percent}%"))
210155
}
211156
}

src/modules/settings/mod.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -415,14 +415,7 @@ impl Settings {
415415
)
416416
};
417417

418-
// Batch both tasks to run in parallel
419-
let brightness_task = match self.brightness.update(brightness::Message::MenuOpened)
420-
{
421-
brightness::Action::None => Task::none(),
422-
brightness::Action::Command(task) => task.map(Message::Brightness),
423-
};
424-
425-
Action::Command(Task::batch([custom_buttons_task, brightness_task]))
418+
Action::Command(custom_buttons_task)
426419
}
427420
Message::ConfigReloaded(config) => {
428421
self.lock_cmd = config.lock_cmd;

0 commit comments

Comments
 (0)