refactor advanced_message_dialog in own file
This commit is contained in:
226
src/widgets/advanced_message_dialog.rs
Normal file
226
src/widgets/advanced_message_dialog.rs
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
use std::cell::OnceCell;
|
||||||
|
|
||||||
|
use adw::prelude::*;
|
||||||
|
use adw::subclass::prelude::*;
|
||||||
|
use gsv::prelude::*;
|
||||||
|
use gtk::{gio, glib};
|
||||||
|
|
||||||
|
use crate::subscription::Subscription;
|
||||||
|
use crate::widgets::*;
|
||||||
|
|
||||||
|
mod imp {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct AdvancedMessageDialog {
|
||||||
|
pub subscription: OnceCell<Subscription>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[glib::object_subclass]
|
||||||
|
impl ObjectSubclass for AdvancedMessageDialog {
|
||||||
|
const NAME: &'static str = "AdvancedMessageDialog";
|
||||||
|
type Type = super::AdvancedMessageDialog;
|
||||||
|
type ParentType = adw::Window;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ObjectImpl for AdvancedMessageDialog {}
|
||||||
|
impl WidgetImpl for AdvancedMessageDialog {}
|
||||||
|
impl WindowImpl for AdvancedMessageDialog {}
|
||||||
|
impl AdwWindowImpl for AdvancedMessageDialog {}
|
||||||
|
}
|
||||||
|
|
||||||
|
glib::wrapper! {
|
||||||
|
pub struct AdvancedMessageDialog(ObjectSubclass<imp::AdvancedMessageDialog>)
|
||||||
|
@extends gtk::Widget, gtk::Window, adw::Window;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AdvancedMessageDialog {
|
||||||
|
pub fn new(
|
||||||
|
parent: &impl IsA<gtk::Window>,
|
||||||
|
subscription: Subscription,
|
||||||
|
message: String,
|
||||||
|
) -> Self {
|
||||||
|
let this: Self = glib::Object::new();
|
||||||
|
this.set_transient_for(Some(parent));
|
||||||
|
this.set_modal(true);
|
||||||
|
this.set_default_height(400);
|
||||||
|
this.imp().subscription.set(subscription).unwrap();
|
||||||
|
this.build_ui(
|
||||||
|
this.imp().subscription.get().unwrap().topic().clone(),
|
||||||
|
message,
|
||||||
|
);
|
||||||
|
this
|
||||||
|
}
|
||||||
|
fn build_ui(&self, topic: String, message: String) {
|
||||||
|
let this = self.clone();
|
||||||
|
relm4_macros::view! {
|
||||||
|
content = &adw::ToolbarView {
|
||||||
|
add_top_bar = &adw::HeaderBar {},
|
||||||
|
#[wrap(Some)]
|
||||||
|
set_content: toast_overlay = &adw::ToastOverlay {
|
||||||
|
#[wrap(Some)]
|
||||||
|
set_child = &adw::Clamp {
|
||||||
|
#[wrap(Some)]
|
||||||
|
set_child = >k::Box {
|
||||||
|
set_margin_top: 8,
|
||||||
|
set_margin_bottom: 8,
|
||||||
|
set_margin_start: 8,
|
||||||
|
set_margin_end: 8,
|
||||||
|
set_spacing: 8,
|
||||||
|
set_orientation: gtk::Orientation::Vertical,
|
||||||
|
append = >k::Label {
|
||||||
|
set_label: "Here you can manually build the JSON message you want to POST to this topic",
|
||||||
|
set_natural_wrap_mode: gtk::NaturalWrapMode::None,
|
||||||
|
set_xalign: 0.0,
|
||||||
|
set_halign: gtk::Align::Start,
|
||||||
|
set_wrap_mode: gtk::pango::WrapMode::WordChar,
|
||||||
|
set_wrap: true,
|
||||||
|
},
|
||||||
|
append = >k::Label {
|
||||||
|
add_css_class: "heading",
|
||||||
|
set_label: "JSON",
|
||||||
|
set_xalign: 0.0,
|
||||||
|
set_halign: gtk::Align::Start,
|
||||||
|
},
|
||||||
|
append = >k::ScrolledWindow {
|
||||||
|
#[wrap(Some)]
|
||||||
|
set_child: text_view = &gsv::View {
|
||||||
|
add_css_class: "code",
|
||||||
|
set_tab_width: 4,
|
||||||
|
set_indent_width: 2,
|
||||||
|
set_auto_indent: true,
|
||||||
|
set_top_margin: 4,
|
||||||
|
set_bottom_margin: 4,
|
||||||
|
set_left_margin: 4,
|
||||||
|
set_right_margin: 4,
|
||||||
|
set_hexpand: true,
|
||||||
|
set_vexpand: true,
|
||||||
|
set_monospace: true,
|
||||||
|
set_background_pattern: gsv::BackgroundPatternType::Grid
|
||||||
|
},
|
||||||
|
},
|
||||||
|
append = >k::Label {
|
||||||
|
add_css_class: "heading",
|
||||||
|
set_label: "Snippets",
|
||||||
|
set_xalign: 0.0,
|
||||||
|
set_halign: gtk::Align::Start,
|
||||||
|
},
|
||||||
|
append = >k::FlowBox {
|
||||||
|
set_column_spacing: 4,
|
||||||
|
set_row_spacing: 4,
|
||||||
|
append = >k::Button {
|
||||||
|
add_css_class: "pill",
|
||||||
|
add_css_class: "small",
|
||||||
|
set_label: "Title",
|
||||||
|
connect_clicked[text_view] => move |_| {
|
||||||
|
text_view.buffer().insert_at_cursor(r#""title": "Title of your message""#)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
append = >k::Button {
|
||||||
|
add_css_class: "pill",
|
||||||
|
add_css_class: "small",
|
||||||
|
set_label: "Tags",
|
||||||
|
connect_clicked[text_view] => move |_| {
|
||||||
|
text_view.buffer().insert_at_cursor(r#""tags": ["warning","cd"]"#)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
append = >k::Button {
|
||||||
|
add_css_class: "pill",
|
||||||
|
add_css_class: "small",
|
||||||
|
set_label: "Priority",
|
||||||
|
connect_clicked[text_view] => move |_| {
|
||||||
|
text_view.buffer().insert_at_cursor(r#""priority": 5"#)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
append = >k::Button {
|
||||||
|
add_css_class: "pill",
|
||||||
|
add_css_class: "small",
|
||||||
|
set_label: "View Action",
|
||||||
|
connect_clicked[text_view] => move |_| {
|
||||||
|
text_view.buffer().insert_at_cursor(r#""actions": [
|
||||||
|
{
|
||||||
|
"action": "view",
|
||||||
|
"label": "torvalds boosted your toot",
|
||||||
|
"url": "https://joinmastodon.org"
|
||||||
|
}
|
||||||
|
]"#)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
append = >k::Button {
|
||||||
|
add_css_class: "pill",
|
||||||
|
add_css_class: "small",
|
||||||
|
set_label: "HTTP Action",
|
||||||
|
connect_clicked[text_view] => move |_| {
|
||||||
|
text_view.buffer().insert_at_cursor(r#""actions": [
|
||||||
|
{
|
||||||
|
"action": "http",
|
||||||
|
"label": "Turn off lights",
|
||||||
|
"method": "post",
|
||||||
|
"url": "https://api.example.com/lights",
|
||||||
|
"body": "OFF"
|
||||||
|
}
|
||||||
|
]"#)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
append = >k::Button {
|
||||||
|
add_css_class: "circular",
|
||||||
|
add_css_class: "small",
|
||||||
|
set_label: "?",
|
||||||
|
connect_clicked[this] => move |_| {
|
||||||
|
gtk::UriLauncher::new("https://docs.ntfy.sh/publish/#publish-as-json").launch(
|
||||||
|
Some(&this),
|
||||||
|
gio::Cancellable::NONE,
|
||||||
|
|_| {}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
append = >k::Button {
|
||||||
|
set_margin_top: 8,
|
||||||
|
set_margin_bottom: 8,
|
||||||
|
add_css_class: "suggested-action",
|
||||||
|
add_css_class: "pill",
|
||||||
|
set_label: "Send",
|
||||||
|
connect_clicked[this, toast_overlay, text_view] => move |_| {
|
||||||
|
let thisc = this.clone();
|
||||||
|
let text_view = text_view.clone();
|
||||||
|
let f = async move {
|
||||||
|
let buffer = text_view.buffer();
|
||||||
|
let msg = serde_json::from_str(&buffer.text(
|
||||||
|
&mut buffer.start_iter(),
|
||||||
|
&mut buffer.end_iter(),
|
||||||
|
true,
|
||||||
|
)).map_err(|e| capnp::Error::failed(e.to_string()))?;
|
||||||
|
thisc.imp().subscription.get().unwrap()
|
||||||
|
.publish_msg(msg).await
|
||||||
|
};
|
||||||
|
toast_overlay.spawn_with_near_toast(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let lang = gsv::LanguageManager::default().language("json").unwrap();
|
||||||
|
let buffer = gsv::Buffer::with_language(&lang);
|
||||||
|
buffer.set_text(&format!(
|
||||||
|
r#"{{
|
||||||
|
"topic": "{topic}",
|
||||||
|
"message": "{message}"
|
||||||
|
}}"#
|
||||||
|
));
|
||||||
|
text_view.set_buffer(Some(&buffer));
|
||||||
|
|
||||||
|
let manager = adw::StyleManager::default();
|
||||||
|
let scheme_name = if manager.is_dark() {
|
||||||
|
"solarized-dark"
|
||||||
|
} else {
|
||||||
|
"solarized-light"
|
||||||
|
};
|
||||||
|
let scheme = gsv::StyleSchemeManager::default().scheme(scheme_name);
|
||||||
|
buffer.set_style_scheme(scheme.as_ref());
|
||||||
|
this.set_content(Some(&content));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,8 +1,10 @@
|
|||||||
mod add_subscription_dialog;
|
mod add_subscription_dialog;
|
||||||
|
mod advanced_message_dialog;
|
||||||
mod message_row;
|
mod message_row;
|
||||||
mod subscription_info_dialog;
|
mod subscription_info_dialog;
|
||||||
mod window;
|
mod window;
|
||||||
pub use add_subscription_dialog::AddSubscriptionDialog;
|
pub use add_subscription_dialog::AddSubscriptionDialog;
|
||||||
|
pub use advanced_message_dialog::*;
|
||||||
pub use message_row::*;
|
pub use message_row::*;
|
||||||
pub use subscription_info_dialog::SubscriptionInfoDialog;
|
pub use subscription_info_dialog::SubscriptionInfoDialog;
|
||||||
pub use window::*;
|
pub use window::*;
|
||||||
|
|||||||
@ -4,7 +4,6 @@ use std::cell::OnceCell;
|
|||||||
use adw::prelude::*;
|
use adw::prelude::*;
|
||||||
use adw::subclass::prelude::*;
|
use adw::subclass::prelude::*;
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
use gsv::prelude::*;
|
|
||||||
use gtk::{gio, glib};
|
use gtk::{gio, glib};
|
||||||
use ntfy_daemon::models;
|
use ntfy_daemon::models;
|
||||||
use ntfy_daemon::ntfy_capnp::{system_notifier, Status};
|
use ntfy_daemon::ntfy_capnp::{system_notifier, Status};
|
||||||
@ -260,192 +259,13 @@ impl NotifyWindow {
|
|||||||
let imp = self.imp();
|
let imp = self.imp();
|
||||||
let this = self.clone();
|
let this = self.clone();
|
||||||
imp.code_btn.connect_clicked(move |_| {
|
imp.code_btn.connect_clicked(move |_| {
|
||||||
this.show_docs_dialog();
|
let this = this.clone();
|
||||||
|
this.selected_subscription().map(move |sub| {
|
||||||
|
AdvancedMessageDialog::new(&this, sub, this.imp().entry.text().to_string())
|
||||||
|
.present()
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
fn show_docs_dialog(&self) {
|
|
||||||
let imp = self.imp();
|
|
||||||
let this = self.clone();
|
|
||||||
let topic = self.selected_subscription().unwrap().topic();
|
|
||||||
let message = imp.entry.text();
|
|
||||||
relm4_macros::view! {
|
|
||||||
window = adw::Window {
|
|
||||||
set_default_height: 400,
|
|
||||||
set_modal: true,
|
|
||||||
set_transient_for: Some(self),
|
|
||||||
#[wrap(Some)]
|
|
||||||
set_content = &adw::ToolbarView {
|
|
||||||
add_top_bar = &adw::HeaderBar {},
|
|
||||||
#[wrap(Some)]
|
|
||||||
set_content: toast_overlay = &adw::ToastOverlay {
|
|
||||||
#[wrap(Some)]
|
|
||||||
set_child = &adw::Clamp {
|
|
||||||
#[wrap(Some)]
|
|
||||||
set_child = >k::Box {
|
|
||||||
set_margin_top: 8,
|
|
||||||
set_margin_bottom: 8,
|
|
||||||
set_margin_start: 8,
|
|
||||||
set_margin_end: 8,
|
|
||||||
set_spacing: 8,
|
|
||||||
set_orientation: gtk::Orientation::Vertical,
|
|
||||||
append = >k::Label {
|
|
||||||
set_label: "Here you can manually build the JSON message you want to POST to this topic",
|
|
||||||
set_natural_wrap_mode: gtk::NaturalWrapMode::None,
|
|
||||||
set_xalign: 0.0,
|
|
||||||
set_halign: gtk::Align::Start,
|
|
||||||
set_wrap_mode: gtk::pango::WrapMode::WordChar,
|
|
||||||
set_wrap: true,
|
|
||||||
},
|
|
||||||
append = >k::Label {
|
|
||||||
add_css_class: "heading",
|
|
||||||
set_label: "JSON",
|
|
||||||
set_xalign: 0.0,
|
|
||||||
set_halign: gtk::Align::Start,
|
|
||||||
},
|
|
||||||
append = >k::ScrolledWindow {
|
|
||||||
#[wrap(Some)]
|
|
||||||
set_child: text_view = &gsv::View {
|
|
||||||
add_css_class: "code",
|
|
||||||
set_tab_width: 4,
|
|
||||||
set_indent_width: 2,
|
|
||||||
set_auto_indent: true,
|
|
||||||
set_top_margin: 4,
|
|
||||||
set_bottom_margin: 4,
|
|
||||||
set_left_margin: 4,
|
|
||||||
set_right_margin: 4,
|
|
||||||
set_hexpand: true,
|
|
||||||
set_vexpand: true,
|
|
||||||
set_monospace: true,
|
|
||||||
set_background_pattern: gsv::BackgroundPatternType::Grid
|
|
||||||
},
|
|
||||||
},
|
|
||||||
append = >k::Label {
|
|
||||||
add_css_class: "heading",
|
|
||||||
set_label: "Snippets",
|
|
||||||
set_xalign: 0.0,
|
|
||||||
set_halign: gtk::Align::Start,
|
|
||||||
},
|
|
||||||
append = >k::FlowBox {
|
|
||||||
set_column_spacing: 4,
|
|
||||||
set_row_spacing: 4,
|
|
||||||
append = >k::Button {
|
|
||||||
add_css_class: "pill",
|
|
||||||
add_css_class: "small",
|
|
||||||
set_label: "Title",
|
|
||||||
connect_clicked[text_view] => move |_| {
|
|
||||||
text_view.buffer().insert_at_cursor(r#""title": "Title of your message""#)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
append = >k::Button {
|
|
||||||
add_css_class: "pill",
|
|
||||||
add_css_class: "small",
|
|
||||||
set_label: "Tags",
|
|
||||||
connect_clicked[text_view] => move |_| {
|
|
||||||
text_view.buffer().insert_at_cursor(r#""tags": ["warning","cd"]"#)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
append = >k::Button {
|
|
||||||
add_css_class: "pill",
|
|
||||||
add_css_class: "small",
|
|
||||||
set_label: "Priority",
|
|
||||||
connect_clicked[text_view] => move |_| {
|
|
||||||
text_view.buffer().insert_at_cursor(r#""priority": 5"#)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
append = >k::Button {
|
|
||||||
add_css_class: "pill",
|
|
||||||
add_css_class: "small",
|
|
||||||
set_label: "View Action",
|
|
||||||
connect_clicked[text_view] => move |_| {
|
|
||||||
text_view.buffer().insert_at_cursor(r#""actions": [
|
|
||||||
{
|
|
||||||
"action": "view",
|
|
||||||
"label": "torvalds boosted your toot",
|
|
||||||
"url": "https://joinmastodon.org"
|
|
||||||
}
|
|
||||||
]"#)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
append = >k::Button {
|
|
||||||
add_css_class: "pill",
|
|
||||||
add_css_class: "small",
|
|
||||||
set_label: "HTTP Action",
|
|
||||||
connect_clicked[text_view] => move |_| {
|
|
||||||
text_view.buffer().insert_at_cursor(r#""actions": [
|
|
||||||
{
|
|
||||||
"action": "http",
|
|
||||||
"label": "Turn off lights",
|
|
||||||
"method": "post",
|
|
||||||
"url": "https://api.example.com/lights",
|
|
||||||
"body": "OFF"
|
|
||||||
}
|
|
||||||
]"#)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
append = >k::Button {
|
|
||||||
add_css_class: "circular",
|
|
||||||
add_css_class: "small",
|
|
||||||
set_label: "?",
|
|
||||||
connect_clicked[this] => move |_| {
|
|
||||||
gtk::UriLauncher::new("https://docs.ntfy.sh/publish/#publish-as-json").launch(
|
|
||||||
Some(&this),
|
|
||||||
gio::Cancellable::NONE,
|
|
||||||
|_| {}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
append = >k::Button {
|
|
||||||
set_margin_top: 8,
|
|
||||||
set_margin_bottom: 8,
|
|
||||||
add_css_class: "suggested-action",
|
|
||||||
add_css_class: "pill",
|
|
||||||
set_label: "Send",
|
|
||||||
connect_clicked[this, toast_overlay, text_view] => move |_| {
|
|
||||||
let thisc = this.clone();
|
|
||||||
let text_view = text_view.clone();
|
|
||||||
let f = async move {
|
|
||||||
let buffer = text_view.buffer();
|
|
||||||
let msg = serde_json::from_str(&buffer.text(
|
|
||||||
&mut buffer.start_iter(),
|
|
||||||
&mut buffer.end_iter(),
|
|
||||||
true,
|
|
||||||
)).map_err(|e| capnp::Error::failed(e.to_string()))?;
|
|
||||||
thisc.selected_subscription()
|
|
||||||
.unwrap()
|
|
||||||
.publish_msg(msg).await
|
|
||||||
};
|
|
||||||
toast_overlay.spawn_with_near_toast(f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let lang = gsv::LanguageManager::default().language("json").unwrap();
|
|
||||||
let buffer = gsv::Buffer::with_language(&lang);
|
|
||||||
buffer.set_text(&format!(
|
|
||||||
r#"{{
|
|
||||||
"topic": "{topic}",
|
|
||||||
"message": "{message}"
|
|
||||||
}}"#
|
|
||||||
));
|
|
||||||
text_view.set_buffer(Some(&buffer));
|
|
||||||
|
|
||||||
let manager = adw::StyleManager::default();
|
|
||||||
let scheme_name = if manager.is_dark() {
|
|
||||||
"solarized-dark"
|
|
||||||
} else {
|
|
||||||
"solarized-light"
|
|
||||||
};
|
|
||||||
let scheme = gsv::StyleSchemeManager::default().scheme(scheme_name);
|
|
||||||
buffer.set_style_scheme(scheme.as_ref());
|
|
||||||
|
|
||||||
window.present();
|
|
||||||
}
|
|
||||||
fn show_subscription_info(&self) {
|
fn show_subscription_info(&self) {
|
||||||
let sub = SubscriptionInfoDialog::new(self.selected_subscription().unwrap());
|
let sub = SubscriptionInfoDialog::new(self.selected_subscription().unwrap());
|
||||||
sub.set_transient_for(Some(self));
|
sub.set_transient_for(Some(self));
|
||||||
|
|||||||
Reference in New Issue
Block a user