Share whether to use the server across screens

This commit is contained in:
Elias Projahn 2021-05-07 20:44:27 +02:00
parent f92a80be87
commit df6e2e86c7
16 changed files with 76 additions and 31 deletions

View file

@ -2,13 +2,10 @@ use gio::prelude::*;
use log::warn;
use musicus_client::{Client, LoginData};
use musicus_database::DbThread;
use std::cell::RefCell;
use std::cell::{Cell, RefCell};
use std::path::PathBuf;
use std::rc::Rc;
use tokio::sync::{
broadcast,
broadcast::Sender,
};
use tokio::sync::{broadcast, broadcast::Sender};
pub use musicus_client as client;
pub use musicus_database as db;
@ -52,6 +49,9 @@ pub struct Backend {
/// Access to GSettings.
settings: gio::Settings,
/// Whether the server should be used by default when searching for or changing items.
use_server: Cell<bool>,
/// The current path to the music library, which is used by the player and the database. This
/// is guaranteed to be Some, when the state is set to BackendState::Ready.
music_library_path: RefCell<Option<PathBuf>>,
@ -83,6 +83,7 @@ impl Backend {
Backend {
state_sender,
settings: gio::Settings::new("de.johrpan.musicus"),
use_server: Cell::new(true),
music_library_path: RefCell::new(None),
library_updated_sender,
database: RefCell::new(None),
@ -127,6 +128,16 @@ impl Backend {
Ok(())
}
/// Whether the server should be used by default.
pub fn use_server(&self) -> bool {
self.use_server.get()
}
/// Set whether the server should be used by default.
pub fn set_use_server(&self, enabled: bool) {
self.use_server.set(enabled);
}
/// Set the URL of the Musicus server to connect to.
pub fn set_server_url(&self, url: &str) {
if let Err(err) = self.settings.set_string("server-url", url) {

View file

@ -16,7 +16,7 @@ pub struct EnsembleEditor {
editor: Editor,
name: EntryRow,
upload: UploadSection,
upload: Rc<UploadSection>,
}
impl Screen<Option<Ensemble>, Ensemble> for EnsembleEditor {
@ -33,7 +33,7 @@ impl Screen<Option<Ensemble>, Ensemble> for EnsembleEditor {
list.append(&name.widget);
let section = Section::new(&gettext("General"), &list);
let upload = UploadSection::new();
let upload = UploadSection::new(Rc::clone(&handle.backend));
editor.add_content(&section.widget);
editor.add_content(&upload.widget);

View file

@ -16,7 +16,7 @@ pub struct InstrumentEditor {
editor: Editor,
name: EntryRow,
upload: UploadSection,
upload: Rc<UploadSection>,
}
impl Screen<Option<Instrument>, Instrument> for InstrumentEditor {
@ -33,7 +33,7 @@ impl Screen<Option<Instrument>, Instrument> for InstrumentEditor {
list.append(&name.widget);
let section = Section::new(&gettext("General"), &list);
let upload = UploadSection::new();
let upload = UploadSection::new(Rc::clone(&handle.backend));
editor.add_content(&section.widget);
editor.add_content(&upload.widget);

View file

@ -17,7 +17,7 @@ pub struct PersonEditor {
editor: Editor,
first_name: EntryRow,
last_name: EntryRow,
upload: UploadSection,
upload: Rc<UploadSection>,
}
impl Screen<Option<Person>, Person> for PersonEditor {
@ -37,7 +37,7 @@ impl Screen<Option<Person>, Person> for PersonEditor {
list.append(&last_name.widget);
let section = Section::new(&gettext("General"), &list);
let upload = UploadSection::new();
let upload = UploadSection::new(Rc::clone(&handle.backend));
editor.add_content(&section.widget);
editor.add_content(&upload.widget);

View file

@ -45,6 +45,8 @@ impl Screen<Option<Recording>, Recording> for RecordingEditor {
get_widget!(builder, gtk::Frame, performance_frame);
get_widget!(builder, gtk::Button, add_performer_button);
upload_switch.set_active(handle.backend.use_server());
let performance_list = List::new();
performance_frame.set_child(Some(&performance_list.widget));

View file

@ -97,6 +97,8 @@ impl Screen<Option<Work>, Work> for WorkEditor {
None => (generate_id(), None, Vec::new(), Vec::new()),
};
upload_switch.set_active(handle.backend.use_server());
let this = Rc::new(Self {
handle,
widget,

View file

@ -119,6 +119,8 @@ impl Screen<Arc<ImportSession>, ()> for ImportScreen {
get_widget!(builder, gtk::Button, select_button);
get_widget!(builder, gtk::Button, add_button);
server_check_button.set_active(handle.backend.use_server());
let this = Rc::new(Self {
handle,
session,
@ -136,6 +138,7 @@ impl Screen<Arc<ImportSession>, ()> for ImportScreen {
}));
this.server_check_button.connect_toggled(clone!(@weak this => move |_| {
this.handle.backend.set_use_server(this.server_check_button.get_active());
this.load_matches();
}));

View file

@ -47,6 +47,8 @@ impl Screen<(Arc<ImportSession>, Option<Medium>), Medium> for MediumEditor {
get_widget!(builder, gtk::Button, try_again_button);
get_widget!(builder, gtk::Button, cancel_button);
publish_switch.set_active(handle.backend.use_server());
let list = List::new();
frame.set_child(Some(&list.widget));
@ -100,6 +102,10 @@ impl Screen<(Arc<ImportSession>, Option<Medium>), Medium> for MediumEditor {
});
}));
this.publish_switch.connect_property_state_notify(clone!(@weak this => move |_| {
this.handle.backend.set_use_server(this.publish_switch.get_state());
}));
this.track_set_list
.set_make_widget_cb(clone!(@weak this => move |index| {
let track_set = &this.track_sets.borrow()[index];

View file

@ -20,7 +20,7 @@ impl Screen<(), Ensemble> for EnsembleSelector {
fn new(_: (), handle: NavigationHandle<Ensemble>) -> Rc<Self> {
// Create UI
let selector = Selector::<Ensemble>::new();
let selector = Selector::<Ensemble>::new(Rc::clone(&handle.backend));
selector.set_title(&gettext("Select ensemble"));
let this = Rc::new(Self {

View file

@ -20,7 +20,7 @@ impl Screen<(), Instrument> for InstrumentSelector {
fn new(_: (), handle: NavigationHandle<Instrument>) -> Rc<Self> {
// Create UI
let selector = Selector::<Instrument>::new();
let selector = Selector::<Instrument>::new(Rc::clone(&handle.backend));
selector.set_title(&gettext("Select instrument"));
let this = Rc::new(Self {

View file

@ -35,7 +35,7 @@ impl Screen<(), Medium> for MediumSelector {
fn new(_: (), handle: NavigationHandle<Medium>) -> Rc<Self> {
// Create UI
let selector = Selector::<PersonOrEnsemble>::new();
let selector = Selector::<PersonOrEnsemble>::new(Rc::clone(&handle.backend));
selector.set_title(&gettext("Select performer"));
let this = Rc::new(Self {
@ -127,7 +127,7 @@ struct MediumSelectorMediumScreen {
impl Screen<PersonOrEnsemble, Medium> for MediumSelectorMediumScreen {
fn new(poe: PersonOrEnsemble, handle: NavigationHandle<Medium>) -> Rc<Self> {
let selector = Selector::<Medium>::new();
let selector = Selector::<Medium>::new(Rc::clone(&handle.backend));
selector.set_title(&gettext("Select medium"));
selector.set_subtitle(&poe.get_title());

View file

@ -20,7 +20,7 @@ impl Screen<(), Person> for PersonSelector {
fn new(_: (), handle: NavigationHandle<Person>) -> Rc<Self> {
// Create UI
let selector = Selector::<Person>::new();
let selector = Selector::<Person>::new(Rc::clone(&handle.backend));
selector.set_title(&gettext("Select person"));
let this = Rc::new(Self {

View file

@ -19,7 +19,7 @@ impl Screen<(), Recording> for RecordingSelector {
fn new(_: (), handle: NavigationHandle<Recording>) -> Rc<Self> {
// Create UI
let selector = Selector::<Person>::new();
let selector = Selector::<Person>::new(Rc::clone(&handle.backend));
selector.set_title(&gettext("Select composer"));
let this = Rc::new(Self {
@ -109,7 +109,7 @@ struct RecordingSelectorWorkScreen {
impl Screen<Person, Work> for RecordingSelectorWorkScreen {
fn new(person: Person, handle: NavigationHandle<Work>) -> Rc<Self> {
let selector = Selector::<Work>::new();
let selector = Selector::<Work>::new(Rc::clone(&handle.backend));
selector.set_title(&gettext("Select work"));
selector.set_subtitle(&person.name_fl());
@ -174,7 +174,7 @@ struct RecordingSelectorRecordingScreen {
impl Screen<Work, Recording> for RecordingSelectorRecordingScreen {
fn new(work: Work, handle: NavigationHandle<Recording>) -> Rc<Self> {
let selector = Selector::<Recording>::new();
let selector = Selector::<Recording>::new(Rc::clone(&handle.backend));
selector.set_title(&gettext("Select recording"));
selector.set_subtitle(&work.get_title());

View file

@ -2,7 +2,7 @@ use crate::widgets::List;
use glib::clone;
use gtk::prelude::*;
use gtk_macros::get_widget;
use musicus_backend::Result;
use musicus_backend::{Backend, Result};
use std::cell::RefCell;
use std::future::Future;
use std::pin::Pin;
@ -12,6 +12,7 @@ use std::rc::Rc;
/// database and to search within the list.
pub struct Selector<T: 'static> {
pub widget: gtk::Box,
backend: Rc<Backend>,
title_label: gtk::Label,
subtitle_label: gtk::Label,
search_entry: gtk::SearchEntry,
@ -28,8 +29,9 @@ pub struct Selector<T: 'static> {
}
impl<T> Selector<T> {
/// Create a new selector.
pub fn new() -> Rc<Self> {
/// Create a new selector. `use_server` is used to decide whether to search
/// online initially.
pub fn new(backend: Rc<Backend>) -> Rc<Self> {
// Create UI
let builder = gtk::Builder::from_resource("/de/johrpan/musicus/ui/selector.ui");
@ -50,6 +52,7 @@ impl<T> Selector<T> {
let this = Rc::new(Self {
widget,
backend,
title_label,
subtitle_label,
search_entry,
@ -85,7 +88,10 @@ impl<T> Selector<T> {
this.server_check_button
.connect_toggled(clone!(@strong this => move |_| {
if this.server_check_button.get_active() {
let active = this.server_check_button.get_active();
this.backend.set_use_server(active);
if active {
this.clone().load_online();
} else {
this.clone().load_local();
@ -117,7 +123,11 @@ impl<T> Selector<T> {
}));
// Initialize
if this.backend.use_server() {
this.clone().load_online();
} else {
this.server_check_button.set_active(false);
}
this
}

View file

@ -19,7 +19,7 @@ impl Screen<(), Work> for WorkSelector {
fn new(_: (), handle: NavigationHandle<Work>) -> Rc<Self> {
// Create UI
let selector = Selector::<Person>::new();
let selector = Selector::<Person>::new(Rc::clone(&handle.backend));
selector.set_title(&gettext("Select composer"));
let this = Rc::new(Self {
@ -99,7 +99,7 @@ struct WorkSelectorWorkScreen {
impl Screen<Person, Work> for WorkSelectorWorkScreen {
fn new(person: Person, handle: NavigationHandle<Work>) -> Rc<Self> {
let selector = Selector::<Work>::new();
let selector = Selector::<Work>::new(Rc::clone(&handle.backend));
selector.set_title(&gettext("Select work"));
selector.set_subtitle(&person.name_fl());

View file

@ -1,26 +1,30 @@
use super::Section;
use gettextrs::gettext;
use glib::clone;
use libadwaita::prelude::*;
use musicus_backend::Backend;
use std::rc::Rc;
/// A section showing a switch to enable uploading an item.
pub struct UploadSection {
/// The GTK widget of the wrapped section.
pub widget: gtk::Box,
backend: Rc<Backend>,
/// The upload switch.
switch: gtk::Switch,
}
impl UploadSection {
/// Create a new upload section which will be initially switched on.
pub fn new() -> Self {
pub fn new(backend: Rc<Backend>) -> Rc<Self> {
let list = gtk::ListBoxBuilder::new()
.selection_mode(gtk::SelectionMode::None)
.build();
let switch = gtk::SwitchBuilder::new()
.active(true)
.active(backend.use_server())
.valign(gtk::Align::Center)
.build();
@ -35,10 +39,17 @@ impl UploadSection {
let section = Section::new(&gettext("Upload"), &list);
Self {
let this = Rc::new(Self {
widget: section.widget.clone(),
backend,
switch,
}
});
this.switch.connect_property_state_notify(clone!(@weak this => move |_| {
this.backend.set_use_server(this.switch.get_state());
}));
this
}
/// Return whether the user has enabled the upload switch.