[fractal/ui-refactor: 9/15] Remove OP global variable
- From: Alejandro Domínguez <aledomu src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [fractal/ui-refactor: 9/15] Remove OP global variable
- Date: Wed, 2 Dec 2020 16:51:50 +0000 (UTC)
commit 815535d61c54c4958ceddf313d06706ee77e17a6
Author: Alejandro Domínguez <adomu net-c com>
Date: Sat Oct 17 10:08:31 2020 +0200
Remove OP global variable
fractal-gtk/src/actions/global.rs | 293 ++++++++++++++------------
fractal-gtk/src/app/mod.rs | 69 +++---
fractal-gtk/src/appop/connect/autocomplete.rs | 12 +-
fractal-gtk/src/appop/connect/mod.rs | 2 +-
fractal-gtk/src/uibuilder.rs | 8 +-
fractal-gtk/src/widgets/autocomplete.rs | 119 +++++------
fractal-gtk/src/widgets/login.rs | 18 +-
7 files changed, 268 insertions(+), 253 deletions(-)
---
diff --git a/fractal-gtk/src/actions/global.rs b/fractal-gtk/src/actions/global.rs
index 0c24ff37..0bc53272 100644
--- a/fractal-gtk/src/actions/global.rs
+++ b/fractal-gtk/src/actions/global.rs
@@ -1,8 +1,6 @@
use glib::clone;
use log::{debug, info};
use std::convert::TryInto;
-use std::rc::Rc;
-use std::sync::{Arc, Mutex};
use crate::app::AppRuntime;
use crate::appop::AppOp;
@@ -63,9 +61,11 @@ impl From<AppState> for glib::Variant {
}
}
-/* This creates globale actions which are connected to the application */
-/* TODO: Remove op */
-pub fn new(app: >k::Application, app_runtime: AppRuntime, op: &Arc<Mutex<AppOp>>) {
+// This creates global actions which are connected to the application
+pub fn new(appop: &AppOp) {
+ let app = &appop.ui.gtk_app;
+ let app_runtime = appop.app_runtime.clone();
+
let settings = SimpleAction::new("settings", None);
let chat = SimpleAction::new("start_chat", None);
let newr = SimpleAction::new("new_room", None);
@@ -142,164 +142,177 @@ pub fn new(app: >k::Application, app_runtime: AppRuntime, op: &Arc<Mutex<AppOp
app.quit();
}));
- about.connect_activate(clone!(@strong op => move |_, _| op.lock().unwrap().about_dialog() ));
- main_menu.connect_activate(clone!(@strong op => move |_, _| op.lock().unwrap().main_menu() ));
+ about.connect_activate(clone!(@strong app_runtime => move |_, _| {
+ app_runtime.update_state_with(|state| state.about_dialog());
+ }));
+ main_menu.connect_activate(clone!(@strong app_runtime => move |_, _| {
+ app_runtime.update_state_with(|state| state.main_menu());
+ }));
settings.connect_activate(move |_, _| {
info!("SETTINGS");
});
settings.set_enabled(false);
- logout.connect_activate(clone!(@strong op => move |_, _| op.lock().unwrap().logout() ));
- inv.connect_activate(
- clone!(@strong op => move |_, _| op.lock().unwrap().show_invite_user_dialog() ),
- );
- chat.connect_activate(
- clone!(@strong op => move |_, _| op.lock().unwrap().show_direct_chat_dialog() ),
- );
- leave.connect_activate(
- clone!(@strong op => move |_, _| op.lock().unwrap().leave_active_room() ),
- );
- newr.connect_activate(clone!(@strong op => move |_, _| op.lock().unwrap().new_room_dialog() ));
- joinr.connect_activate(
- clone!(@strong op => move |_, _| op.lock().unwrap().join_to_room_dialog() ),
- );
-
- previous_room.connect_activate(clone!(@strong op => move |_, _| {
- let mut op = op.lock().unwrap();
- if let Some(id) = op.roomlist.prev_id() {
- op.set_active_room_by_id(id);
- } else if let Some(last_room) = op.roomlist.last_id() {
- op.set_active_room_by_id(last_room);
- }
+ logout.connect_activate(clone!(@strong app_runtime => move |_, _| {
+ app_runtime.update_state_with(|state| state.logout());
}));
- next_room.connect_activate(clone!(@strong op => move |_, _| {
- let mut op = op.lock().unwrap();
- if let Some(id) = op.roomlist.next_id() {
- op.set_active_room_by_id(id);
- } else if let Some(first_room) = op.roomlist.first_id() {
- op.set_active_room_by_id(first_room);
- }
+ inv.connect_activate(clone!(@strong app_runtime => move |_, _| {
+ app_runtime.update_state_with(|state| state.show_invite_user_dialog());
}));
- prev_unread_room.connect_activate(clone!(@strong op => move |_, _| {
- let mut op = op.lock().unwrap();
- if let Some(id) = op.roomlist.prev_unread_id() {
- op.set_active_room_by_id(id);
- }
+ chat.connect_activate(clone!(@strong app_runtime => move |_, _| {
+ app_runtime.update_state_with(|state| state.show_direct_chat_dialog());
}));
- next_unread_room.connect_activate(clone!(@strong op => move |_, _| {
- let mut op = op.lock().unwrap();
- if let Some(id) = op.roomlist.next_unread_id() {
- op.set_active_room_by_id(id);
- }
+ leave.connect_activate(clone!(@strong app_runtime => move |_, _| {
+ app_runtime.update_state_with(|state| state.leave_active_room());
}));
- first_room.connect_activate(clone!(@strong op => move |_, _| {
- let mut op = op.lock().unwrap();
- if let Some(id) = op.roomlist.first_id() {
- op.set_active_room_by_id(id);
- }
+ newr.connect_activate(clone!(@strong app_runtime => move |_, _| {
+ app_runtime.update_state_with(|state| state.new_room_dialog());
}));
- last_room.connect_activate(clone!(@strong op => move |_, _| {
- let mut op = op.lock().unwrap();
- if let Some(id) = op.roomlist.last_id() {
- op.set_active_room_by_id(id);
- }
+ joinr.connect_activate(clone!(@strong app_runtime => move |_, _| {
+ app_runtime.update_state_with(|state| state.join_to_room_dialog());
}));
- older_messages.connect_activate(clone!(@strong op => move |_, _| {
- if let Some(ref mut hist) = op.lock().unwrap().history {
- hist.page_up();
- }
+
+ previous_room.connect_activate(clone!(@strong app_runtime => move |_, _| {
+ app_runtime.update_state_with(|state| {
+ if let Some(id) = state.roomlist.prev_id() {
+ state.set_active_room_by_id(id);
+ } else if let Some(last_room) = state.roomlist.last_id() {
+ state.set_active_room_by_id(last_room);
+ }
+ });
}));
- newer_messages.connect_activate(clone!(@strong op => move |_, _| {
- if let Some(ref mut hist) = op.lock().unwrap().history {
- hist.page_down();
- }
+ next_room.connect_activate(clone!(@strong app_runtime => move |_, _| {
+ app_runtime.update_state_with(|state| {
+ if let Some(id) = state.roomlist.next_id() {
+ state.set_active_room_by_id(id);
+ } else if let Some(first_room) = state.roomlist.first_id() {
+ state.set_active_room_by_id(first_room);
+ }
+ });
+ }));
+ prev_unread_room.connect_activate(clone!(@strong app_runtime => move |_, _| {
+ app_runtime.update_state_with(|state| {
+ if let Some(id) = state.roomlist.prev_unread_id() {
+ state.set_active_room_by_id(id);
+ }
+ });
+ }));
+ next_unread_room.connect_activate(clone!(@strong app_runtime => move |_, _| {
+ app_runtime.update_state_with(|state| {
+ if let Some(id) = state.roomlist.next_unread_id() {
+ state.set_active_room_by_id(id);
+ }
+ });
+ }));
+ first_room.connect_activate(clone!(@strong app_runtime => move |_, _| {
+ app_runtime.update_state_with(|state| {
+ if let Some(id) = state.roomlist.first_id() {
+ state.set_active_room_by_id(id);
+ }
+ });
+ }));
+ last_room.connect_activate(clone!(@strong app_runtime => move |_, _| {
+ app_runtime.update_state_with(|state| {
+ if let Some(id) = state.roomlist.last_id() {
+ state.set_active_room_by_id(id);
+ }
+ });
+ }));
+ older_messages.connect_activate(clone!(@strong app_runtime => move |_, _| {
+ app_runtime.update_state_with(|state| {
+ if let Some(ref mut hist) = state.history {
+ hist.page_up();
+ }
+ });
+ }));
+ newer_messages.connect_activate(clone!(@strong app_runtime => move |_, _| {
+ app_runtime.update_state_with(|state| {
+ if let Some(ref mut hist) = state.history {
+ hist.page_down();
+ }
+ });
}));
- let back_history = op.lock().unwrap().room_back_history.clone();
-
- account.connect_activate(clone!(
- @strong op,
- @weak back_history as back
- => move |_, _| {
- op.lock().unwrap().show_account_settings_dialog();
- back.borrow_mut().push(AppState::AccountSettings);
+ account.connect_activate(clone!(@strong app_runtime => move |_, _| {
+ app_runtime.update_state_with(|state| {
+ state.show_account_settings_dialog();
+ state.room_back_history.borrow_mut().push(AppState::AccountSettings);
+ });
}));
- directory.connect_activate(clone!(
- @strong op,
- @weak back_history as back
- => move |_, _| {
- op.lock().unwrap().set_state(AppState::Directory);
- back.borrow_mut().push(AppState::Directory);
+ directory.connect_activate(clone!(@strong app_runtime => move |_, _| {
+ app_runtime.update_state_with(|state| {
+ state.set_state(AppState::Directory);
+ state.room_back_history.borrow_mut().push(AppState::Directory);
+ });
}));
/* TODO: We could pass a message to this to highlight it in the room history, might be
* handy when opening the room from a notification */
- open_room.connect_activate(clone!(
- @strong op,
- @weak back_history as back
- => move |_, data| {
- if let Some(id) = get_room_id(data) {
- op.lock().unwrap().set_active_room_by_id(id);
- /* This does nothing if fractal is already in focus */
- op.lock().unwrap().activate();
- }
- // Push a new state only if the current state is not already Room
- let push = if let Some(last) = back.borrow().last() {
- last != &AppState::Room
- } else {
- true
- };
- if push {
- back.borrow_mut().push(AppState::Room);
- }
+ open_room.connect_activate(clone!(@strong app_runtime => move |_, data| {
+ let data = data.cloned();
+ app_runtime.update_state_with(move |state| {
+ if let Some(id) = get_room_id(data.as_ref()) {
+ state.set_active_room_by_id(id);
+ // This does nothing if fractal is already in focus
+ state.activate();
+ }
+ // Push a new state only if the current state is not already Room
+ let push = if let Some(last) = state.room_back_history.borrow().last() {
+ last != &AppState::Room
+ } else {
+ true
+ };
+ if push {
+ state.room_back_history.borrow_mut().push(AppState::Room);
+ }
+ });
}));
- room_settings.connect_activate(clone!(
- @strong op,
- @weak back_history as back
- => move |_, _| {
- op.lock().unwrap().create_room_settings();
- back.borrow_mut().push(AppState::RoomSettings);
+ room_settings.connect_activate(clone!(@strong app_runtime => move |_, _| {
+ app_runtime.update_state_with(|state| {
+ state.create_room_settings();
+ state.room_back_history.borrow_mut().push(AppState::RoomSettings);
+ });
}));
- media_viewer.connect_activate(clone!(
- @weak back_history as back
- => move |_, data| {
+ media_viewer.connect_activate(clone!(@strong app_runtime => move |_, data| {
open_viewer(&app_runtime, data.cloned());
- back.borrow_mut().push(AppState::MediaViewer);
+ app_runtime.update_state_with(|state| {
+ state.room_back_history.borrow_mut().push(AppState::MediaViewer);
+ });
}));
- deck_back.connect_activate(clone!(@strong op => move |_, _| {
- let deck = op.lock().unwrap().deck.clone();
- if deck.get_can_swipe_back() {
- deck.navigate(libhandy::NavigationDirection::Back);
- }
+ deck_back.connect_activate(clone!(@strong app_runtime => move |_, _| {
+ app_runtime.update_state_with(|state| {
+ let deck = state.deck.clone();
+ if deck.get_can_swipe_back() {
+ deck.navigate(libhandy::NavigationDirection::Back);
+ }
+ });
}));
- let mv = op.lock().unwrap().media_viewer.clone();
- let back_weak = Rc::downgrade(&back_history);
- back.connect_activate(clone!(@weak mv, @strong op => move |_, _| {
- if let Some(mut mv) = mv.borrow_mut().take() {
- mv.disconnect_signal_id();
- }
+ back.connect_activate(clone!(@strong app_runtime => move |_, _| {
+ app_runtime.update_state_with(|state| {
+ if let Some(mut mv) = state.media_viewer.borrow_mut().take() {
+ mv.disconnect_signal_id();
+ }
- // Remove the current state from the store
- if let Some(back) = back_weak.upgrade() {
- back.borrow_mut().pop();
- let mut op = op.lock().unwrap();
- if let Some(state) = back.borrow().last() {
- debug!("Go back to state {:?}", state);
- op.set_state(*state);
+ // Remove the current state from the store
+ state.room_back_history.borrow_mut().pop();
+ let app_state = state.room_back_history.borrow().last().cloned();
+ if let Some(app_state) = app_state {
+ debug!("Go back to state {:?}", app_state);
+ state.set_state(app_state);
} else {
// Fallback when there is no back history
debug!("There is no state to go back to. Go back to state NoRoom");
- if op.login_data.is_some() {
- op.set_state(AppState::NoRoom);
+ if state.login_data.is_some() {
+ state.set_state(AppState::NoRoom);
}
}
- }
+ });
}));
send_file.connect_activate(clone!(@weak app => move |_, _| {
@@ -310,22 +323,24 @@ pub fn new(app: >k::Application, app_runtime: AppRuntime, op: &Arc<Mutex<AppOp
}
}));
- send_message.connect_activate(clone!(@strong op => move |_, _| {
- let msg_entry = op.lock().unwrap().ui.sventry.view.clone();
- if let Some(buffer) = msg_entry.get_buffer() {
- let start = buffer.get_start_iter();
- let end = buffer.get_end_iter();
+ send_message.connect_activate(move |_, _| {
+ app_runtime.update_state_with(|state| {
+ let msg_entry = state.ui.sventry.view.clone();
+ if let Some(buffer) = msg_entry.get_buffer() {
+ let start = buffer.get_start_iter();
+ let end = buffer.get_end_iter();
- if let Some(text) = buffer.get_text(&start, &end, false) {
- op.lock().unwrap().send_message(text.to_string());
- }
+ if let Some(text) = buffer.get_text(&start, &end, false) {
+ state.send_message(text.to_string());
+ }
- buffer.set_text("");
- }
- }));
+ buffer.set_text("");
+ }
+ });
+ });
send_message.set_enabled(false);
- let buffer = op.lock().unwrap().ui.sventry.buffer.clone();
+ let buffer = appop.ui.sventry.buffer.clone();
buffer.connect_changed(move |buffer| {
if 0 < buffer.get_char_count() {
send_message.set_enabled(true);
diff --git a/fractal-gtk/src/app/mod.rs b/fractal-gtk/src/app/mod.rs
index bec097b1..7907970a 100644
--- a/fractal-gtk/src/app/mod.rs
+++ b/fractal-gtk/src/app/mod.rs
@@ -6,7 +6,6 @@ use lazy_static::lazy_static;
use libhandy::prelude::*;
use std::cell::RefCell;
use std::rc::Rc;
-use std::sync::{Arc, Mutex};
use tokio::runtime::Runtime as TokioRuntime;
use log::error;
@@ -22,11 +21,7 @@ mod windowstate;
use windowstate::WindowState;
-type GlobalState = Arc<Mutex<AppOp>>;
-
static mut APP_RUNTIME: Option<AppRuntime> = None;
-// TODO: Deprecated. It should be removed
-static mut OP: Option<GlobalState> = None;
lazy_static! {
pub static ref RUNTIME: TokioRuntime = TokioRuntime::new().unwrap();
@@ -49,22 +44,22 @@ macro_rules! APPOP {
pub struct AppRuntime(glib::Sender<Box<dyn FnOnce(&mut AppOp)>>);
impl AppRuntime {
- fn init(ui: uibuilder::UI) {
+ fn init(ui: uibuilder::UI) -> Self {
let (app_tx, app_rx) = glib::MainContext::channel(Default::default());
let app_runtime = Self(app_tx);
- let state = AppOp::new(ui, app_runtime.clone());
+ let mut state = AppOp::new(ui, app_runtime.clone());
unsafe {
- OP = Some(Arc::new(Mutex::new(state)));
- APP_RUNTIME = Some(app_runtime);
+ APP_RUNTIME = Some(app_runtime.clone());
}
- let state = get_op();
app_rx.attach(None, move |update_state| {
- update_state(&mut state.lock().unwrap());
+ update_state(&mut state);
glib::Continue(true)
});
+
+ app_runtime
}
pub fn update_state_with(&self, update_fn: impl FnOnce(&mut AppOp) + 'static) {
@@ -75,13 +70,14 @@ impl AppRuntime {
// Our application struct for containing all the state we have to carry around.
// TODO: subclass gtk::Application once possible
pub struct App {
+ app_runtime: AppRuntime,
ui: uibuilder::UI,
}
pub type AppRef = Rc<App>;
impl App {
- pub fn new(gtk_app: >k::Application) -> AppRef {
+ pub fn new(gtk_app: gtk::Application) -> AppRef {
// Set up the textdomain for gettext
setlocale(LocaleCategory::LcAll, "");
bindtextdomain("fractal", config::LOCALEDIR);
@@ -99,12 +95,8 @@ impl App {
gtk::STYLE_PROVIDER_PRIORITY_APPLICATION,
);
- let ui = uibuilder::UI::new();
- AppRuntime::init(ui.clone());
-
- ui.main_window.set_application(Some(gtk_app));
-
- ui.main_window.set_title("Fractal");
+ let ui = uibuilder::UI::new(gtk_app.clone());
+ let app_runtime = AppRuntime::init(ui.clone());
let settings: gio::Settings = gio::Settings::new("org.gnome.Fractal");
let window_state = WindowState::load_from_gsettings(&settings);
@@ -170,23 +162,25 @@ impl App {
.expect("Can't find main_content_stack in ui file.");
// Add login view to the main stack
- let login = widgets::LoginWidget::new(get_op());
+ let login = widgets::LoginWidget::new(app_runtime.clone());
main_stack.add_named(&login.container, "login");
- gtk_app.set_accels_for_action("login.back", &["Escape"]);
-
- actions::Global::new(gtk_app, get_app_runtime().clone(), get_op());
-
- let app = AppRef::new(Self { ui });
-
- get_app_runtime().update_state_with(|state| state.connect_gtk());
+ app_runtime.update_state_with(|state| {
+ state
+ .ui
+ .gtk_app
+ .set_accels_for_action("login.back", &["Escape"]);
+ actions::Global::new(state);
+ state.connect_gtk();
+ });
- app
+ AppRef::new(Self { app_runtime, ui })
}
pub fn on_startup(gtk_app: >k::Application) {
// Create application.
- let app = App::new(gtk_app);
+ let app = App::new(gtk_app.clone());
+ let app_runtime = app.app_runtime.clone();
// Initialize libhandy
libhandy::init();
@@ -197,8 +191,10 @@ impl App {
app.ui
.main_window
- .connect_property_has_toplevel_focus_notify(clone!(@weak app => move |_| {
- get_op().lock().unwrap().mark_active_room_messages();
+ .connect_property_has_toplevel_focus_notify(clone!(@strong app_runtime => move |_| {
+ app_runtime.update_state_with(|state| {
+ state.mark_active_room_messages();
+ });
}));
app.ui.main_window.connect_delete_event(move |window, _| {
@@ -211,7 +207,9 @@ impl App {
Inhibit(false)
});
- get_op().lock().unwrap().init();
+ app_runtime.update_state_with(|state| {
+ state.init();
+ });
// When the application is shut down we drop our app struct
let app_container = RefCell::new(Some(app));
@@ -230,15 +228,12 @@ impl App {
}
fn on_shutdown(self: AppRef) {
- get_op().lock().unwrap().quit();
+ self.app_runtime.update_state_with(|state| {
+ state.quit();
+ });
}
}
-// TODO: Deprecated. It should be removed
-pub fn get_op() -> &'static GlobalState {
- unsafe { OP.as_ref().expect("Fatal: AppOp has not been initialized") }
-}
-
pub fn get_app_runtime() -> &'static AppRuntime {
unsafe {
APP_RUNTIME
diff --git a/fractal-gtk/src/appop/connect/autocomplete.rs b/fractal-gtk/src/appop/connect/autocomplete.rs
index a55ac8bf..01af58d6 100644
--- a/fractal-gtk/src/appop/connect/autocomplete.rs
+++ b/fractal-gtk/src/appop/connect/autocomplete.rs
@@ -2,9 +2,10 @@ use gtk::prelude::*;
use crate::widgets;
+use crate::app::AppRuntime;
use crate::uibuilder::UI;
-pub fn connect(ui: &UI) {
+pub fn connect(ui: &UI, app_runtime: AppRuntime) {
let popover = ui
.builder
.get_object::<gtk::Popover>("autocomplete_popover")
@@ -18,5 +19,12 @@ pub fn connect(ui: &UI) {
.get_object("main_window")
.expect("Can't find main_window in ui file.");
- widgets::Autocomplete::new(window, ui.sventry.view.clone(), popover, listbox).connect();
+ widgets::Autocomplete::new(
+ app_runtime,
+ window,
+ ui.sventry.view.clone(),
+ popover,
+ listbox,
+ )
+ .connect();
}
diff --git a/fractal-gtk/src/appop/connect/mod.rs b/fractal-gtk/src/appop/connect/mod.rs
index 20e0b11e..2e7e9079 100644
--- a/fractal-gtk/src/appop/connect/mod.rs
+++ b/fractal-gtk/src/appop/connect/mod.rs
@@ -23,7 +23,7 @@ impl AppOp {
headerbar::connect(ui);
send::connect(ui, app_runtime.clone());
markdown::connect(ui, app_runtime.clone());
- autocomplete::connect(ui);
+ autocomplete::connect(ui, app_runtime.clone());
language::connect(ui, app_runtime.clone());
directory::connect(ui, app_runtime.clone());
leave_room::connect(ui, app_runtime.clone());
diff --git a/fractal-gtk/src/uibuilder.rs b/fractal-gtk/src/uibuilder.rs
index dfbd6835..1365e8ec 100644
--- a/fractal-gtk/src/uibuilder.rs
+++ b/fractal-gtk/src/uibuilder.rs
@@ -5,13 +5,14 @@ use gtk::{self, prelude::*};
#[derive(Clone, Debug)]
pub struct UI {
pub builder: gtk::Builder,
+ pub gtk_app: gtk::Application,
pub main_window: libhandy::ApplicationWindow,
pub sventry: SVEntry,
pub sventry_box: Box<gtk::Stack>,
}
impl UI {
- pub fn new() -> UI {
+ pub fn new(gtk_app: gtk::Application) -> UI {
// The order here is important because some ui file depends on others
let builder = gtk::Builder::new();
@@ -86,12 +87,15 @@ impl UI {
.add_from_resource("/org/gnome/Fractal/ui/account_settings.ui")
.expect("Can't load ui file: account_settings.ui");
- let main_window = builder
+ let main_window: libhandy::ApplicationWindow = builder
.get_object("main_window")
.expect("Couldn't find main_window in ui file.");
+ main_window.set_application(Some(>k_app));
+ main_window.set_title("Fractal");
UI {
builder,
+ gtk_app,
main_window,
sventry,
sventry_box,
diff --git a/fractal-gtk/src/widgets/autocomplete.rs b/fractal-gtk/src/widgets/autocomplete.rs
index 7244e314..29b8a499 100644
--- a/fractal-gtk/src/widgets/autocomplete.rs
+++ b/fractal-gtk/src/widgets/autocomplete.rs
@@ -3,18 +3,18 @@ use log::info;
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
-use std::sync::{Arc, Mutex};
use gtk::prelude::*;
use gtk::TextTag;
use crate::model::member::Member;
-use crate::app;
+use crate::app::AppRuntime;
use crate::appop::AppOp;
use crate::widgets;
pub struct Autocomplete {
+ app_runtime: AppRuntime,
entry: sourceview4::View,
listbox: gtk::ListBox,
popover: gtk::Popover,
@@ -23,18 +23,19 @@ pub struct Autocomplete {
popover_position: Option<i32>,
popover_search: Option<String>,
popover_closing: bool,
- op: Arc<Mutex<AppOp>>,
}
impl Autocomplete {
pub fn new(
+ app_runtime: AppRuntime,
window: gtk::Window,
- msg_entry: sourceview4::View,
+ entry: sourceview4::View,
popover: gtk::Popover,
listbox: gtk::ListBox,
) -> Autocomplete {
Autocomplete {
- entry: msg_entry,
+ app_runtime,
+ entry,
listbox,
popover,
window,
@@ -42,11 +43,11 @@ impl Autocomplete {
popover_position: None,
popover_search: None,
popover_closing: false,
- op: app::get_op().clone(),
}
}
pub fn connect(self) {
+ let app_runtime = self.app_runtime.clone();
let this: Rc<RefCell<Autocomplete>> = Rc::new(RefCell::new(self));
let context = this.borrow().entry.get_style_context();
@@ -275,42 +276,41 @@ impl Autocomplete {
}
if own.borrow().popover_position.is_some() {
- let list = {
- own.borrow()
- .autocomplete(text, buffer.get_property_cursor_position())
- };
- let widget_list = { own.borrow_mut().autocomplete_show_popover(list) };
- for (alias, widget) in widget_list.iter() {
- widget.connect_key_press_event(clone!(
- @strong own,
- @strong alias
- => move |_, ev| {
- own.borrow_mut().autocomplete_insert(alias.clone());
- let ev = {
- let ev: &gdk::Event = ev;
-
- ev.clone()
- .downcast::<gdk::EventKey>()
- .unwrap()
- };
- /* Submit on enter */
- if ev.get_keyval() == gdk::keys::constants::Return
- || ev.get_keyval() == gdk::keys::constants::Tab
- {
+ app_runtime.update_state_with(clone!(@strong own => move |state| {
+ let list = own
+ .borrow()
+ .autocomplete(text, buffer.get_property_cursor_position(), state);
+ let widget_list = own
+ .borrow_mut()
+ .autocomplete_show_popover(list, state);
+ for (alias, widget) in widget_list.iter() {
+ widget.connect_key_press_event(clone!(
+ @strong own,
+ @strong alias
+ => move |_, ev| {
+ own.borrow_mut().autocomplete_insert(alias.clone());
+ let ev = ev
+ .downcast_ref::<gdk::EventKey>()
+ .unwrap();
+ // Submit on enter
+ if ev.get_keyval() == gdk::keys::constants::Return
+ || ev.get_keyval() == gdk::keys::constants::Tab
+ {
+ own.borrow_mut().autocomplete_enter();
+ }
+ Inhibit(true)
+ }));
+
+ widget.connect_button_press_event(clone!(
+ @strong own,
+ @strong alias
+ => move |_, _| {
+ own.borrow_mut().autocomplete_insert(alias.clone());
own.borrow_mut().autocomplete_enter();
- }
- Inhibit(true)
- }));
-
- widget.connect_button_press_event(clone!(
- @strong own,
- @strong alias
- => move |_, _| {
- own.borrow_mut().autocomplete_insert(alias.clone());
- own.borrow_mut().autocomplete_enter();
- Inhibit(true)
- }));
- }
+ Inhibit(true)
+ }));
+ };
+ }));
}
}
}
@@ -423,33 +423,31 @@ impl Autocomplete {
pub fn autocomplete_show_popover(
&mut self,
list: Vec<Member>,
+ op: &AppOp,
) -> HashMap<String, gtk::EventBox> {
for ch in self.listbox.get_children().iter() {
self.listbox.remove(ch);
}
- let mut widget_list: HashMap<String, gtk::EventBox> = HashMap::new();
-
- if !list.is_empty() {
- for m in list.iter() {
- let alias = &m
+ let widget_list: HashMap<String, gtk::EventBox> = list
+ .iter()
+ .map(|member| {
+ let alias = member
.alias
.clone()
.unwrap_or_default()
.trim_end_matches(" (IRC)")
.to_owned();
- let widget;
- {
- let guard = self.op.lock().unwrap();
- let mb = widgets::MemberBox::new(&m, &guard);
- widget = mb.widget(true);
- }
+ let widget = widgets::MemberBox::new(&member, op).widget(true);
- let w = widget.clone();
- let a = alias.clone();
- widget_list.insert(a, w);
- self.listbox.add(&widget);
- }
+ (alias, widget)
+ })
+ .collect();
+
+ if !widget_list.is_empty() {
+ widget_list
+ .values()
+ .for_each(|widget| self.listbox.add(widget));
self.popover.set_relative_to(Some(&self.entry));
self.popover
@@ -472,10 +470,9 @@ impl Autocomplete {
widget_list
}
- pub fn autocomplete(&self, text: Option<String>, pos: i32) -> Vec<Member> {
+ pub fn autocomplete(&self, text: Option<String>, pos: i32, op: &AppOp) -> Vec<Member> {
let mut list: Vec<Member> = vec![];
- let guard = self.op.lock().unwrap();
- let rooms = &guard.rooms;
+ let rooms = &op.rooms;
match text {
None => {}
Some(txt) => {
@@ -495,7 +492,7 @@ impl Autocomplete {
};
/* Search for the 5 most recent active users */
- if let Some(aroom) = guard.active_room.clone() {
+ if let Some(aroom) = op.active_room.clone() {
if let Some(r) = rooms.get(&aroom) {
let mut count = 0;
for (_, m) in r.members.iter() {
diff --git a/fractal-gtk/src/widgets/login.rs b/fractal-gtk/src/widgets/login.rs
index cbd59caa..a4ea0fc4 100644
--- a/fractal-gtk/src/widgets/login.rs
+++ b/fractal-gtk/src/widgets/login.rs
@@ -8,8 +8,7 @@ use url::Url;
use crate::actions;
use crate::actions::global::AppState;
use crate::actions::login::LoginState;
-use crate::app::RUNTIME;
-use crate::appop::AppOp;
+use crate::app::{AppRuntime, RUNTIME};
use crate::globals;
use crate::util::i18n::i18n;
use crate::widgets::ErrorDialog;
@@ -17,7 +16,6 @@ use crate::widgets::ErrorDialog;
use crate::backend::register::get_well_known;
use std::convert::TryInto;
-use std::sync::{Arc, Mutex};
#[derive(Debug, Clone)]
pub struct LoginWidget {
@@ -31,7 +29,7 @@ pub struct LoginWidget {
}
impl LoginWidget {
- pub fn new(op: &Arc<Mutex<AppOp>>) -> Self {
+ pub fn new(app_runtime: AppRuntime) -> Self {
let widget = Self::default();
let server_entry = &widget.server_entry;
@@ -59,8 +57,6 @@ impl LoginWidget {
}
}));
- let op = op.clone();
-
let login = widget
.actions
.lookup_action("login")
@@ -126,11 +122,11 @@ impl LoginWidget {
.unwrap_or((homeserver_url, globals::DEFAULT_IDENTITYSERVER.clone()));
err_label.hide();
- op.lock().unwrap().set_state(AppState::Loading);
- op.lock().unwrap().since = None;
- op.lock()
- .unwrap()
- .connect(username, password, homeserver_url, idserver);
+ app_runtime.update_state_with(|state| {
+ state.set_state(AppState::Loading);
+ state.since = None;
+ state.connect(username, password, homeserver_url, idserver);
+ });
} else {
err_label.show();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]