feat: use message dialog to display message

This commit is contained in:
b1n
2024-06-29 01:01:42 +08:00
parent 9ed415ee2c
commit f6cf55b698
5 changed files with 230 additions and 176 deletions

2
Cargo.lock generated
View File

@@ -2488,7 +2488,7 @@ checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58"
[[package]] [[package]]
name = "pumpbin" name = "pumpbin"
version = "0.2.1" version = "0.3.0"
dependencies = [ dependencies = [
"aes-gcm", "aes-gcm",
"anyhow", "anyhow",

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "pumpbin" name = "pumpbin"
version = "0.2.1" version = "0.3.0"
authors = ["b1n <b1n@b1n.io>"] authors = ["b1n <b1n@b1n.io>"]
edition = "2021" edition = "2021"
description = "PumpBin is an Implant Generation Platform." description = "PumpBin is an Implant Generation Platform."

View File

@@ -1,6 +1,6 @@
#![windows_subsystem = "windows"] #![windows_subsystem = "windows"]
use std::{fs, path::PathBuf, time::Duration, usize}; use std::{fs, path::PathBuf, usize};
use dirs::{desktop_dir, home_dir}; use dirs::{desktop_dir, home_dir};
use iced::{ use iced::{
@@ -13,14 +13,15 @@ use iced::{
Alignment, Length, Renderer, Task, Theme, Alignment, Length, Renderer, Task, Theme,
}; };
use pumpbin::{ use pumpbin::{
error_dialog,
plugin::{Bins, Plugin}, plugin::{Bins, Plugin},
svg_style, ShellcodeSaveType, FONT, settings, svg_style, ShellcodeSaveType, JETBRAINS_MONO_FONT,
}; };
use pumpbin::{ use pumpbin::{
plugin::{EncryptType, Platforms}, plugin::{EncryptType, Platforms},
Pumpbin, show_message,
}; };
use rfd::AsyncFileDialog; use rfd::{AsyncFileDialog, MessageLevel};
#[derive(Debug)] #[derive(Debug)]
struct Maker { struct Maker {
@@ -39,7 +40,7 @@ struct Maker {
darwin_exe: String, darwin_exe: String,
darwin_lib: String, darwin_lib: String,
desc: text_editor::Content, desc: text_editor::Content,
message: String, pumpbin_version: String,
selected_theme: Theme, selected_theme: Theme,
} }
@@ -61,21 +62,13 @@ impl Default for Maker {
darwin_exe: Default::default(), darwin_exe: Default::default(),
darwin_lib: Default::default(), darwin_lib: Default::default(),
desc: text_editor::Content::new(), desc: text_editor::Content::new(),
message: "Welcom to PumpBin Maker.".to_string(), pumpbin_version: env!("CARGO_PKG_VERSION").into(),
selected_theme: Theme::CatppuccinMacchiato, selected_theme: Theme::CatppuccinMacchiato,
} }
} }
} }
impl Maker { impl Maker {
fn show_message(&mut self, message: String) -> Task<MakerMessage> {
self.message = message;
let wait = async {
tokio::time::sleep(Duration::from_secs(3)).await;
};
Task::perform(wait, MakerMessage::ClearMessage)
}
fn plugin_name(&self) -> &str { fn plugin_name(&self) -> &str {
&self.plugin_name &self.plugin_name
} }
@@ -147,6 +140,10 @@ impl Maker {
fn selected_theme(&self) -> Theme { fn selected_theme(&self) -> Theme {
self.selected_theme.clone() self.selected_theme.clone()
} }
fn pumpbin_version(&self) -> &str {
&self.pumpbin_version
}
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
@@ -191,7 +188,6 @@ enum MakerMessage {
B1nClicked, B1nClicked,
GithubClicked, GithubClicked,
ThemeChanged(Theme), ThemeChanged(Theme),
ClearMessage(()),
} }
impl Application for Maker { impl Application for Maker {
@@ -292,39 +288,50 @@ impl Application for Maker {
} }
MakerMessage::GenerateClicked => { MakerMessage::GenerateClicked => {
if self.plugin_name().is_empty() { if self.plugin_name().is_empty() {
return self.show_message("Plugin Name is empty.".to_string()); show_message("Plugin Name is empty.".to_string(), MessageLevel::Error);
return Task::none();
} }
if self.prefix().is_empty() { if self.prefix().is_empty() {
return self.show_message("Prefix is empty.".to_string()); show_message("Prefix is empty.".to_string(), MessageLevel::Error);
return Task::none();
}
if self.max_len().is_empty() {
show_message("MaxLen is empty.".to_string(), MessageLevel::Error);
return Task::none();
}
let max_len;
if let Ok(max) = self.max_len().parse::<usize>() {
max_len = max;
} else {
show_message("MaxLen numeric only.".to_string(), MessageLevel::Error);
return Task::none();
} }
if let ShellcodeSaveType::Local = self.shellcode_save_type() { if let ShellcodeSaveType::Local = self.shellcode_save_type() {
if self.size_holder().is_empty() { if self.size_holder().is_empty() {
return self.show_message("Size Holder is empty.".to_string()); show_message("Size Holder is empty.".to_string(), MessageLevel::Error);
return Task::none();
} }
} }
let max_len;
if let Ok(max) = self.max_len().parse::<usize>() {
max_len = max;
} else {
return self.show_message("MaxLen numeric only.".to_string());
}
match self.encrypt_type() { match self.encrypt_type() {
EncryptType::None => (), EncryptType::None => (),
EncryptType::Xor(x) => { EncryptType::Xor(x) => {
if x.is_empty() { if x.is_empty() {
return self.show_message("Xor Pass is empty.".to_string()); show_message("Xor Pass is empty.".to_string(), MessageLevel::Error);
return Task::none();
} }
} }
EncryptType::AesGcm(x) => { EncryptType::AesGcm(x) => {
if x.key_holder().is_empty() { if x.key_holder().is_empty() {
return self.show_message("AesGcm Key is empty.".to_string()); show_message("AesGcm Key is empty.".to_string(), MessageLevel::Error);
return Task::none();
} else if x.nonce_holder().is_empty() { } else if x.nonce_holder().is_empty() {
return self.show_message("AesGcm Nonce is empty.".to_string()); show_message("AesGcm Nonce is empty.".to_string(), MessageLevel::Error);
return Task::none();
} }
} }
} }
@@ -440,10 +447,13 @@ impl Application for Maker {
Task::perform(make_plugin, MakerMessage::GenerateDone) Task::perform(make_plugin, MakerMessage::GenerateDone)
} }
MakerMessage::GenerateDone(x) => self.show_message(match x { MakerMessage::GenerateDone(x) => {
Ok(_) => "Generate done.".to_string(), match x {
Err(e) => e, Ok(_) => show_message("Generate done.".to_string(), MessageLevel::Info),
}), Err(e) => show_message(e, MessageLevel::Error),
};
Task::none()
}
MakerMessage::ChooseFileClicked(x) => { MakerMessage::ChooseFileClicked(x) => {
let choose_file = async move { let choose_file = async move {
AsyncFileDialog::new() AsyncFileDialog::new()
@@ -468,56 +478,56 @@ impl Application for Maker {
) )
} }
MakerMessage::WindowsExeChooseDone(x) => { MakerMessage::WindowsExeChooseDone(x) => {
match x { if let Ok(path) = x {
Ok(x) => self.windows_exe = x, self.windows_exe = path;
Err(x) => return self.show_message(x),
} }
Task::none() Task::none()
} }
MakerMessage::WindowsLibChooseDone(x) => { MakerMessage::WindowsLibChooseDone(x) => {
match x { if let Ok(path) = x {
Ok(x) => self.windows_lib = x, self.windows_lib = path;
Err(x) => return self.show_message(x),
} }
Task::none() Task::none()
} }
MakerMessage::LinuxExeChooseDone(x) => { MakerMessage::LinuxExeChooseDone(x) => {
match x { if let Ok(path) = x {
Ok(x) => self.linux_exe = x, self.linux_exe = path;
Err(x) => return self.show_message(x),
} }
Task::none() Task::none()
} }
MakerMessage::LinuxLibChooseDone(x) => { MakerMessage::LinuxLibChooseDone(x) => {
match x { if let Ok(path) = x {
Ok(x) => self.linux_lib = x, self.linux_lib = path;
Err(x) => return self.show_message(x),
} }
Task::none() Task::none()
} }
MakerMessage::DarwinExeChooseDone(x) => { MakerMessage::DarwinExeChooseDone(x) => {
match x { if let Ok(path) = x {
Ok(x) => self.darwin_exe = x, self.darwin_exe = path;
Err(x) => return self.show_message(x),
} }
Task::none() Task::none()
} }
MakerMessage::DarwinLibChooseDone(x) => { MakerMessage::DarwinLibChooseDone(x) => {
match x { if let Ok(path) = x {
Ok(x) => self.darwin_lib = x, self.darwin_lib = path;
Err(x) => return self.show_message(x),
} }
Task::none() Task::none()
} }
MakerMessage::B1nClicked => { MakerMessage::B1nClicked => {
if open::that(env!("CARGO_PKG_HOMEPAGE")).is_err() { if open::that(env!("CARGO_PKG_HOMEPAGE")).is_err() {
return self.show_message("Open home failed.".into()); show_message("Open home failed.".into(), MessageLevel::Error);
} }
Task::none() Task::none()
} }
MakerMessage::GithubClicked => { MakerMessage::GithubClicked => {
if open::that(env!("CARGO_PKG_REPOSITORY")).is_err() { if open::that(env!("CARGO_PKG_REPOSITORY")).is_err() {
return self.show_message("Open repo failed.".into()); show_message("Open repo failed.".into(), MessageLevel::Error);
} }
Task::none() Task::none()
} }
@@ -525,10 +535,6 @@ impl Application for Maker {
self.selected_theme = x; self.selected_theme = x;
Task::none() Task::none()
} }
MakerMessage::ClearMessage(_) => {
self.message = "Welcom to PumpBin Maker.".to_string();
Task::none()
}
} }
} }
@@ -544,14 +550,14 @@ impl Application for Maker {
let pick_list_handle = || pick_list::Handle::Dynamic { let pick_list_handle = || pick_list::Handle::Dynamic {
closed: pick_list::Icon { closed: pick_list::Icon {
font: FONT, font: JETBRAINS_MONO_FONT,
code_point: '', code_point: '',
size: None, size: None,
line_height: text::LineHeight::Relative(1.0), line_height: text::LineHeight::Relative(1.0),
shaping: text::Shaping::Basic, shaping: text::Shaping::Basic,
}, },
open: pick_list::Icon { open: pick_list::Icon {
font: FONT, font: JETBRAINS_MONO_FONT,
code_point: '', code_point: '',
size: None, size: None,
line_height: text::LineHeight::Relative(1.0), line_height: text::LineHeight::Relative(1.0),
@@ -724,7 +730,9 @@ impl Application for Maker {
.padding(20) .padding(20)
.spacing(10); .spacing(10);
let message = row![text("").size(25), text(&self.message)].align_items(Alignment::Center); let version = text(format!("PumpBin  v{}", self.pumpbin_version()))
.color(self.theme().extended_palette().primary.base.color);
let b1n = button( let b1n = button(
Svg::new(Handle::from_memory(include_bytes!( Svg::new(Handle::from_memory(include_bytes!(
"../../assets/svg/house-heart-fill.svg" "../../assets/svg/house-heart-fill.svg"
@@ -755,14 +763,14 @@ impl Application for Maker {
let footer = column![ let footer = column![
horizontal_rule(0), horizontal_rule(0),
row![ row![
column![message] column![version]
.width(Length::FillPortion(1)) .width(Length::Fill)
.align_items(Alignment::Start), .align_items(Alignment::Start),
column![row![b1n, github].align_items(Alignment::Center)] column![row![b1n, github].align_items(Alignment::Center)]
.width(Length::Shrink) .width(Length::Shrink)
.align_items(Alignment::Center), .align_items(Alignment::Center),
column![theme_list] column![theme_list]
.width(Length::FillPortion(1)) .width(Length::Fill)
.align_items(Alignment::End) .align_items(Alignment::End)
] ]
.padding([0, 20]) .padding([0, 20])
@@ -778,6 +786,16 @@ impl Application for Maker {
} }
} }
fn main() -> iced::Result { fn main() {
Maker::run(Pumpbin::settings()) match try_main() {
Ok(_) => (),
Err(e) => {
error_dialog(e);
}
}
}
fn try_main() -> anyhow::Result<()> {
Maker::run(settings())?;
Ok(())
} }

View File

@@ -2,7 +2,7 @@ mod button_style;
pub mod plugin; pub mod plugin;
pub mod svg_style; pub mod svg_style;
use std::{fmt::Display, fs, iter, ops::Not, path::PathBuf, time::Duration}; use std::{fmt::Display, fs, iter, ops::Not, path::PathBuf};
use dirs::{desktop_dir, home_dir}; use dirs::{desktop_dir, home_dir};
use iced::{ use iced::{
@@ -19,50 +19,32 @@ use iced::{
use memchr::memmem; use memchr::memmem;
use plugin::{EncryptType, Plugin, Plugins}; use plugin::{EncryptType, Plugin, Plugins};
use rand::RngCore; use rand::RngCore;
use rfd::AsyncFileDialog; use rfd::{
AsyncFileDialog, AsyncMessageDialog, MessageButtons, MessageDialog, MessageDialogResult,
MessageLevel,
};
pub const FONT: Font = Font::with_name("JetBrainsMono NF"); pub const JETBRAINS_MONO_FONT: Font = Font::with_name("JetBrainsMono NF");
#[derive(Debug)] pub fn error_dialog(error: anyhow::Error) {
pub struct Pumpbin { MessageDialog::new()
shellcode_src: String, .set_buttons(MessageButtons::Ok)
shellcode_save_type: ShellcodeSaveType, .set_description(error.to_string())
supported_binary_types: Vec<BinaryType>, .set_level(MessageLevel::Error)
selected_binary_type: Option<BinaryType>, .set_title("PumpBin")
message: String, .show();
supported_platforms: Vec<Platform>,
selected_platform: Option<Platform>,
plugins: Plugins,
selected_plugin: Option<String>,
encrypt_type: EncryptType,
plugin_desc: text_editor::Content,
selected_theme: Theme,
} }
impl Default for Pumpbin { pub fn show_message(message: String, level: MessageLevel) -> Task<MessageDialogResult> {
fn default() -> Self { let dialog = AsyncMessageDialog::new()
Self { .set_buttons(MessageButtons::Ok)
shellcode_src: Default::default(), .set_description(message)
shellcode_save_type: ShellcodeSaveType::Local, .set_level(level)
supported_binary_types: Default::default(), .set_title("PumpBin")
selected_binary_type: None, .show();
message: "Welcome to PumpBin!".into(), Task::future(dialog)
supported_platforms: Default::default(),
selected_platform: None,
plugins: if let Ok(plugins) = Plugins::reade_plugins() {
plugins
} else {
Plugins::default()
},
selected_plugin: None,
encrypt_type: EncryptType::None,
plugin_desc: text_editor::Content::with_text("None"),
selected_theme: Theme::CatppuccinMacchiato,
}
}
} }
impl Pumpbin {
pub fn settings() -> Settings { pub fn settings() -> Settings {
let size = Size::new(1000.0, 600.0); let size = Size::new(1000.0, 600.0);
@@ -88,13 +70,53 @@ impl Pumpbin {
..Default::default() ..Default::default()
}, },
fonts: vec![include_bytes!("../assets/JetBrainsMonoNerdFont-Regular.ttf").into()], fonts: vec![include_bytes!("../assets/JetBrainsMonoNerdFont-Regular.ttf").into()],
default_font: FONT, default_font: JETBRAINS_MONO_FONT,
default_text_size: Pixels(13.0), default_text_size: Pixels(13.0),
antialiasing: true, antialiasing: true,
..Default::default() ..Default::default()
} }
} }
#[derive(Debug)]
pub struct Pumpbin {
shellcode_src: String,
shellcode_save_type: ShellcodeSaveType,
supported_binary_types: Vec<BinaryType>,
selected_binary_type: Option<BinaryType>,
version: String,
supported_platforms: Vec<Platform>,
selected_platform: Option<Platform>,
plugins: Plugins,
selected_plugin: Option<String>,
encrypt_type: EncryptType,
plugin_desc: text_editor::Content,
selected_theme: Theme,
}
impl Default for Pumpbin {
fn default() -> Self {
Self {
shellcode_src: Default::default(),
shellcode_save_type: ShellcodeSaveType::Local,
supported_binary_types: Default::default(),
selected_binary_type: None,
version: env!("CARGO_PKG_VERSION").into(),
supported_platforms: Default::default(),
selected_platform: None,
plugins: if let Ok(plugins) = Plugins::reade_plugins() {
plugins
} else {
Plugins::default()
},
selected_plugin: None,
encrypt_type: EncryptType::None,
plugin_desc: text_editor::Content::with_text("None"),
selected_theme: Theme::CatppuccinMacchiato,
}
}
}
impl Pumpbin {
fn random_encrypt_pass(&mut self) { fn random_encrypt_pass(&mut self) {
match self.encrypt_type() { match self.encrypt_type() {
EncryptType::None => self.encrypt_type = EncryptType::None, EncryptType::None => self.encrypt_type = EncryptType::None,
@@ -112,14 +134,6 @@ impl Pumpbin {
} }
} }
fn show_message(&mut self, message: String) -> Task<Message> {
self.message = message;
let wait = async {
tokio::time::sleep(Duration::from_secs(3)).await;
};
Task::perform(wait, Message::ClearMessage)
}
pub fn shellcode_src(&self) -> &str { pub fn shellcode_src(&self) -> &str {
&self.shellcode_src &self.shellcode_src
} }
@@ -136,8 +150,8 @@ impl Pumpbin {
self.selected_binary_type self.selected_binary_type
} }
pub fn message(&self) -> &str { pub fn version(&self) -> &str {
&self.message &self.version
} }
pub fn supported_platforms(&self) -> &[Platform] { pub fn supported_platforms(&self) -> &[Platform] {
@@ -189,7 +203,6 @@ pub enum Message {
B1nClicked, B1nClicked,
GithubClicked, GithubClicked,
ThemeChanged(Theme), ThemeChanged(Theme),
ClearMessage(()),
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -281,8 +294,6 @@ impl Application for Pumpbin {
Message::ChooseShellcodeDone(x) => { Message::ChooseShellcodeDone(x) => {
if let Some(path) = x { if let Some(path) = x {
self.shellcode_src = path.to_string_lossy().to_string(); self.shellcode_src = path.to_string_lossy().to_string();
} else {
return self.show_message("Canceled shellcode selection.".into());
} }
Task::none() Task::none()
} }
@@ -361,23 +372,28 @@ impl Application for Pumpbin {
Ok(()) Ok(())
}; };
Task::perform(write_encrypted, Message::EncryptShellcodeDone) return Task::perform(write_encrypted, Message::EncryptShellcodeDone);
} else { };
self.show_message("Canceled shellcode selection.".into()) Task::none()
} }
Message::EncryptShellcodeDone(x) => {
match x {
Ok(_) => show_message("Saved encrypted shellcode.".into(), MessageLevel::Info),
Err(e) => show_message(e, MessageLevel::Error),
};
Task::none()
} }
Message::EncryptShellcodeDone(x) => self.show_message(match x {
Ok(_) => "Saved encrypted shellcode.".into(),
Err(e) => e,
}),
Message::GenerateClicked => { Message::GenerateClicked => {
// verify path if local mode // verify path if local mode
let path = PathBuf::from(self.shellcode_src()); let path = PathBuf::from(self.shellcode_src());
if self.shellcode_save_type() == ShellcodeSaveType::Local { if self.shellcode_save_type() == ShellcodeSaveType::Local {
if path.exists().not() { if path.exists().not() {
return self.show_message("Shellcode path not exists.".into()); show_message("Shellcode path not exists.".into(), MessageLevel::Error);
return Task::none();
} else if path.is_file().not() { } else if path.is_file().not() {
return self.show_message("Shellcode path is not a file.".into()); show_message("Shellcode path is not a file.".into(), MessageLevel::Error);
return Task::none();
} }
} }
@@ -547,10 +563,14 @@ impl Application for Pumpbin {
Task::perform(generate, Message::GenerateDone) Task::perform(generate, Message::GenerateDone)
} }
Message::GenerateDone(x) => self.show_message(match x { Message::GenerateDone(x) => {
Ok(_) => "Saved generated binary.".into(), match x {
Err(e) => e, Ok(_) => show_message("Saved generated binary.".into(), MessageLevel::Info),
}), Err(e) => show_message(e, MessageLevel::Error),
};
Task::none()
}
Message::BinaryTypeChanged(x) => { Message::BinaryTypeChanged(x) => {
self.selected_binary_type = Some(x); self.selected_binary_type = Some(x);
Task::none() Task::none()
@@ -602,11 +622,17 @@ impl Application for Pumpbin {
self.update(Message::PluginItemClicked(selected_plugin)); self.update(Message::PluginItemClicked(selected_plugin));
} }
self.plugins = plugins; self.plugins = plugins;
self.show_message(format!("Added {} plugins, {} failed.", success, failed)) show_message(
format!("Added {} plugins, {} failed.", success, failed),
MessageLevel::Info,
);
} }
Err(e) => self.show_message(e), Err(e) => {
show_message(e, MessageLevel::Error);
} }
} }
Task::none()
}
Message::RemovePlugin(x) => { Message::RemovePlugin(x) => {
let mut plugins = self.plugins().clone(); let mut plugins = self.plugins().clone();
@@ -623,7 +649,8 @@ impl Application for Pumpbin {
}; };
Task::perform(remove_plugin, Message::RemovePluginDone) Task::perform(remove_plugin, Message::RemovePluginDone)
} }
Message::RemovePluginDone(x) => match x { Message::RemovePluginDone(x) => {
match x {
Ok((plugin_name, plugins)) => { Ok((plugin_name, plugins)) => {
self.plugins = plugins; self.plugins = plugins;
@@ -641,10 +668,17 @@ impl Application for Pumpbin {
self.selected_plugin = None; self.selected_plugin = None;
self.shellcode_save_type = ShellcodeSaveType::Local; self.shellcode_save_type = ShellcodeSaveType::Local;
} }
self.show_message(format!("Removed plugin {}", plugin_name)) show_message(
format!("Removed plugin {}", plugin_name),
MessageLevel::Info,
);
}
Err(e) => {
show_message(e, MessageLevel::Error);
}
};
Task::none()
} }
Err(e) => self.show_message(e),
},
Message::PluginItemClicked(x) => { Message::PluginItemClicked(x) => {
// unwrap is safe. // unwrap is safe.
// UI implemented strict restrictions. // UI implemented strict restrictions.
@@ -654,9 +688,11 @@ impl Application for Pumpbin {
if plugin.plugin_name() == selected_plugin { if plugin.plugin_name() == selected_plugin {
// random encryption pass // random encryption pass
self.random_encrypt_pass(); self.random_encrypt_pass();
return self.show_message( show_message(
"Generated new random encryption passwords.".to_string(), "Generated new random encryption passwords.".into(),
MessageLevel::Info,
); );
return Task::none();
} }
} }
@@ -704,13 +740,13 @@ impl Application for Pumpbin {
} }
Message::B1nClicked => { Message::B1nClicked => {
if open::that(env!("CARGO_PKG_HOMEPAGE")).is_err() { if open::that(env!("CARGO_PKG_HOMEPAGE")).is_err() {
return self.show_message("Open home failed.".into()); show_message("Open home failed.".into(), MessageLevel::Error);
} }
Task::none() Task::none()
} }
Message::GithubClicked => { Message::GithubClicked => {
if open::that(env!("CARGO_PKG_REPOSITORY")).is_err() { if open::that(env!("CARGO_PKG_REPOSITORY")).is_err() {
return self.show_message("Open repo failed.".into()); show_message("Open repo failed.".into(), MessageLevel::Error);
} }
Task::none() Task::none()
} }
@@ -718,10 +754,6 @@ impl Application for Pumpbin {
self.selected_theme = x; self.selected_theme = x;
Task::none() Task::none()
} }
Message::ClearMessage(_) => {
self.message = "Welcome to PumpBin!".to_string();
Task::none()
}
} }
} }
@@ -739,7 +771,7 @@ impl Application for Pumpbin {
) )
.on_input(Message::ShellcodeSrcChanged) .on_input(Message::ShellcodeSrcChanged)
.icon(text_input::Icon { .icon(text_input::Icon {
font: FONT, font: JETBRAINS_MONO_FONT,
code_point: '󱓞', code_point: '󱓞',
size: None, size: None,
spacing: 12.0, spacing: 12.0,
@@ -759,14 +791,14 @@ impl Application for Pumpbin {
let pick_list_handle = || pick_list::Handle::Dynamic { let pick_list_handle = || pick_list::Handle::Dynamic {
closed: pick_list::Icon { closed: pick_list::Icon {
font: FONT, font: JETBRAINS_MONO_FONT,
code_point: '', code_point: '',
size: None, size: None,
line_height: text::LineHeight::Relative(1.0), line_height: text::LineHeight::Relative(1.0),
shaping: text::Shaping::Basic, shaping: text::Shaping::Basic,
}, },
open: pick_list::Icon { open: pick_list::Icon {
font: FONT, font: JETBRAINS_MONO_FONT,
code_point: '', code_point: '',
size: None, size: None,
line_height: text::LineHeight::Relative(1.0), line_height: text::LineHeight::Relative(1.0),
@@ -1115,13 +1147,8 @@ impl Application for Pumpbin {
.width(Length::Fill) .width(Length::Fill)
.height(Length::Fill); .height(Length::Fill);
let message = row![ let version = text(format!("PumpBin  v{}", self.version()))
text("") .color(self.theme().extended_palette().primary.base.color);
.color(self.theme().extended_palette().primary.base.color)
.size(25),
text(&self.message).color(self.theme().extended_palette().primary.base.color)
]
.align_items(Alignment::Center);
let b1n = button( let b1n = button(
Svg::new(Handle::from_memory(include_bytes!( Svg::new(Handle::from_memory(include_bytes!(
@@ -1153,14 +1180,14 @@ impl Application for Pumpbin {
let footer = column![ let footer = column![
horizontal_rule(0), horizontal_rule(0),
row![ row![
column![message] column![version]
.width(Length::FillPortion(1)) .width(Length::Fill)
.align_items(Alignment::Start), .align_items(Alignment::Start),
column![row![b1n, github].align_items(Alignment::Center)] column![row![b1n, github].align_items(Alignment::Center)]
.width(Length::Shrink) .width(Length::Shrink)
.align_items(Alignment::Center), .align_items(Alignment::Center),
column![theme_list] column![theme_list]
.width(Length::FillPortion(1)) .width(Length::Fill)
.align_items(Alignment::End) .align_items(Alignment::End)
] ]
.padding([0, padding]) .padding([0, padding])

View File

@@ -5,9 +5,18 @@ use std::{fs, ops::Not};
use anyhow::anyhow; use anyhow::anyhow;
use dirs::data_dir; use dirs::data_dir;
use iced::advanced::Application; use iced::advanced::Application;
use pumpbin::{plugin::CONFIG_FILE_PATH, Pumpbin}; use pumpbin::{error_dialog, plugin::CONFIG_FILE_PATH, settings, Pumpbin};
fn main() -> anyhow::Result<()> { fn main() {
match try_main() {
Ok(_) => (),
Err(e) => {
error_dialog(e);
}
}
}
fn try_main() -> anyhow::Result<()> {
let mut config_path = data_dir().ok_or(anyhow!("Get data_dir failed."))?; let mut config_path = data_dir().ok_or(anyhow!("Get data_dir failed."))?;
config_path.push("PumpBin"); config_path.push("PumpBin");
config_path.push("plugins"); config_path.push("plugins");
@@ -25,6 +34,6 @@ fn main() -> anyhow::Result<()> {
.set(config_path) .set(config_path)
.map_err(|_| anyhow!("Set CONFIG_FILE_PATH failed."))?; .map_err(|_| anyhow!("Set CONFIG_FILE_PATH failed."))?;
Pumpbin::run(Pumpbin::settings())?; Pumpbin::run(settings())?;
Ok(()) Ok(())
} }