use libquassel_derive::sync; use libquassel_derive::{NetworkList, NetworkMap}; #[allow(unused_imports)] use crate::message::StatefulSyncableClient; #[allow(unused_imports)] use crate::message::StatefulSyncableServer; use crate::message::{Class, Syncable}; use crate::primitive::{BufferId, NetworkId, VariantList}; #[derive(Debug, Default, Clone, PartialEq, NetworkList, NetworkMap)] pub struct BufferViewConfig { #[network(rename = "BufferList", network = "list", variant = "VariantList")] pub buffers: Vec, #[network(rename = "RemovedBuffers", network = "list", variant = "VariantList")] pub removed_buffers: Vec, #[network(rename = "TemporarilyRemovedBuffers", network = "list", variant = "VariantList")] pub temporarily_removed_buffers: Vec, #[network(rename = "bufferViewId", default, skip)] pub buffer_view_id: i32, #[network(rename = "bufferViewName")] pub buffer_view_name: String, #[network(rename = "networkId")] pub network_id: NetworkId, #[network(rename = "addNewBuffersAutomatically")] pub add_new_buffers_automatically: bool, #[network(rename = "sortAlphabetically")] pub sort_alphabetically: bool, #[network(rename = "hideInactiveBuffers")] pub hide_inactive_buffers: bool, #[network(rename = "hideInactiveNetworks")] pub hide_inactive_networks: bool, #[network(rename = "disableDecoration")] pub disable_decoration: bool, // TODO use bitflags for buffertypes #[network(rename = "allowedBufferTypes")] pub allowed_buffer_types: i32, #[network(rename = "minimumActivity")] pub minimum_activity: i32, #[network(rename = "showSearch")] pub show_search: bool, } #[allow(dead_code)] impl BufferViewConfig { pub fn request_add_buffer(&self, id: BufferId, pos: usize) { sync!("requestAddBuffer", [id, (pos as i32)]); } pub fn add_buffer(&mut self, id: BufferId, pos: usize) { if !self.buffers.contains(&id) { self.buffers.insert(pos, id) } if let Some(old_pos) = self.removed_buffers.iter().position(|&x| x == id) { self.removed_buffers.remove(old_pos); } if let Some(old_pos) = self.temporarily_removed_buffers.iter().position(|&x| x == id) { self.temporarily_removed_buffers.remove(old_pos); } #[cfg(feature = "server")] sync!("addBuffer", [id, (pos as i32)]); } pub fn request_move_buffer(&self, id: BufferId, pos: usize) { sync!("requestMoveBuffer", [id, (pos as i32)]); } pub fn move_buffer(&mut self, id: BufferId, pos: usize) { let old_pos = self.buffers.iter().position(|&x| x == id).unwrap(); self.buffers.remove(old_pos); self.buffers.insert(pos, id); #[cfg(feature = "server")] sync!("moveBuffer", [id, (pos as i32)]); } pub fn request_remove_buffer(&mut self, id: BufferId) { sync!("requestRemoveBuffer", [id]); } pub fn remove_buffer(&mut self, id: BufferId) { if let Some(old_pos) = self.buffers.iter().position(|&x| x == id) { self.buffers.remove(old_pos); } if let Some(old_pos) = self.removed_buffers.iter().position(|&x| x == id) { self.removed_buffers.remove(old_pos); } if !self.temporarily_removed_buffers.contains(&id) { self.temporarily_removed_buffers.push(id) } #[cfg(feature = "server")] sync!("removeBuffer", [id]); } pub fn request_remove_buffer_permanently(&mut self, id: BufferId) { sync!("requestRemoveBufferPermanently", [id]); } pub fn remove_buffer_permanently(&mut self, id: BufferId) { if let Some(old_pos) = self.buffers.iter().position(|&x| x == id) { self.buffers.remove(old_pos); } if let Some(old_pos) = self.temporarily_removed_buffers.iter().position(|&x| x == id) { self.temporarily_removed_buffers.remove(old_pos); } if !self.removed_buffers.contains(&id) { self.removed_buffers.push(id) } #[cfg(feature = "server")] sync!("removeBufferPermanently", [id]); } } #[cfg(feature = "client")] impl StatefulSyncableClient for BufferViewConfig { fn sync_custom(&mut self, mut msg: crate::message::SyncMessage) where Self: Sized, { log::debug!("entering bufferviewconfig sync_custom()"); match msg.slot_name.as_str() { "addBuffer" => self.add_buffer( msg.params.remove(0).try_into().unwrap(), i32::try_from(msg.params.remove(0)).unwrap() as usize, ), "moveBuffer" => self.move_buffer( msg.params.remove(0).try_into().unwrap(), i32::try_from(msg.params.remove(0)).unwrap() as usize, ), "removeBuffer" => self.remove_buffer(msg.params.remove(0).try_into().unwrap()), "removeBufferPermanently" => { self.remove_buffer_permanently(msg.params.remove(0).try_into().unwrap()) } _ => (), } } } #[cfg(feature = "server")] impl StatefulSyncableServer for BufferViewConfig { fn sync_custom(&mut self, mut msg: crate::message::SyncMessage) where Self: Sized, { match msg.slot_name.as_str() { "requestAddBuffer" => self.add_buffer( msg.params.remove(0).try_into().unwrap(), i32::try_from(msg.params.remove(0)).unwrap() as usize, ), "requestMoveBuffer" => self.move_buffer( msg.params.remove(0).try_into().unwrap(), i32::try_from(msg.params.remove(0)).unwrap() as usize, ), "requestRemoveBuffer" => self.remove_buffer(msg.params.remove(0).try_into().unwrap()), "requestRemoveBufferPermanently" => { self.remove_buffer_permanently(msg.params.remove(0).try_into().unwrap()) } "setAddNewBuffersAutomatically" => { self.add_new_buffers_automatically = msg.params.remove(0).try_into().unwrap() } "setAllowedBufferTypes" => self.allowed_buffer_types = msg.params.remove(0).try_into().unwrap(), "setBufferViewName" => self.buffer_view_name = msg.params.remove(0).try_into().unwrap(), "setDisableDecoration" => self.disable_decoration = msg.params.remove(0).try_into().unwrap(), "setHideInactiveBuffers" => self.hide_inactive_buffers = msg.params.remove(0).try_into().unwrap(), "setHideInactiveNetworks" => { self.hide_inactive_networks = msg.params.remove(0).try_into().unwrap() } "setMinimumActivity" => self.minimum_activity = msg.params.remove(0).try_into().unwrap(), "setNetworkId" => self.network_id = msg.params.remove(0).try_into().unwrap(), "setShowSearch" => self.show_search = msg.params.remove(0).try_into().unwrap(), "setSortAlphabetically" => self.sort_alphabetically = msg.params.remove(0).try_into().unwrap(), _ => (), } } } impl Syncable for BufferViewConfig { const CLASS: Class = Class::BufferViewConfig; fn send_sync(&self, function: &str, params: VariantList) { crate::message::signalproxy::SYNC_PROXY.get().unwrap().sync( Self::CLASS, Some(&self.buffer_view_id.to_string()), function, params, ); } } #[cfg(test)] mod tests { use super::*; fn bufferviewconfig_sample() -> BufferViewConfig { BufferViewConfig { buffers: vec![1.into(), 2.into(), 3.into()], removed_buffers: vec![4.into(), 5.into()], temporarily_removed_buffers: vec![6.into(), 7.into()], ..Default::default() } } #[test] fn bufferviewconfig_add_buffer() { // Add existing buffer, no change let mut buffer_view_config = bufferviewconfig_sample(); buffer_view_config.add_buffer(1.into(), 2); assert_eq!(bufferviewconfig_sample(), buffer_view_config); // Add new buffer let mut buffer_view_config = bufferviewconfig_sample(); buffer_view_config.add_buffer(10.into(), 1); assert_eq!( BufferViewConfig { buffers: vec![1.into(), 10.into(), 2.into(), 3.into()], removed_buffers: vec![4.into(), 5.into()], temporarily_removed_buffers: vec![6.into(), 7.into()], ..Default::default() }, buffer_view_config ); // Add new buffer, remove from removed buffers let mut buffer_view_config = BufferViewConfig { buffers: vec![1.into(), 2.into(), 3.into()], removed_buffers: vec![4.into(), 5.into(), 10.into()], temporarily_removed_buffers: vec![6.into(), 7.into(), 10.into()], ..Default::default() }; buffer_view_config.add_buffer(10.into(), 1); assert_eq!( BufferViewConfig { buffers: vec![1.into(), 10.into(), 2.into(), 3.into()], removed_buffers: vec![4.into(), 5.into()], temporarily_removed_buffers: vec![6.into(), 7.into()], ..Default::default() }, buffer_view_config ); } #[test] fn bufferviewconfig_remove_buffer() { // Remove already removed buffer let mut buffer_view_config = bufferviewconfig_sample(); buffer_view_config.remove_buffer(6.into()); assert_eq!(bufferviewconfig_sample(), buffer_view_config); // Remove buffer let mut buffer_view_config = bufferviewconfig_sample(); buffer_view_config.remove_buffer(1.into()); assert_eq!( BufferViewConfig { buffers: vec![2.into(), 3.into()], removed_buffers: vec![4.into(), 5.into()], temporarily_removed_buffers: vec![6.into(), 7.into(), 1.into()], ..Default::default() }, buffer_view_config ); } #[test] fn bufferviewconfig_remove_buffer_permanently() { // Remove already removed buffer let mut buffer_view_config = bufferviewconfig_sample(); buffer_view_config.remove_buffer_permanently(4.into()); assert_eq!(bufferviewconfig_sample(), buffer_view_config); // Remove buffer let mut buffer_view_config = bufferviewconfig_sample(); buffer_view_config.remove_buffer_permanently(1.into()); assert_eq!( BufferViewConfig { buffers: vec![2.into(), 3.into()], removed_buffers: vec![4.into(), 5.into(), 1.into()], temporarily_removed_buffers: vec![6.into(), 7.into()], ..Default::default() }, buffer_view_config ); } #[test] fn bufferviewconfig_move_buffer() { // Do nothing let mut buffer_view_config = bufferviewconfig_sample(); buffer_view_config.move_buffer(1.into(), 0); assert_eq!(bufferviewconfig_sample(), buffer_view_config); // Move buffer let mut buffer_view_config = bufferviewconfig_sample(); buffer_view_config.move_buffer(1.into(), 1); assert_eq!( BufferViewConfig { buffers: vec![2.into(), 1.into(), 3.into()], removed_buffers: vec![4.into(), 5.into()], temporarily_removed_buffers: vec![6.into(), 7.into()], ..Default::default() }, buffer_view_config ); } }