window: Add a global paste action to paste media

Now it's possible to paste an image even when the message entry is not focused.
This commit is contained in:
Marco Melorio 2022-04-17 01:56:23 +02:00 committed by Julian Sparber
parent e069053cda
commit 89b89024c9
5 changed files with 59 additions and 13 deletions

View file

@ -3,14 +3,14 @@
<template class="Session" parent="AdwBin">
<property name="child">
<object class="GtkStack" id="stack">
<property name="visible-child">content</property>
<property name="visible-child">leaflet</property>
<property name="transition-type">crossfade</property>
<child>
<object class="AdwLeaflet" id="content">
<object class="AdwLeaflet" id="leaflet">
<property name="fold-threshold-policy">minimum</property>
<child>
<object class="Sidebar" id="sidebar">
<property name="compact" bind-source="content" bind-property="folded" bind-flags="sync-create"/>
<property name="compact" bind-source="leaflet" bind-property="folded" bind-flags="sync-create"/>
<property name="user" bind-source="Session" bind-property="user" bind-flags="sync-create"/>
<property name="item-list" bind-source="Session" bind-property="item-list" bind-flags="sync-create"/>
</object>
@ -24,8 +24,8 @@
</object>
</child>
<child>
<object class="Content">
<property name="compact" bind-source="content" bind-property="folded" bind-flags="sync-create"/>
<object class="Content" id="content">
<property name="compact" bind-source="leaflet" bind-property="folded" bind-flags="sync-create"/>
<property name="item" bind-source="sidebar" bind-property="selected-item" bind-flags="sync-create | bidirectional"/>
<property name="session">Session</property>
</object>

View file

@ -169,6 +169,19 @@ impl Content {
glib::Object::new(&[("session", session)]).expect("Failed to create Content")
}
pub fn handle_paste_action(&self) {
let priv_ = self.imp();
if priv_
.stack
.visible_child()
.as_ref()
.map(|c| c == priv_.room_history.upcast_ref::<gtk::Widget>())
.unwrap_or_default()
{
priv_.room_history.handle_paste_action();
}
}
pub fn session(&self) -> Option<Session> {
self.imp()
.session

View file

@ -440,6 +440,12 @@ impl RoomHistory {
}
}
pub fn handle_paste_action(&self) {
spawn!(glib::clone!(@weak self as obj => async move {
obj.read_clipboard().await;
}));
}
pub fn new() -> Self {
glib::Object::new(&[]).expect("Failed to create RoomHistory")
}

View file

@ -101,10 +101,12 @@ mod imp {
#[template_child]
pub stack: TemplateChild<gtk::Stack>,
#[template_child]
pub content: TemplateChild<adw::Leaflet>,
pub leaflet: TemplateChild<adw::Leaflet>,
#[template_child]
pub sidebar: TemplateChild<Sidebar>,
#[template_child]
pub content: TemplateChild<Content>,
#[template_child]
pub media_viewer: TemplateChild<MediaViewer>,
pub client: RefCell<Option<Client>>,
pub item_list: OnceCell<ItemList>,
@ -186,8 +188,6 @@ mod imp {
}
fn instance_init(obj: &InitializingObject<Self>) {
Sidebar::static_type();
Content::static_type();
obj.init_template();
}
}
@ -249,9 +249,9 @@ mod imp {
let priv_ = obj.imp();
if priv_.sidebar.selected_item().is_none() {
priv_.content.navigate(adw::NavigationDirection::Back);
priv_.leaflet.navigate(adw::NavigationDirection::Back);
} else {
priv_.content.navigate(adw::NavigationDirection::Forward);
priv_.leaflet.navigate(adw::NavigationDirection::Forward);
}
}),
);
@ -559,7 +559,7 @@ impl Session {
let handle = spawn_tokio!(async move { encryption.bootstrap_cross_signing(None).await });
if handle.await.is_ok() {
priv_.stack.set_visible_child(&*priv_.content);
priv_.stack.set_visible_child(&*priv_.leaflet);
if let Some(window) = obj.parent_window() {
window.switch_to_sessions_page();
}
@ -771,6 +771,10 @@ impl Session {
);
}
pub fn handle_paste_action(&self) {
self.imp().content.handle_paste_action();
}
async fn cleanup_session(&self) {
let priv_ = self.imp();
let info = priv_.info.get().unwrap();
@ -806,7 +810,7 @@ impl Session {
spawn!(clone!(@weak self as obj => async move {
obj.has_cross_signing_keys().await;
}));
priv_.stack.set_visible_child(&*priv_.content);
priv_.stack.set_visible_child(&*priv_.leaflet);
priv_.logout_on_dispose.set(false);
if let Some(window) = self.parent_window() {
window.switch_to_sessions_page();

View file

@ -1,7 +1,7 @@
use adw::subclass::prelude::AdwApplicationWindowImpl;
use gettextrs::gettext;
use glib::signal::Inhibit;
use gtk::{self, gio, glib, glib::clone, prelude::*, subclass::prelude::*, CompositeTemplate};
use gtk::{self, gdk, gio, glib, glib::clone, prelude::*, subclass::prelude::*, CompositeTemplate};
use log::warn;
use crate::{
@ -48,6 +48,29 @@ mod imp {
Toast::static_type();
InAppNotification::static_type();
Self::bind_template(klass);
klass.add_binding_action(
gdk::Key::v,
gdk::ModifierType::CONTROL_MASK,
"win.paste",
None,
);
klass.add_binding_action(
gdk::Key::Insert,
gdk::ModifierType::SHIFT_MASK,
"win.paste",
None,
);
klass.install_action("win.paste", None, move |widget, _, _| {
if let Some(session) = widget
.imp()
.sessions
.visible_child()
.and_then(|c| c.downcast::<Session>().ok())
{
session.handle_paste_action();
}
});
}
fn instance_init(obj: &InitializingObject<Self>) {