@@ -6,19 +6,18 @@ use crate::{
66 brightness:: { BrightnessCommand , BrightnessService } ,
77 } ,
88 theme:: AshellTheme ,
9+ utils:: remote_value,
910} ;
1011use 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 ) ]
1718pub 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 {
3029pub 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
3834impl 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}
0 commit comments