From 93fcf5d6a6f5461ccb46b09faa58b7bedb49886f Mon Sep 17 00:00:00 2001
From: Kubat <mael.martin31@gmail.com>
Date: Mon, 23 Oct 2023 06:49:05 +0200
Subject: [PATCH] AMADEUS: The message of what to show is send at update time,
 not at view time

---
 amadeus/src/app.rs                            | 49 ++++++++---------
 amadeus/src/components/mainpanel/mod.rs       | 53 ++++++++++++++++---
 amadeus/src/components/mainpanel/playlists.rs | 27 ++++++----
 3 files changed, 89 insertions(+), 40 deletions(-)

diff --git a/amadeus/src/app.rs b/amadeus/src/app.rs
index 86b9c8ec..e1eba7fa 100644
--- a/amadeus/src/app.rs
+++ b/amadeus/src/app.rs
@@ -60,8 +60,9 @@ pub struct Amadeus {
     /// The main panel, displays the queue, history, etc.
     mainpanel: mainpanel::State,
 
-    /// What to show in the main panel.
-    show: MainPanelDisplay,
+    /// Whever to show the main panel or not, if we don't show the mainpanel, then we show the
+    /// config panel.
+    show_main_panel: bool,
 
     /// Currently playing kara, for the title.
     current_kara: Option<Arc<Kara>>,
@@ -89,6 +90,7 @@ impl Default for Amadeus {
             // Manual defaults.
             last_instant: iced::time::Instant::now(),
             sidebar_size: Some(300),
+            show_main_panel: false,
 
             // Has default.
             kara_store: Arc::new(KaraStore::new()),
@@ -99,7 +101,6 @@ impl Default for Amadeus {
             bottombar: Default::default(),
             topbar: Default::default(),
             mainpanel: Default::default(),
-            show: Default::default(),
             current_kara: Default::default(),
             playback_state: Default::default(),
             modal: Default::default(),
@@ -663,10 +664,16 @@ impl Application for Amadeus {
 
             // Change what the main panel displays + We have informations to pass to it
             Message::MainPanelMessage(message) => self.mainpanel.update(message).map(Message::from),
-            Message::MainPanelDisplay(show) => {
-                self.show = show;
+            Message::MainPanelDisplay(MainPanelDisplay::Config) => {
+                self.show_main_panel = false;
                 Command::none()
             }
+            Message::MainPanelDisplay(MainPanelDisplay::MainPanel(show)) => {
+                self.show_main_panel = true;
+                self.mainpanel
+                    .update(mainpanel::Message::Show(show))
+                    .map(Message::from)
+            }
 
             // A message for the side panel.
             Message::SideBarResize(size) => {
@@ -732,30 +739,24 @@ impl Application for Amadeus {
         }
 
         // Main panel
-        let inner_main_panel = container(match self.show {
-            MainPanelDisplay::MainPanel(ref show) => self.mainpanel.view(show).map(Message::from),
-            MainPanelDisplay::Config => self.config.view().map(Message::from),
+        let inner_main_panel = container(match self.show_main_panel {
+            true => self.mainpanel.view().map(Message::from),
+            false => self.config.view().map(Message::from),
         })
         .width(Length::Fill)
         .height(Length::Fill)
         .padding(20);
 
-        let main_panel_title = row![
-            text(&self.show).size(SIZE_FONT_TITLE),
-            horizontal_space(Length::Fill),
-        ];
-        let main_panel_title = match self.show {
-            MainPanelDisplay::Config => {
-                main_panel_title.push(Into::<Element<'_, Self::Message>>::into(row![
-                    tip!(icon!(SIZE_FONT_MEDIUM | Fullscreen -> Message::ToggleFullScreen)                       => Bottom | "Toggle fullscreen"),
-                    tip!(icon!(SIZE_FONT_MEDIUM | Github     -> Message::OpenLinkInBrowser(LEKTORD_HOME_LINK))   => Bottom | "Open lektor homepage"),
-                    tip!(icon!(SIZE_FONT_MEDIUM | Bug        -> Message::OpenLinkInBrowser(LEKTORD_ISSUES_LINK)) => Bottom | "Open issues for lektor"),
-                    tip!(icon!(SIZE_FONT_MEDIUM | XOctagon   -> Message::ShutdownLektord)                        => Bottom | "Shutdown lektord and exit amadeus"),
-                ]))
-            }
-            MainPanelDisplay::MainPanel(ref show) => {
-                main_panel_title.push(self.mainpanel.view_actions(show).map(Message::from))
-            }
+        let main_panel_title = match self.show_main_panel {
+            true => self.mainpanel.view_title().push(self.mainpanel.view_actions().map(Message::from)),
+            false => row![
+                text("Settings").size(SIZE_FONT_TITLE),
+                horizontal_space(Length::Fill),
+                tip!(icon!(SIZE_FONT_MEDIUM | Fullscreen -> Message::ToggleFullScreen)                       => Bottom | "Toggle fullscreen"),
+                tip!(icon!(SIZE_FONT_MEDIUM | Github     -> Message::OpenLinkInBrowser(LEKTORD_HOME_LINK))   => Bottom | "Open lektor homepage"),
+                tip!(icon!(SIZE_FONT_MEDIUM | Bug        -> Message::OpenLinkInBrowser(LEKTORD_ISSUES_LINK)) => Bottom | "Open issues for lektor"),
+                tip!(icon!(SIZE_FONT_MEDIUM | XOctagon   -> Message::ShutdownLektord)                        => Bottom | "Shutdown lektord and exit amadeus"),
+            ],
         }
         .padding(0)
         .height(Length::Shrink)
diff --git a/amadeus/src/components/mainpanel/mod.rs b/amadeus/src/components/mainpanel/mod.rs
index 545d339d..e894b964 100644
--- a/amadeus/src/components/mainpanel/mod.rs
+++ b/amadeus/src/components/mainpanel/mod.rs
@@ -5,7 +5,11 @@ pub mod playlists;
 pub mod queue;
 pub mod search;
 
-use iced::{Command, Element};
+use crate::style_sheet::sizes::*;
+use iced::{
+    widget::{horizontal_space, row, text, Row},
+    Command, Element, Length,
+};
 use search::filter;
 use std::sync::Arc;
 
@@ -16,6 +20,7 @@ pub struct State {
     search: search::State,
     history: history::State,
     playlists: playlists::State,
+    show: Show,
 }
 
 /// What to show in the main panel.
@@ -35,6 +40,7 @@ pub enum Message {
     Queue(queue::Message),
     Search(search::Message),
     Playlists(playlists::Message),
+    Show(Show),
 }
 
 /// Request more information to display. Those things requires to communicate whith the server.
@@ -46,6 +52,17 @@ pub enum Request {
     Playlists(playlists::Request),
 }
 
+impl std::fmt::Display for Show {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self {
+            Show::Queue => f.write_str("Queue"),
+            Show::History => f.write_str("History"),
+            Show::Database => f.write_str("Search Database"),
+            Show::Playlist(plt) => write!(f, "Playlist {plt}"),
+        }
+    }
+}
+
 impl From<history::Message> for Message {
     fn from(value: history::Message) -> Self {
         Self::History(value)
@@ -107,27 +124,49 @@ impl State {
             Message::Search(msg) => self.search.update(msg).map(Request::Search),
             Message::History(msg) => self.history.update(msg).map(Request::History),
             Message::Playlists(msg) => self.playlists.update(msg).map(Request::Playlists),
+            Message::Show(show) => match show {
+                Show::Playlist(ref name) => {
+                    let name = name.clone();
+                    self.show = show;
+                    self.playlists
+                        .update(playlists::Message::ShowPlaylist(name))
+                        .map(Request::from)
+                }
+                show => {
+                    self.show = show;
+                    Command::none()
+                }
+            },
         }
     }
 
+    /// View the name of the main panel. As we don't return anny message, we add a generic type to
+    /// adapt this function to any message type.
+    pub fn view_title<'a, T: 'a>(&'a self) -> Row<'a, T> {
+        row![
+            text(&self.show).size(SIZE_FONT_TITLE),
+            horizontal_space(Length::Fill),
+        ]
+    }
+
     /// View some global actions, to be displayed above the main panel, along side the main panel
     /// name. Function called by the Amadeus application.
-    pub fn view_actions(&self, show: &Show) -> Element<'_, Request> {
-        match show {
+    pub fn view_actions(&self) -> Element<'_, Request> {
+        match self.show {
             Show::Queue => self.queue.view_actions().map(Request::from),
             Show::History => self.history.view_actions().map(Request::from),
             Show::Database => self.search.view_actions().map(Request::from),
-            Show::Playlist(plt) => self.playlists.view_actions(plt).map(Request::from),
+            Show::Playlist(ref plt) => self.playlists.view_actions(plt).map(Request::from),
         }
     }
 
     /// Render the state of the component.
-    pub fn view(&self, show: &Show) -> Element<'_, Request> {
-        match show {
+    pub fn view(&self) -> Element<'_, Request> {
+        match self.show {
             Show::Queue => self.queue.view().map(Request::from),
             Show::History => self.history.view().map(Request::from),
             Show::Database => self.search.view().map(Request::from),
-            Show::Playlist(plt) => self.playlists.view(plt).map(Request::from),
+            Show::Playlist(ref plt) => self.playlists.view(plt).map(Request::from),
         }
     }
 }
diff --git a/amadeus/src/components/mainpanel/playlists.rs b/amadeus/src/components/mainpanel/playlists.rs
index 5a5956e9..9b11ea3c 100644
--- a/amadeus/src/components/mainpanel/playlists.rs
+++ b/amadeus/src/components/mainpanel/playlists.rs
@@ -6,7 +6,10 @@ use lektor_utils::log;
 use std::sync::Arc;
 
 #[derive(Default)]
-pub struct State(HashMap<Arc<str>, (PlaylistInfo, karalist::State)>);
+pub struct State {
+    playlists: HashMap<Arc<str>, (PlaylistInfo, karalist::State)>,
+    to_show: Option<Arc<str>>,
+}
 
 #[derive(Debug, Clone)]
 pub enum Message {
@@ -22,6 +25,8 @@ pub enum Message {
     RemoveKaraFromPlaylist(Arc<str>, KId),
 
     AddKaraToPlaylist(Arc<str>, Arc<Kara>),
+
+    ShowPlaylist(Arc<str>),
 }
 
 #[derive(Debug, Clone)]
@@ -45,27 +50,26 @@ pub enum Request {
 impl State {
     pub fn update(&mut self, message: Message) -> Command<Request> {
         match message {
-            // Update a playlist
             Message::KeepPlaylists(plts) => {
-                self.0.retain(|name, _| plts.contains(name));
+                self.playlists.retain(|name, _| plts.contains(name));
                 Command::none()
             }
             Message::Reload(plt, karas) => {
-                match self.0.get_mut(&plt) {
+                match self.playlists.get_mut(&plt) {
                     Some((_, plt)) => plt.update(karalist::Message::Reload(karas)),
                     None => log::error!("failed to update playlist {}", plt.as_ref()),
                 }
                 Command::none()
             }
             Message::UpdatePlaylistInfos(plt, infos) => {
-                match self.0.get_mut(&plt) {
+                match self.playlists.get_mut(&plt) {
                     Some((old, _)) => *old = infos,
                     None => log::error!("failed to update playlist {}", plt.as_ref()),
                 }
                 Command::none()
             }
             Message::RemoveKaraFromPlaylist(plt, id) => {
-                match self.0.get_mut(&plt) {
+                match self.playlists.get_mut(&plt) {
                     Some((_, plt)) => plt.update(karalist::Message::RemoveId(id)),
                     None => log::error!(
                         "failed to delete kara {id:?} from playlist {}",
@@ -75,18 +79,23 @@ impl State {
                 Command::none()
             }
             Message::DeletePlaylist(plt) => {
-                if self.0.remove(&plt).is_none() {
+                if self.playlists.remove(&plt).is_none() {
                     log::error!("failed do delete playlist {}", plt.as_ref())
                 }
                 Command::none()
             }
             Message::AddKaraToPlaylist(plt, kara) => {
-                match self.0.get_mut(&plt) {
+                match self.playlists.get_mut(&plt) {
                     Some(plt) => plt.1.update(karalist::Message::Add(kara)),
                     None => log::error!("can't add kara {} to playlist {}", kara.id, plt.as_ref()),
                 }
                 Command::none()
             }
+
+            Message::ShowPlaylist(name) => {
+                self.to_show = Some(name);
+                Command::none()
+            }
         }
     }
 
@@ -98,7 +107,7 @@ impl State {
     }
 
     pub fn view(&self, plt: &Arc<str>) -> Element<'_, Request> {
-        self.0
+        self.playlists
             .get_key_value(plt)
             .map(|(plt, (_, content))| content.view().map(|req| Request::Inner(plt.clone(), req)))
             .unwrap_or(components::loading())
-- 
GitLab