Skip to content

Commit

Permalink
refactor: use single instance
Browse files Browse the repository at this point in the history
  • Loading branch information
wash2 committed Nov 20, 2023
1 parent 99ff272 commit e44eafa
Show file tree
Hide file tree
Showing 8 changed files with 485 additions and 362 deletions.
532 changes: 344 additions & 188 deletions Cargo.lock

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ authors = ["Ashley Wulber <ashley@system76.com>"]
edition = "2021"

[dependencies]
libcosmic = { git = "https://github.com/pop-os/libcosmic/", default-features = false, features = ["wayland", "tokio"] }
# libcosmic = { path = "../libcosmic", default-features = false, features = ["wayland", "tokio"] }
# libcosmic = { git = "https://github.com/pop-os/libcosmic/", default-features = false, features = ["wayland", "tokio"] }
libcosmic = { path = "../libcosmic", default-features = false, features = ["wayland", "tokio", "single-instance"] }
tokio = { version = "1.17.0", features = ["sync", "rt", "process"] }
pretty_env_logger = "0.5"
log = "0.4"
Expand All @@ -30,6 +30,6 @@ freedesktop-icons = "0.2.4"
current_locale = "0.1.1"
url = "2.4"
nix = "0.26"

clap = { version = "4.4.8", features = ["derive"] }
[profile.release]
lto = "thin"
207 changes: 131 additions & 76 deletions src/app.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use std::fmt::Debug;

use std::str::FromStr;
use std::sync::Arc;

use cosmic::app::{Command, Core, Settings};
use cosmic::cosmic_config::{Config, ConfigSet, CosmicConfigEntry};
use clap::{Parser, Subcommand};
use cosmic::app::{Command, Core, CosmicFlags, DbusActivationDetails, Settings};
use cosmic::cosmic_config::{Config, CosmicConfigEntry};
use cosmic::cosmic_theme::Spacing;
use cosmic::iced::id::Id;
use cosmic::iced::subscription::events_with;
Expand Down Expand Up @@ -31,17 +33,17 @@ use cosmic::theme::{self, Button, TextInput};
use cosmic::widget::button::StyleSheet as ButtonStyleSheet;
use cosmic::widget::icon::{from_name, from_path};
use cosmic::widget::{button, icon, search_input, text_input, tooltip, Column};
use cosmic::{iced, sctk, Element, Theme};
use cosmic::{cctk::sctk, iced, Element, Theme};
use iced::wayland::actions::layer_surface::IcedMargin;

use itertools::Itertools;
use log::error;
use once_cell::sync::Lazy;
use ron::error::SpannedError;
use serde::{Deserialize, Serialize};

use crate::app_group::{AppLibraryConfig, DesktopEntryData};
use crate::fl;
use crate::subscriptions::desktop_files::desktop_files;
use crate::subscriptions::toggle_dbus::dbus_toggle;
use crate::widgets::application::ApplicationButton;
use crate::widgets::group::GroupButton;

Expand All @@ -67,8 +69,53 @@ const DELETE_GROUP_WINDOW_ID: SurfaceId = SurfaceId(3);
pub(crate) const DND_ICON_ID: SurfaceId = SurfaceId(4);
pub(crate) const MENU_ID: SurfaceId = SurfaceId(5);

#[derive(Parser, Debug, Serialize, Deserialize, Clone)]
#[command(author, version, about, long_about = None)]
#[command(propagate_version = true)]
pub struct Args {
#[command(subcommand)]
subcommand: Option<LauncherCommands>,
}

#[derive(Subcommand, Debug, Serialize, Deserialize, Clone)]
pub enum LauncherCommands {
/// Open the launcher
Open,
/// Close the launcher
Close,
}

impl FromStr for LauncherCommands {
type Err = SpannedError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
ron::de::from_str(s)
}
}

impl ToString for LauncherCommands {
fn to_string(&self) -> String {
ron::ser::to_string(self).unwrap()
}
}

impl CosmicFlags for Args {
type SubCommand = LauncherCommands;
type Args = Vec<String>;

fn action(&self) -> Option<&LauncherCommands> {
self.subcommand.as_ref()
}
}

impl From<DbusActivationDetails<LauncherCommands, Vec<String>>> for Message {
fn from(msg: DbusActivationDetails<LauncherCommands, Vec<String>>) -> Self {
Message::DbusActivation(msg)
}
}

pub fn run() -> cosmic::iced::Result {
cosmic::app::run::<CosmicAppLibrary>(
cosmic::app::run_single_instance::<CosmicAppLibrary>(
Settings::default()
.antialiasing(true)
.client_decorations(true)
Expand All @@ -78,9 +125,8 @@ pub fn run() -> cosmic::iced::Result {
.scale_factor(1.0)
.no_main_window(true)
.exit_on_close(false),
(),
)?;
Ok(())
Args::parse(),
)
}

#[derive(Default)]
Expand All @@ -106,7 +152,6 @@ struct CosmicAppLibrary {
enum Message {
InputChanged(String),
Layer(LayerEvent),
Toggle,
Hide,
Clear,
ActivateApp(usize),
Expand All @@ -133,8 +178,9 @@ enum Message {
StartDndOffer(usize),
FinishDndOffer(usize, DesktopEntryData),
LeaveDndOffer,
Ignore,
ScrollYOffset(f32),
DbusActivation(DbusActivationDetails<LauncherCommands, Vec<String>>),
Ignore,
}

#[derive(Clone)]
Expand All @@ -159,12 +205,30 @@ impl CosmicAppLibrary {
.filtered(self.cur_group, self.locale.as_deref(), &self.search_value);
self.entry_path_input.sort_by(|a, b| a.name.cmp(&b.name));
}

pub fn hide(&mut self) -> Command<Message> {
self.active_surface = false;
self.new_group = None;
self.search_value.clear();
self.edit_name = None;
self.cur_group = 0;
self.group_to_delete = None;
self.load_apps();
iced::Command::batch(vec![
text_input::focus(SEARCH_ID.clone()),
destroy_layer_surface(NEW_GROUP_WINDOW_ID),
destroy_layer_surface(DELETE_GROUP_WINDOW_ID),
destroy_layer_surface(WINDOW_ID),
cancel_dnd(),
iced::Command::perform(async {}, |_| cosmic::app::Message::App(Message::Clear)),
])
}
}

impl cosmic::Application for CosmicAppLibrary {
type Message = Message;
type Executor = executor::Default;
type Flags = ();
type Flags = Args;
const APP_ID: &'static str = "com.system76.CosmicAppLibrary";

fn core(&self) -> &Core {
Expand Down Expand Up @@ -202,18 +266,7 @@ impl cosmic::Application for CosmicAppLibrary {
return commands::popup::destroy_popup(MENU_ID);
}
if self.active_surface {
self.active_surface = false;
self.edit_name = None;
self.new_group = None;
return iced::Command::batch(vec![
destroy_layer_surface(NEW_GROUP_WINDOW_ID),
destroy_layer_surface(DELETE_GROUP_WINDOW_ID),
destroy_layer_surface(WINDOW_ID),
cancel_dnd(),
iced::Command::perform(async {}, |_| {
cosmic::app::Message::App(Message::Clear)
}),
]);
return self.hide();
}
}
Message::Clear => {
Expand Down Expand Up @@ -244,7 +297,7 @@ impl cosmic::Application for CosmicAppLibrary {
};
for arg in exec {
// TODO handle "%" args here if necessary?
if !arg.starts_with("%") {
if !arg.starts_with('%') {
cmd.arg(arg);
}
}
Expand All @@ -264,44 +317,9 @@ impl cosmic::Application for CosmicAppLibrary {
self.scroll_offset = 0.0;
self.load_apps();
}
Message::Toggle => {
if self.active_surface {
self.active_surface = false;
self.new_group = None;
return Command::batch(vec![
destroy_layer_surface(NEW_GROUP_WINDOW_ID),
destroy_layer_surface(DELETE_GROUP_WINDOW_ID),
destroy_layer_surface(WINDOW_ID),
]);
} else {
let mut cmds = Vec::new();
self.edit_name = None;
self.search_value = "".to_string();
self.active_surface = true;
self.scroll_offset = 0.0;
self.cur_group = 0;
cmds.push(text_input::focus(SEARCH_ID.clone()));
cmds.push(get_layer_surface(SctkLayerSurfaceSettings {
id: WINDOW_ID,
keyboard_interactivity: KeyboardInteractivity::Exclusive,
anchor: Anchor::TOP,
namespace: "app-library".into(),
size: None,
margin: IcedMargin {
top: 16,
right: 0,
bottom: 0,
left: 0,
},
..Default::default()
}));
return Command::batch(cmds);
}
}
Message::LoadApps => {
self.load_apps();
}
Message::Ignore => {}
Message::Delete(group) => {
self.group_to_delete = Some(group);
return get_layer_surface(SctkLayerSurfaceSettings {
Expand Down Expand Up @@ -363,9 +381,9 @@ impl cosmic::Application for CosmicAppLibrary {
return destroy_layer_surface(NEW_GROUP_WINDOW_ID);
}
Message::OpenContextMenu(rect, i) => {
if let Some(i) = self.menu.take() {
if i == i {
return commands::popup::destroy_popup(MENU_ID.clone());
if let Some(cur_i) = self.menu.take() {
if i == cur_i {
return commands::popup::destroy_popup(MENU_ID);
}
} else {
self.menu = Some(i);
Expand Down Expand Up @@ -394,7 +412,7 @@ impl cosmic::Application for CosmicAppLibrary {
}
Message::CloseContextMenu => {
self.menu = None;
return commands::popup::destroy_popup(MENU_ID.clone());
return commands::popup::destroy_popup(MENU_ID);
}
Message::SelectAction(action) => {
if let Some(info) = self.menu.take().and_then(|i| self.entry_path_input.get(i)) {
Expand All @@ -412,20 +430,20 @@ impl cosmic::Application for CosmicAppLibrary {
let mut exec = shlex::Shlex::new(&exec);

let mut cmd = match exec.next() {
Some(cmd) if !cmd.contains("=") => {
Some(cmd) if !cmd.contains('=') => {
tokio::process::Command::new(cmd)
}
_ => return Command::none(),
};
for arg in exec {
// TODO handle "%" args here if necessary?
if !arg.starts_with("%") {
if !arg.starts_with('%') {
cmd.arg(arg);
}
}
let _ = cmd.spawn();
return iced::Command::batch(vec![
commands::popup::destroy_popup(MENU_ID.clone()),
commands::popup::destroy_popup(MENU_ID),
iced::Command::perform(async {}, |_| {
cosmic::app::Message::App(Message::Hide)
}),
Expand All @@ -435,7 +453,6 @@ impl cosmic::Application for CosmicAppLibrary {
}
}
Message::StartDrag(i) => {
// self.dnd_icon = self.entry_path_input.get(i).map(|e| e.icon.clone());
self.dnd_icon = Some(i);
}
Message::FinishDrag(copy) => {
Expand All @@ -445,7 +462,7 @@ impl cosmic::Application for CosmicAppLibrary {
.take()
.and_then(|i| self.entry_path_input.get(i))
{
let _ = self.config.remove_entry(self.cur_group, &info.id);
self.config.remove_entry(self.cur_group, &info.id);
if let Some(helper) = self.helper.as_ref() {
if let Err(err) = self.config.write_entry(helper) {
error!("{:?}", err);
Expand Down Expand Up @@ -502,6 +519,49 @@ impl cosmic::Application for CosmicAppLibrary {
self.group_to_delete = None;
return destroy_layer_surface(DELETE_GROUP_WINDOW_ID);
}
Message::DbusActivation(details) => match details {
DbusActivationDetails::ActivateAction {
action: LauncherCommands::Open,
args: _,
}
| DbusActivationDetails::Activate
if !self.active_surface =>
{
self.edit_name = None;
self.search_value = "".to_string();
self.active_surface = true;
self.scroll_offset = 0.0;
self.cur_group = 0;
return Command::batch(vec![
text_input::focus(SEARCH_ID.clone()),
get_layer_surface(SctkLayerSurfaceSettings {
id: WINDOW_ID,
keyboard_interactivity: KeyboardInteractivity::Exclusive,
anchor: Anchor::TOP,
namespace: "app-library".into(),
size: None,
margin: IcedMargin {
top: 16,
right: 0,
bottom: 0,
left: 0,
},
..Default::default()
}),
]);
}
DbusActivationDetails::ActivateAction {
action: LauncherCommands::Close,
args: _,
}
| DbusActivationDetails::Activate
if self.active_surface =>
{
return self.hide();
}
_ => {}
},
Message::Ignore => {}
}
Command::none()
}
Expand All @@ -516,7 +576,6 @@ impl cosmic::Application for CosmicAppLibrary {
if id == DND_ICON_ID {
let Some(icon_path) = self
.dnd_icon
.clone()
.and_then(|i| self.entry_path_input.get(i).map(|e| e.icon.clone()))
else {
return container(horizontal_space(Length::Fixed(1.0)))
Expand Down Expand Up @@ -1047,19 +1106,15 @@ impl cosmic::Application for CosmicAppLibrary {
fn subscription(&self) -> Subscription<Message> {
Subscription::batch(
vec![
dbus_toggle(0).map(|_| Message::Toggle),
desktop_files(0).map(|_| Message::LoadApps),
events_with(|e, _status| match e {
cosmic::iced::Event::PlatformSpecific(PlatformSpecific::Wayland(
wayland::Event::Layer(e, ..),
)) => Some(Message::Layer(e)),
cosmic::iced::Event::Keyboard(cosmic::iced::keyboard::Event::KeyReleased {
key_code,
key_code: KeyCode::Escape,
modifiers: _mods,
}) => match key_code {
KeyCode::Escape => Some(Message::Hide),
_ => None,
},
}) => Some(Message::Hide),
_ => None,
}),
]
Expand Down
Loading

0 comments on commit e44eafa

Please sign in to comment.