mirror of
https://github.com/ByteAtATime/raycast-linux.git
synced 2025-12-23 10:11:57 +00:00
refactor: extract ActionPanel state into separate struct
This commit is contained in:
parent
cda9834b1a
commit
07b332b845
7 changed files with 211 additions and 174 deletions
|
|
@ -1,15 +1,16 @@
|
|||
use iced::widget::text;
|
||||
use iced::{
|
||||
Alignment::Center,
|
||||
Border, Color, Element, Length, Padding, Theme, color,
|
||||
Border, Color, Element, Length, Padding, Task, Theme, color,
|
||||
widget::{
|
||||
Button, button, column, container, mouse_area, opaque, row, rule, space, text::LineHeight,
|
||||
text_input,
|
||||
},
|
||||
};
|
||||
use std::time::Instant;
|
||||
|
||||
use crate::{
|
||||
components::actions::{Action, ActionPanelItem, ActionPanelSection},
|
||||
components::actions::{Action, ActionHandler, ActionPanelItem, ActionPanelSection},
|
||||
icons,
|
||||
};
|
||||
|
||||
|
|
@ -27,45 +28,171 @@ const SECTION_TITLE_COLOR: Color = Color::from_rgba(1.0, 1.0, 1.0, 0.5);
|
|||
const TEXT_COLOR: Color = Color::WHITE;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ActionPanelMessage {
|
||||
pub enum Message {
|
||||
Open,
|
||||
Close,
|
||||
InvokeAction(crate::components::actions::ActionHandler),
|
||||
InvokeAction(ActionHandler),
|
||||
SearchChanged(String),
|
||||
Select(usize),
|
||||
MoveUp,
|
||||
MoveDown,
|
||||
InvokeSelected,
|
||||
Tick(Instant),
|
||||
}
|
||||
|
||||
pub fn render_action_panel(
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct AnimationState {
|
||||
pub start_time: Option<Instant>,
|
||||
pub opacity: f32,
|
||||
pub scale: f32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct State {
|
||||
pub visible: bool,
|
||||
pub search_text: String,
|
||||
pub selected_index: usize,
|
||||
pub input_id: iced::widget::Id,
|
||||
pub animation: AnimationState,
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
visible: false,
|
||||
search_text: String::new(),
|
||||
selected_index: 0,
|
||||
input_id: iced::widget::Id::unique(),
|
||||
animation: AnimationState::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(
|
||||
&mut self,
|
||||
message: Message,
|
||||
actions: &[ActionPanelItem],
|
||||
) -> (Task<crate::Message>, Option<ActionHandler>) {
|
||||
match message {
|
||||
Message::Open => {
|
||||
self.visible = true;
|
||||
self.selected_index = 0;
|
||||
self.animation.start_time = Some(Instant::now());
|
||||
self.animation.opacity = animation::OPACITY_START;
|
||||
self.animation.scale = animation::SCALE_START;
|
||||
(iced::widget::operation::focus(self.input_id.clone()), None)
|
||||
}
|
||||
Message::Close => {
|
||||
self.visible = false;
|
||||
self.reset();
|
||||
(Task::none(), None)
|
||||
}
|
||||
Message::InvokeAction(handler) => {
|
||||
self.visible = false;
|
||||
self.reset();
|
||||
(Task::none(), Some(handler))
|
||||
}
|
||||
Message::SearchChanged(text) => {
|
||||
self.search_text = text;
|
||||
self.selected_index = 0;
|
||||
(Task::none(), None)
|
||||
}
|
||||
Message::Select(index) => {
|
||||
self.selected_index = index;
|
||||
(Task::none(), None)
|
||||
}
|
||||
Message::MoveUp => {
|
||||
if self.selected_index > 0 {
|
||||
self.selected_index -= 1;
|
||||
}
|
||||
(Task::none(), None)
|
||||
}
|
||||
Message::MoveDown => {
|
||||
let count = count_actions(actions, &self.search_text);
|
||||
if self.selected_index < count.saturating_sub(1) {
|
||||
self.selected_index += 1;
|
||||
}
|
||||
(Task::none(), None)
|
||||
}
|
||||
Message::InvokeSelected => {
|
||||
let filtered = filter_actions(actions, &self.search_text);
|
||||
let action = filtered
|
||||
.iter()
|
||||
.flat_map(|item| match item {
|
||||
ActionPanelItem::Action(a) => std::slice::from_ref(a).iter(),
|
||||
ActionPanelItem::Section(s) => s.children.iter(),
|
||||
})
|
||||
.nth(self.selected_index);
|
||||
|
||||
if let Some(action) = action {
|
||||
if let Some(handler) = &action.handler {
|
||||
self.visible = false;
|
||||
self.reset();
|
||||
return (Task::none(), Some(handler.clone()));
|
||||
}
|
||||
}
|
||||
(Task::none(), None)
|
||||
}
|
||||
Message::Tick(now) => {
|
||||
if let Some(start) = self.animation.start_time {
|
||||
let elapsed = now.duration_since(start).as_millis() as f32;
|
||||
let duration = animation::DURATION_MS as f32;
|
||||
let t = (elapsed / duration).clamp(0.0, 1.0);
|
||||
|
||||
let ease = 1.0 - (1.0 - t).powi(2);
|
||||
|
||||
self.animation.opacity =
|
||||
animation::OPACITY_START + (1.0 - animation::OPACITY_START) * ease;
|
||||
self.animation.scale =
|
||||
animation::SCALE_START + (1.0 - animation::SCALE_START) * ease;
|
||||
|
||||
if t >= 1.0 {
|
||||
self.animation.start_time = None;
|
||||
self.animation.opacity = 1.0;
|
||||
self.animation.scale = 1.0;
|
||||
}
|
||||
}
|
||||
(Task::none(), None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn reset(&mut self) {
|
||||
self.search_text.clear();
|
||||
self.selected_index = 0;
|
||||
self.animation.start_time = None;
|
||||
self.animation.opacity = 1.0;
|
||||
self.animation.scale = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_action_panel<'a>(
|
||||
state: &'a State,
|
||||
actions: &[ActionPanelItem],
|
||||
search_text: &str,
|
||||
selected_index: usize,
|
||||
opacity: f32,
|
||||
input_id: iced::widget::Id,
|
||||
) -> Element<'static, ActionPanelMessage> {
|
||||
let filtered_actions = filter_actions(actions, search_text);
|
||||
let search_text_owned = search_text.to_string();
|
||||
) -> Element<'a, Message> {
|
||||
let filtered_actions = filter_actions(actions, &state.search_text);
|
||||
let search_text_owned = state.search_text.to_string();
|
||||
let filtered_count = filtered_actions.len();
|
||||
|
||||
let text_color = Color {
|
||||
a: opacity,
|
||||
a: state.animation.opacity,
|
||||
..TEXT_COLOR
|
||||
};
|
||||
let section_title_color = Color {
|
||||
a: 0.5 * opacity,
|
||||
a: 0.5 * state.animation.opacity,
|
||||
..SECTION_TITLE_COLOR
|
||||
};
|
||||
let bg_color = Color {
|
||||
a: opacity,
|
||||
a: state.animation.opacity,
|
||||
..color!(0x2c2c2c)
|
||||
};
|
||||
|
||||
let mut current_index = 0usize;
|
||||
let _total_actions = count_actions(&filtered_actions, &search_text_owned);
|
||||
|
||||
let actions_col = filtered_actions.into_iter().enumerate().fold(
|
||||
column![].width(Length::Fill).padding([12, 0]),
|
||||
|col, (idx, action)| match action {
|
||||
ActionPanelItem::Action(action) => {
|
||||
let is_selected = current_index == selected_index;
|
||||
let is_selected = current_index == state.selected_index;
|
||||
current_index += 1;
|
||||
|
||||
col.push(
|
||||
|
|
@ -73,7 +200,7 @@ pub fn render_action_panel(
|
|||
action,
|
||||
is_selected,
|
||||
current_index - 1,
|
||||
opacity,
|
||||
state.animation.opacity,
|
||||
))
|
||||
.width(Length::Fill)
|
||||
.padding([0, 8]),
|
||||
|
|
@ -84,11 +211,11 @@ pub fn render_action_panel(
|
|||
|
||||
let mut col = col.push(render_section_owned(
|
||||
section,
|
||||
selected_index,
|
||||
state.selected_index,
|
||||
&mut current_index,
|
||||
is_first,
|
||||
section_title_color,
|
||||
opacity,
|
||||
state.animation.opacity,
|
||||
));
|
||||
|
||||
if idx < filtered_count - 1 {
|
||||
|
|
@ -104,17 +231,17 @@ pub fn render_action_panel(
|
|||
);
|
||||
|
||||
let search_bar = text_input("Search for actions...", &search_text_owned)
|
||||
.id(input_id)
|
||||
.on_input(ActionPanelMessage::SearchChanged)
|
||||
.id(state.input_id.clone())
|
||||
.on_input(Message::SearchChanged)
|
||||
.size(13)
|
||||
.padding([0, 16])
|
||||
.style(move |_theme: &Theme, _status| text_input::Style {
|
||||
background: iced::Background::Color(Color::TRANSPARENT),
|
||||
border: iced::Border::default(),
|
||||
icon: text_color,
|
||||
placeholder: Color::from_rgba(1.0, 1.0, 1.0, 0.4 * opacity),
|
||||
placeholder: Color::from_rgba(1.0, 1.0, 1.0, 0.4 * state.animation.opacity),
|
||||
value: text_color,
|
||||
selection: Color::from_rgba(1.0, 1.0, 1.0, 0.2 * opacity),
|
||||
selection: Color::from_rgba(1.0, 1.0, 1.0, 0.2 * state.animation.opacity),
|
||||
});
|
||||
|
||||
let search_container = column![rule::horizontal(1), container(search_bar).center_y(44)];
|
||||
|
|
@ -138,7 +265,7 @@ pub fn render_action_panel(
|
|||
.align_right(Length::Fill)
|
||||
.padding([0, 12]),
|
||||
)
|
||||
.on_press(ActionPanelMessage::Close),
|
||||
.on_press(Message::Close),
|
||||
)
|
||||
.into()
|
||||
}
|
||||
|
|
@ -197,7 +324,7 @@ fn render_action_owned(
|
|||
is_selected: bool,
|
||||
index: usize,
|
||||
opacity: f32,
|
||||
) -> Element<'static, ActionPanelMessage> {
|
||||
) -> Element<'static, Message> {
|
||||
let title = action.title.clone();
|
||||
let icon_char = action
|
||||
.icon
|
||||
|
|
@ -210,7 +337,7 @@ fn render_action_owned(
|
|||
..TEXT_COLOR
|
||||
};
|
||||
|
||||
let content: Element<'static, ActionPanelMessage> = if let Some(icon) = icon_char {
|
||||
let content: Element<'static, Message> = if let Some(icon) = icon_char {
|
||||
row![
|
||||
text(icon).font(ICON_FONT).size(18).color(text_color),
|
||||
text(title).font(INTER_FONT).color(text_color)
|
||||
|
|
@ -253,9 +380,9 @@ fn render_action_owned(
|
|||
});
|
||||
|
||||
if let Some(handler) = action.handler {
|
||||
btn = btn.on_press(ActionPanelMessage::InvokeAction(handler));
|
||||
btn = btn.on_press(Message::InvokeAction(handler));
|
||||
} else {
|
||||
btn = btn.on_press(ActionPanelMessage::Select(index));
|
||||
btn = btn.on_press(Message::Select(index));
|
||||
}
|
||||
|
||||
btn.into()
|
||||
|
|
@ -268,7 +395,7 @@ fn render_section_owned(
|
|||
is_first: bool,
|
||||
section_title_color: Color,
|
||||
opacity: f32,
|
||||
) -> Element<'static, ActionPanelMessage> {
|
||||
) -> Element<'static, Message> {
|
||||
let section_title = text(section.props.title.clone())
|
||||
.size(13)
|
||||
.line_height(LineHeight::Absolute(iced::Pixels(14.0)))
|
||||
|
|
@ -295,12 +422,3 @@ fn render_section_owned(
|
|||
.padding(Padding::from(8).top(top_pad))
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn map_action_panel_message(msg: ActionPanelMessage) -> crate::Message {
|
||||
match msg {
|
||||
ActionPanelMessage::Close => crate::Message::ToggleActionPanel(false),
|
||||
ActionPanelMessage::InvokeAction(handler) => crate::Message::InvokeAction(handler),
|
||||
ActionPanelMessage::SearchChanged(text) => crate::Message::ActionPanelSearchChanged(text),
|
||||
ActionPanelMessage::Select(index) => crate::Message::ActionPanelSelect(index),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,7 +121,9 @@ pub fn render_footer<'a>(
|
|||
|
||||
pub fn map_footer_message(msg: FooterMessage) -> crate::Message {
|
||||
match msg {
|
||||
FooterMessage::OpenActionPanel => crate::Message::ToggleActionPanel(true),
|
||||
FooterMessage::OpenActionPanel => {
|
||||
crate::Message::ActionPanel(crate::components::action_panel::Message::Open)
|
||||
}
|
||||
FooterMessage::InvokeAction(handler) => crate::Message::InvokeAction(handler),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ fn subscription(state: &State) -> Subscription<Message> {
|
|||
|
||||
let window_close_sub = window::close_events().map(Message::WindowClosed);
|
||||
|
||||
let animation_sub = if state.action_panel_start_time.is_some() {
|
||||
let animation_sub = if state.action_panel.animation.start_time.is_some() {
|
||||
window::frames().map(Message::Tick)
|
||||
} else {
|
||||
Subscription::none()
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ use iced::widget::image::Handle;
|
|||
use iced::window;
|
||||
use std::time::Instant;
|
||||
|
||||
use crate::components::action_panel;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Message {
|
||||
UpdateTree(Tree),
|
||||
|
|
@ -14,11 +16,9 @@ pub enum Message {
|
|||
EscapePressed,
|
||||
ImageLoaded(String, Handle),
|
||||
InvokeAction(ActionHandler),
|
||||
ToggleActionPanel(bool),
|
||||
ActionPanelSearchChanged(String),
|
||||
ActionPanelSelect(usize),
|
||||
ActionPanelMoveUp,
|
||||
ActionPanelMoveDown,
|
||||
|
||||
ActionPanel(action_panel::Message),
|
||||
|
||||
ShowToast(String),
|
||||
DropdownChanged(String),
|
||||
LaunchCommand(ExtensionCommand),
|
||||
|
|
|
|||
22
src/state.rs
22
src/state.rs
|
|
@ -1,9 +1,9 @@
|
|||
use iced::widget::Id as WidgetId;
|
||||
use iced::window;
|
||||
use std::path::PathBuf;
|
||||
use std::time::Instant;
|
||||
|
||||
use crate::apps;
|
||||
use crate::components::action_panel;
|
||||
use crate::components::actions::ActionPanelItem;
|
||||
use crate::extensions;
|
||||
use crate::frecency::FrecencyStore;
|
||||
|
|
@ -20,19 +20,13 @@ pub struct State {
|
|||
pub theme: Theme,
|
||||
pub search_text: String,
|
||||
pub search_input_id: WidgetId,
|
||||
pub action_panel_input_id: WidgetId,
|
||||
pub action_panel_visible: bool,
|
||||
pub action_panel_search: String,
|
||||
pub action_panel_selected: usize,
|
||||
|
||||
pub action_panel: action_panel::State,
|
||||
pub selected_actions: Vec<ActionPanelItem>,
|
||||
|
||||
pub toast_message: String,
|
||||
pub window_id: Option<window::Id>,
|
||||
pub settings_window_id: Option<window::Id>,
|
||||
|
||||
// Animation state
|
||||
pub action_panel_start_time: Option<Instant>,
|
||||
pub action_panel_opacity: f32,
|
||||
pub action_panel_scale: f32,
|
||||
}
|
||||
|
||||
fn get_frecency_path() -> PathBuf {
|
||||
|
|
@ -71,17 +65,11 @@ impl State {
|
|||
theme,
|
||||
search_text,
|
||||
search_input_id: WidgetId::unique(),
|
||||
action_panel_input_id: WidgetId::unique(),
|
||||
action_panel_visible: false,
|
||||
action_panel_search: String::new(),
|
||||
action_panel_selected: 0,
|
||||
action_panel: action_panel::State::new(),
|
||||
selected_actions: Vec::new(),
|
||||
toast_message: String::new(),
|
||||
window_id: None,
|
||||
settings_window_id: None,
|
||||
action_panel_start_time: None,
|
||||
action_panel_opacity: 1.0,
|
||||
action_panel_scale: 1.0,
|
||||
};
|
||||
|
||||
state.update_selected_actions();
|
||||
|
|
|
|||
135
src/update.rs
135
src/update.rs
|
|
@ -5,7 +5,6 @@ use iced::{
|
|||
window,
|
||||
};
|
||||
use serde_json::Value;
|
||||
use std::time::Instant;
|
||||
|
||||
use crate::apps;
|
||||
use crate::components::action_panel;
|
||||
|
|
@ -107,62 +106,31 @@ pub fn update(state: &mut State, message: Message) -> Task<Message> {
|
|||
Message::InvokeAction(handler) => {
|
||||
return handler.call();
|
||||
}
|
||||
Message::ToggleActionPanel(visibility) => {
|
||||
state.action_panel_visible = visibility;
|
||||
if visibility {
|
||||
state.action_panel_selected = 0;
|
||||
state.action_panel_start_time = Some(Instant::now());
|
||||
state.action_panel_opacity = action_panel::animation::OPACITY_START;
|
||||
state.action_panel_scale = action_panel::animation::SCALE_START;
|
||||
return operation::focus(state.action_panel_input_id.clone());
|
||||
} else {
|
||||
state.action_panel_start_time = None;
|
||||
state.action_panel_search.clear();
|
||||
state.action_panel_selected = 0;
|
||||
if state.screen.can_search() {
|
||||
return operation::focus(state.search_input_id.clone());
|
||||
Message::ActionPanel(msg) => {
|
||||
let actions = state.selected_actions.clone();
|
||||
let (task, command) = state.action_panel.update(msg, &actions);
|
||||
|
||||
if !state.action_panel.visible && state.screen.can_search() {
|
||||
if command.is_none() {
|
||||
return Task::batch(vec![
|
||||
task,
|
||||
operation::focus(state.search_input_id.clone()),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(handler) = command {
|
||||
return Task::batch(vec![task, handler.call()]);
|
||||
}
|
||||
|
||||
return task;
|
||||
}
|
||||
Message::Tick(now) => {
|
||||
if let Some(start) = state.action_panel_start_time {
|
||||
let elapsed = now.duration_since(start).as_millis() as f32;
|
||||
let duration = action_panel::animation::DURATION_MS as f32;
|
||||
let t = (elapsed / duration).clamp(0.0, 1.0);
|
||||
|
||||
let ease = 1.0 - (1.0 - t).powi(2);
|
||||
|
||||
state.action_panel_opacity = action_panel::animation::OPACITY_START
|
||||
+ (1.0 - action_panel::animation::OPACITY_START) * ease;
|
||||
state.action_panel_scale = action_panel::animation::SCALE_START
|
||||
+ (1.0 - action_panel::animation::SCALE_START) * ease;
|
||||
|
||||
if t >= 1.0 {
|
||||
state.action_panel_start_time = None;
|
||||
state.action_panel_opacity = 1.0;
|
||||
state.action_panel_scale = 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
Message::ActionPanelSearchChanged(text) => {
|
||||
state.action_panel_search = text;
|
||||
state.action_panel_selected = 0;
|
||||
}
|
||||
Message::ActionPanelSelect(index) => {
|
||||
state.action_panel_selected = index;
|
||||
}
|
||||
Message::ActionPanelMoveUp => {
|
||||
if state.action_panel_selected > 0 {
|
||||
state.action_panel_selected -= 1;
|
||||
}
|
||||
}
|
||||
Message::ActionPanelMoveDown => {
|
||||
let count = crate::components::action_panel::count_actions(
|
||||
&state.selected_actions,
|
||||
&state.action_panel_search,
|
||||
);
|
||||
if state.action_panel_selected < count.saturating_sub(1) {
|
||||
state.action_panel_selected += 1;
|
||||
if state.action_panel.animation.start_time.is_some() {
|
||||
return update(
|
||||
state,
|
||||
Message::ActionPanel(action_panel::Message::Tick(now)),
|
||||
);
|
||||
}
|
||||
}
|
||||
Message::ShowToast(message) => {
|
||||
|
|
@ -255,15 +223,8 @@ fn dispatch_screen_message(state: &mut State, message: Message) -> Task<Message>
|
|||
}
|
||||
|
||||
fn handle_escape(state: &mut State) -> Task<Message> {
|
||||
if state.action_panel_visible {
|
||||
state.action_panel_visible = false;
|
||||
state.action_panel_search.clear();
|
||||
state.action_panel_selected = 0;
|
||||
state.action_panel_start_time = None;
|
||||
if state.screen.can_search() {
|
||||
return operation::focus(state.search_input_id.clone());
|
||||
}
|
||||
return Task::none();
|
||||
if state.action_panel.visible {
|
||||
return update(state, Message::ActionPanel(action_panel::Message::Close));
|
||||
}
|
||||
|
||||
if !state.search_text.is_empty() {
|
||||
|
|
@ -291,38 +252,23 @@ fn handle_key_press(state: &mut State, key: Key, modifiers: Modifiers) -> Task<M
|
|||
return handle_escape(state);
|
||||
}
|
||||
|
||||
if state.action_panel_visible {
|
||||
if state.action_panel.visible {
|
||||
if modifiers.is_empty() {
|
||||
match named_key {
|
||||
Named::ArrowUp => {
|
||||
return Task::done(Message::ActionPanelMoveUp);
|
||||
return update(state, Message::ActionPanel(action_panel::Message::MoveUp));
|
||||
}
|
||||
Named::ArrowDown => {
|
||||
return Task::done(Message::ActionPanelMoveDown);
|
||||
return update(
|
||||
state,
|
||||
Message::ActionPanel(action_panel::Message::MoveDown),
|
||||
);
|
||||
}
|
||||
Named::Enter => {
|
||||
let filtered = crate::components::action_panel::filter_actions(
|
||||
&state.selected_actions,
|
||||
&state.action_panel_search,
|
||||
return update(
|
||||
state,
|
||||
Message::ActionPanel(action_panel::Message::InvokeSelected),
|
||||
);
|
||||
let action = filtered
|
||||
.iter()
|
||||
.flat_map(|item| match item {
|
||||
ActionPanelItem::Action(a) => std::slice::from_ref(a).iter(),
|
||||
ActionPanelItem::Section(s) => s.children.iter(),
|
||||
})
|
||||
.nth(state.action_panel_selected);
|
||||
|
||||
if let Some(action) = action {
|
||||
if let Some(handler) = &action.handler {
|
||||
state.action_panel_visible = false;
|
||||
state.action_panel_search.clear();
|
||||
state.action_panel_selected = 0;
|
||||
state.action_panel_start_time = None;
|
||||
return handler.call();
|
||||
}
|
||||
}
|
||||
return Task::none();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
@ -367,21 +313,10 @@ fn handle_key_press(state: &mut State, key: Key, modifiers: Modifiers) -> Task<M
|
|||
if modifiers == Modifiers::COMMAND {
|
||||
if let Key::Character(c) = &key {
|
||||
if c == "k" {
|
||||
let new_vis = !state.action_panel_visible;
|
||||
state.action_panel_visible = new_vis;
|
||||
if new_vis {
|
||||
state.action_panel_selected = 0;
|
||||
state.action_panel_start_time = Some(Instant::now());
|
||||
state.action_panel_opacity = action_panel::animation::OPACITY_START;
|
||||
state.action_panel_scale = action_panel::animation::SCALE_START;
|
||||
return operation::focus(state.action_panel_input_id.clone());
|
||||
if state.action_panel.visible {
|
||||
return update(state, Message::ActionPanel(action_panel::Message::Close));
|
||||
} else {
|
||||
state.action_panel_start_time = None;
|
||||
if state.screen.can_search() {
|
||||
return operation::focus(state.search_input_id.clone());
|
||||
} else {
|
||||
return Task::none();
|
||||
}
|
||||
return update(state, Message::ActionPanel(action_panel::Message::Open));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
16
src/view.rs
16
src/view.rs
|
|
@ -3,7 +3,7 @@ use iced::{Element, Length, Theme};
|
|||
|
||||
use crate::components::animator::Scaler;
|
||||
use crate::components::{
|
||||
action_panel::{map_action_panel_message, render_action_panel},
|
||||
action_panel::render_action_panel,
|
||||
dropdown::{Dropdown, DropdownChild},
|
||||
footer::{map_footer_message, render_footer},
|
||||
};
|
||||
|
|
@ -45,17 +45,11 @@ pub fn view(state: &State) -> Element<'_, Message> {
|
|||
.push(container(content).width(Length::Fill).height(Length::Fill))
|
||||
.push(footer);
|
||||
|
||||
let action_panel = if state.action_panel_visible {
|
||||
let panel_content = render_action_panel(
|
||||
&state.selected_actions,
|
||||
&state.action_panel_search,
|
||||
state.action_panel_selected,
|
||||
state.action_panel_opacity,
|
||||
state.action_panel_input_id.clone(),
|
||||
)
|
||||
.map(map_action_panel_message);
|
||||
let action_panel = if state.action_panel.visible {
|
||||
let panel_content = render_action_panel(&state.action_panel, &state.selected_actions)
|
||||
.map(Message::ActionPanel);
|
||||
|
||||
let animated = Scaler::new(state.action_panel_scale, panel_content);
|
||||
let animated = Scaler::new(state.action_panel.animation.scale, panel_content);
|
||||
|
||||
Some(Element::from(animated))
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue