use relm4::view!
This commit is contained in:
12
Cargo.lock
generated
12
Cargo.lock
generated
@ -1655,6 +1655,7 @@ dependencies = [
|
|||||||
"ntfy-daemon",
|
"ntfy-daemon",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"rand",
|
"rand",
|
||||||
|
"relm4-macros",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tracing",
|
"tracing",
|
||||||
@ -2051,6 +2052,17 @@ version = "0.8.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "relm4-macros"
|
||||||
|
version = "0.6.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9340e2553c0a184a80a0bfa1dcf73c47f3d48933aa6be90724b202f9fbd24735"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.38",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "reqwest"
|
name = "reqwest"
|
||||||
version = "0.11.22"
|
version = "0.11.22"
|
||||||
|
|||||||
@ -30,3 +30,4 @@ rand = "0.8.5"
|
|||||||
ureq = "2.7.1"
|
ureq = "2.7.1"
|
||||||
futures = "0.3.0"
|
futures = "0.3.0"
|
||||||
ashpd = "0.6.0"
|
ashpd = "0.6.0"
|
||||||
|
relm4-macros = { version = "0.6.2", features = [], default-features = false }
|
||||||
|
|||||||
@ -10,7 +10,7 @@ use gtk::prelude::*;
|
|||||||
use gtk::{gdk, gio, glib};
|
use gtk::{gdk, gio, glib};
|
||||||
use ntfy_daemon::models;
|
use ntfy_daemon::models;
|
||||||
use ntfy_daemon::ntfy_capnp::system_notifier;
|
use ntfy_daemon::ntfy_capnp::system_notifier;
|
||||||
use tracing::{debug, info};
|
use tracing::{debug, info, warn};
|
||||||
|
|
||||||
use crate::config::{APP_ID, PKGDATADIR, PROFILE, VERSION};
|
use crate::config::{APP_ID, PKGDATADIR, PROFILE, VERSION};
|
||||||
use crate::widgets::*;
|
use crate::widgets::*;
|
||||||
@ -69,7 +69,9 @@ mod imp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
glib::MainContext::default().spawn_local(async move {
|
glib::MainContext::default().spawn_local(async move {
|
||||||
super::NotifyApplication::run_in_background().await.unwrap();
|
if let Err(e) = super::NotifyApplication::run_in_background().await {
|
||||||
|
warn!(error = %e, "couldn't request running in background from portal");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if is_daemon {
|
if is_daemon {
|
||||||
|
|||||||
@ -1,20 +1,18 @@
|
|||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
use adw::prelude::*;
|
use adw::prelude::*;
|
||||||
use adw::subclass::prelude::*;
|
use adw::subclass::prelude::*;
|
||||||
use glib::once_cell::sync::Lazy;
|
use glib::once_cell::sync::Lazy;
|
||||||
use glib::subclass::Signal;
|
use glib::subclass::Signal;
|
||||||
use glib::Properties;
|
|
||||||
use gtk::gio;
|
use gtk::gio;
|
||||||
use gtk::glib;
|
use gtk::glib;
|
||||||
|
|
||||||
mod imp {
|
mod imp {
|
||||||
pub use super::*;
|
pub use super::*;
|
||||||
#[derive(Debug, Default, Properties)]
|
#[derive(Debug, Default)]
|
||||||
#[properties(wrapper_type = super::AddSubscriptionDialog)]
|
|
||||||
pub struct AddSubscriptionDialog {
|
pub struct AddSubscriptionDialog {
|
||||||
#[property(name = "topic", get = |imp: &Self| imp.topic_entry.text(), type = glib::GString)]
|
pub topic_entry: RefCell<adw::EntryRow>,
|
||||||
pub topic_entry: adw::EntryRow,
|
pub server_entry: RefCell<adw::EntryRow>,
|
||||||
#[property(name = "server", get = |imp: &Self| imp.server_entry.text(), type = glib::GString)]
|
|
||||||
pub server_entry: adw::EntryRow,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[glib::object_subclass]
|
#[glib::object_subclass]
|
||||||
@ -36,7 +34,7 @@ mod imp {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[glib::derived_properties]
|
|
||||||
impl ObjectImpl for AddSubscriptionDialog {
|
impl ObjectImpl for AddSubscriptionDialog {
|
||||||
fn signals() -> &'static [Signal] {
|
fn signals() -> &'static [Signal] {
|
||||||
static SIGNALS: Lazy<Vec<Signal>> =
|
static SIGNALS: Lazy<Vec<Signal>> =
|
||||||
@ -72,108 +70,81 @@ impl AddSubscriptionDialog {
|
|||||||
obj.set_modal(true);
|
obj.set_modal(true);
|
||||||
obj.set_default_width(360);
|
obj.set_default_width(360);
|
||||||
|
|
||||||
let toolbar_view = adw::ToolbarView::new();
|
relm4_macros::view! {
|
||||||
toolbar_view.add_top_bar(&adw::HeaderBar::new());
|
toolbar_view = adw::ToolbarView {
|
||||||
|
add_top_bar: &adw::HeaderBar::new(),
|
||||||
|
#[wrap(Some)]
|
||||||
|
set_content = &adw::Clamp {
|
||||||
|
#[wrap(Some)]
|
||||||
|
set_child = >k::Box {
|
||||||
|
set_orientation: gtk::Orientation::Vertical,
|
||||||
|
set_spacing: 12,
|
||||||
|
set_margin_end: 12,
|
||||||
|
set_margin_start: 12,
|
||||||
|
set_margin_top: 12,
|
||||||
|
set_margin_bottom: 12,
|
||||||
|
append = >k::Label {
|
||||||
|
add_css_class: "dim-label",
|
||||||
|
set_label: "Topics may not be password-protected, so choose a name that's not easy to guess. \
|
||||||
|
Once subscribed, you can PUT/POST notifications.",
|
||||||
|
set_wrap: true,
|
||||||
|
set_xalign: 0.0,
|
||||||
|
set_wrap_mode: gtk::pango::WrapMode::WordChar
|
||||||
|
},
|
||||||
|
append = >k::ListBox {
|
||||||
|
add_css_class: "boxed-list",
|
||||||
|
append: topic_entry = &adw::EntryRow {
|
||||||
|
set_title: "Topic",
|
||||||
|
set_activates_default: true,
|
||||||
|
add_suffix = >k::Button {
|
||||||
|
set_icon_name: "dice3-symbolic",
|
||||||
|
set_tooltip_text: Some("Generate name"),
|
||||||
|
set_valign: gtk::Align::Center,
|
||||||
|
add_css_class: "flat",
|
||||||
|
connect_clicked[topic_entry] => move |_| {
|
||||||
|
use rand::distributions::Alphanumeric;
|
||||||
|
use rand::{thread_rng, Rng};
|
||||||
|
let mut rng = thread_rng();
|
||||||
|
let chars: String = (0..10).map(|_| rng.sample(Alphanumeric) as char).collect();
|
||||||
|
topic_entry.set_text(&chars);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
append = &adw::ExpanderRow {
|
||||||
|
set_title: "Custom server...",
|
||||||
|
set_enable_expansion: false,
|
||||||
|
set_show_enable_switch: true,
|
||||||
|
add_row: server_entry = &adw::EntryRow {
|
||||||
|
set_title: "Server",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
append = >k::Button {
|
||||||
|
set_label: "Subscribe",
|
||||||
|
add_css_class: "suggested-action",
|
||||||
|
add_css_class: "pill",
|
||||||
|
set_halign: gtk::Align::Center,
|
||||||
|
connect_clicked[obj] => move |_| {
|
||||||
|
obj.emit_subscribe_request();
|
||||||
|
obj.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
let content = gtk::Box::builder()
|
imp.topic_entry.replace(topic_entry);
|
||||||
.orientation(gtk::Orientation::Vertical)
|
imp.server_entry.replace(server_entry);
|
||||||
.spacing(12)
|
|
||||||
.margin_end(12)
|
|
||||||
.margin_start(12)
|
|
||||||
.margin_top(12)
|
|
||||||
.margin_bottom(12)
|
|
||||||
.build();
|
|
||||||
let clamp = adw::Clamp::new();
|
|
||||||
clamp.set_child(Some(&content));
|
|
||||||
|
|
||||||
let description = {
|
|
||||||
let d = gtk::Label::builder()
|
|
||||||
.label("Topics may not be password-protected, so choose a name that's not easy to guess. Once subscribed, you can PUT/POST notifications.")
|
|
||||||
.wrap(true)
|
|
||||||
.xalign(0.0)
|
|
||||||
.wrap_mode(gtk::pango::WrapMode::WordChar)
|
|
||||||
.build();
|
|
||||||
d.add_css_class("dim-label");
|
|
||||||
d
|
|
||||||
};
|
|
||||||
|
|
||||||
content.append(&description);
|
|
||||||
|
|
||||||
let topic_entry = {
|
|
||||||
let e = &imp.topic_entry;
|
|
||||||
e.set_title("Topic");
|
|
||||||
e.set_activates_default(true);
|
|
||||||
|
|
||||||
let rand_btn = {
|
|
||||||
let b = gtk::Button::builder()
|
|
||||||
.icon_name("dice3-symbolic")
|
|
||||||
.tooltip_text("Generate Name")
|
|
||||||
.valign(gtk::Align::Center)
|
|
||||||
.css_classes(["flat"])
|
|
||||||
.build();
|
|
||||||
let ec = e.clone();
|
|
||||||
b.connect_clicked(move |_| {
|
|
||||||
use rand::distributions::Alphanumeric;
|
|
||||||
use rand::{thread_rng, Rng};
|
|
||||||
let mut rng = thread_rng();
|
|
||||||
let chars: String = (0..10).map(|_| rng.sample(Alphanumeric) as char).collect();
|
|
||||||
ec.set_text(&chars);
|
|
||||||
});
|
|
||||||
b
|
|
||||||
};
|
|
||||||
|
|
||||||
e.add_suffix(&rand_btn);
|
|
||||||
e
|
|
||||||
};
|
|
||||||
// TODO: Reserved topics
|
|
||||||
/*let reserved_switch = {
|
|
||||||
adw::SwitchRow::builder()
|
|
||||||
.title("Reserved")
|
|
||||||
.subtitle("For Ntfy Pro users only")
|
|
||||||
.build()
|
|
||||||
};*/
|
|
||||||
let server_entry = &imp.server_entry;
|
|
||||||
server_entry.set_title("Server");
|
|
||||||
|
|
||||||
let expander_row = {
|
|
||||||
let e = adw::ExpanderRow::builder()
|
|
||||||
.title("Custom Server...")
|
|
||||||
.enable_expansion(false)
|
|
||||||
.show_enable_switch(true)
|
|
||||||
.build();
|
|
||||||
e.add_row(server_entry);
|
|
||||||
e
|
|
||||||
};
|
|
||||||
let list_box = {
|
|
||||||
let l = gtk::ListBox::new();
|
|
||||||
l.add_css_class("boxed-list");
|
|
||||||
l.append(topic_entry);
|
|
||||||
// l.append(&reserved_switch);
|
|
||||||
l.append(&expander_row);
|
|
||||||
l
|
|
||||||
};
|
|
||||||
content.append(&list_box);
|
|
||||||
|
|
||||||
let sub_btn = {
|
|
||||||
let b = gtk::Button::new();
|
|
||||||
b.set_label("Subscribe");
|
|
||||||
b.add_css_class("suggested-action");
|
|
||||||
b.add_css_class("pill");
|
|
||||||
b.set_halign(gtk::Align::Center);
|
|
||||||
|
|
||||||
let wc = obj.clone();
|
|
||||||
b.connect_clicked(move |_| {
|
|
||||||
wc.emit_subscribe_request();
|
|
||||||
wc.close();
|
|
||||||
});
|
|
||||||
b
|
|
||||||
};
|
|
||||||
|
|
||||||
content.append(&sub_btn);
|
|
||||||
toolbar_view.set_content(Some(&clamp));
|
|
||||||
|
|
||||||
obj.set_content(Some(&toolbar_view));
|
obj.set_content(Some(&toolbar_view));
|
||||||
}
|
}
|
||||||
|
pub fn topic(&self) -> String {
|
||||||
|
self.imp().topic_entry.borrow().text().to_string()
|
||||||
|
}
|
||||||
|
pub fn server(&self) -> String {
|
||||||
|
self.imp().server_entry.borrow().text().to_string()
|
||||||
|
}
|
||||||
fn emit_subscribe_request(&self) {
|
fn emit_subscribe_request(&self) {
|
||||||
self.emit_by_name::<()>("subscribe-request", &[]);
|
self.emit_by_name::<()>("subscribe-request", &[]);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user