commit
4186358c39
|
@ -54,6 +54,11 @@ impl SimpleComponent for CommunityPage {
|
||||||
view! {
|
view! {
|
||||||
gtk::ScrolledWindow {
|
gtk::ScrolledWindow {
|
||||||
set_vexpand: false,
|
set_vexpand: false,
|
||||||
|
connect_edge_reached[sender] => move |_, pos| {
|
||||||
|
if pos == gtk::PositionType::Bottom && settings::get_prefs().infinite_scroll {
|
||||||
|
sender.input(CommunityInput::FetchPosts);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
gtk::Box {
|
gtk::Box {
|
||||||
set_orientation: gtk::Orientation::Vertical,
|
set_orientation: gtk::Orientation::Vertical,
|
||||||
|
|
|
@ -7,6 +7,8 @@ use relm4::{factory::FactoryVecDeque, prelude::*};
|
||||||
|
|
||||||
use crate::api;
|
use crate::api;
|
||||||
|
|
||||||
|
use crate::settings::get_prefs;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
post_row::PostRow,
|
post_row::PostRow,
|
||||||
sort_dropdown::{SortDropdown, SortDropdownOutput},
|
sort_dropdown::{SortDropdown, SortDropdownOutput},
|
||||||
|
@ -36,6 +38,13 @@ impl SimpleComponent for PostsPage {
|
||||||
view! {
|
view! {
|
||||||
gtk::ScrolledWindow {
|
gtk::ScrolledWindow {
|
||||||
set_hexpand: true,
|
set_hexpand: true,
|
||||||
|
connect_edge_reached[sender] => move |_, pos| {
|
||||||
|
if pos == gtk::PositionType::Bottom && get_prefs().infinite_scroll {
|
||||||
|
sender.input(
|
||||||
|
PostsPageInput::FetchPosts(model.posts_type, model.posts_order, false)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
gtk::Box {
|
gtk::Box {
|
||||||
set_orientation: gtk::Orientation::Vertical,
|
set_orientation: gtk::Orientation::Vertical,
|
||||||
|
|
|
@ -9,9 +9,9 @@ use crate::dialogs::editor::EditorDialog;
|
||||||
use crate::dialogs::editor::EditorOutput;
|
use crate::dialogs::editor::EditorOutput;
|
||||||
use crate::dialogs::editor::EditorType;
|
use crate::dialogs::editor::EditorType;
|
||||||
use crate::settings;
|
use crate::settings;
|
||||||
|
use crate::util::format_elapsed_time;
|
||||||
use crate::util::get_web_image_msg;
|
use crate::util::get_web_image_msg;
|
||||||
use crate::util::markdown_to_pango_markup;
|
use crate::util::markdown_to_pango_markup;
|
||||||
use crate::util::format_elapsed_time;
|
|
||||||
|
|
||||||
use super::comment_row::CommentRow;
|
use super::comment_row::CommentRow;
|
||||||
use super::moderates_row::ModeratesRow;
|
use super::moderates_row::ModeratesRow;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
pub mod about;
|
pub mod about;
|
||||||
pub mod editor;
|
pub mod editor;
|
||||||
|
pub mod settings;
|
||||||
pub mod site_info;
|
pub mod site_info;
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
use crate::settings::{get_prefs, save_prefs};
|
||||||
|
use gtk::prelude::*;
|
||||||
|
use relm4::prelude::*;
|
||||||
|
|
||||||
|
pub struct Settings {
|
||||||
|
visible: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum SettingsInput {
|
||||||
|
Show,
|
||||||
|
Hide,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[relm4::component(pub)]
|
||||||
|
impl SimpleComponent for Settings {
|
||||||
|
type Init = ();
|
||||||
|
type Input = SettingsInput;
|
||||||
|
type Output = crate::AppMsg;
|
||||||
|
|
||||||
|
view! {
|
||||||
|
dialog = gtk::Dialog {
|
||||||
|
#[watch]
|
||||||
|
set_visible: model.visible,
|
||||||
|
set_modal: true,
|
||||||
|
set_title: Some("Settings"),
|
||||||
|
connect_close_request[sender] => move |_| {
|
||||||
|
sender.input(SettingsInput::Hide);
|
||||||
|
gtk::Inhibit(false)
|
||||||
|
},
|
||||||
|
|
||||||
|
#[wrap(Some)]
|
||||||
|
set_titlebar = >k::HeaderBar{
|
||||||
|
set_show_title_buttons: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
gtk::ScrolledWindow {
|
||||||
|
set_size_request: (400, 400),
|
||||||
|
|
||||||
|
gtk::Box {
|
||||||
|
set_orientation: gtk::Orientation::Vertical,
|
||||||
|
set_spacing: 5,
|
||||||
|
set_margin_all: 15,
|
||||||
|
|
||||||
|
gtk::CheckButton {
|
||||||
|
set_active: get_prefs().infinite_scroll,
|
||||||
|
set_margin_all: 12,
|
||||||
|
set_label: Some("Infinite scroll"),
|
||||||
|
set_tooltip:"Fetch new content automatically when scrolling down",
|
||||||
|
connect_toggled => move |checkbox| {
|
||||||
|
let mut prefs = get_prefs();
|
||||||
|
prefs.infinite_scroll = checkbox.is_active();
|
||||||
|
save_prefs(&prefs);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init(
|
||||||
|
_init: Self::Init,
|
||||||
|
root: &Self::Root,
|
||||||
|
sender: ComponentSender<Self>,
|
||||||
|
) -> ComponentParts<Self> {
|
||||||
|
let model = Self { visible: false };
|
||||||
|
let widgets = view_output!();
|
||||||
|
ComponentParts { model, widgets }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, message: Self::Input, _sender: ComponentSender<Self>) {
|
||||||
|
match message {
|
||||||
|
SettingsInput::Show => {
|
||||||
|
self.visible = true;
|
||||||
|
}
|
||||||
|
SettingsInput::Hide => {
|
||||||
|
self.visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
src/main.rs
16
src/main.rs
|
@ -19,6 +19,7 @@ use components::{
|
||||||
};
|
};
|
||||||
use dialogs::{
|
use dialogs::{
|
||||||
about::AboutDialog,
|
about::AboutDialog,
|
||||||
|
settings::Settings,
|
||||||
site_info::{SiteInfo, SiteInfoInput},
|
site_info::{SiteInfo, SiteInfoInput},
|
||||||
};
|
};
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
|
@ -68,6 +69,7 @@ struct App {
|
||||||
login_page: Controller<LoginPage>,
|
login_page: Controller<LoginPage>,
|
||||||
accounts_page: Controller<AccountsPage>,
|
accounts_page: Controller<AccountsPage>,
|
||||||
saved_page: Controller<ProfilePage>,
|
saved_page: Controller<ProfilePage>,
|
||||||
|
settings_dialog: Controller<Settings>,
|
||||||
about_dialog: Controller<AboutDialog>,
|
about_dialog: Controller<AboutDialog>,
|
||||||
site_info: Controller<SiteInfo>,
|
site_info: Controller<SiteInfo>,
|
||||||
logged_in: bool,
|
logged_in: bool,
|
||||||
|
@ -222,6 +224,7 @@ impl SimpleComponent for App {
|
||||||
"Login" => LoginAction,
|
"Login" => LoginAction,
|
||||||
"Profile" => ProfileAction,
|
"Profile" => ProfileAction,
|
||||||
"Site Info" => SiteInfoAction,
|
"Site Info" => SiteInfoAction,
|
||||||
|
"Settings" => SettingsAction,
|
||||||
"About" => AboutAction
|
"About" => AboutAction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -262,6 +265,7 @@ impl SimpleComponent for App {
|
||||||
let communities_page = CommunitiesPage::builder()
|
let communities_page = CommunitiesPage::builder()
|
||||||
.launch(())
|
.launch(())
|
||||||
.forward(sender.input_sender(), |msg| msg);
|
.forward(sender.input_sender(), |msg| msg);
|
||||||
|
let settings_dialog = dialogs::settings::Settings::builder().launch(()).detach();
|
||||||
let about_dialog = AboutDialog::builder()
|
let about_dialog = AboutDialog::builder()
|
||||||
.launch(root.toplevel_window().unwrap())
|
.launch(root.toplevel_window().unwrap())
|
||||||
.detach();
|
.detach();
|
||||||
|
@ -293,6 +297,7 @@ impl SimpleComponent for App {
|
||||||
accounts_page,
|
accounts_page,
|
||||||
message: None,
|
message: None,
|
||||||
about_dialog,
|
about_dialog,
|
||||||
|
settings_dialog,
|
||||||
saved_page,
|
saved_page,
|
||||||
site_info,
|
site_info,
|
||||||
logged_in,
|
logged_in,
|
||||||
|
@ -340,7 +345,6 @@ impl SimpleComponent for App {
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
let login_action: RelmAction<LoginAction> = {
|
let login_action: RelmAction<LoginAction> = {
|
||||||
let sender = sender.clone();
|
|
||||||
RelmAction::new_stateless(move |_| {
|
RelmAction::new_stateless(move |_| {
|
||||||
sender.input(AppMsg::UpdateState(AppState::Login));
|
sender.input(AppMsg::UpdateState(AppState::Login));
|
||||||
})
|
})
|
||||||
|
@ -351,6 +355,14 @@ impl SimpleComponent for App {
|
||||||
sender.emit(SiteInfoInput::Fetch);
|
sender.emit(SiteInfoInput::Fetch);
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
let settings_action = {
|
||||||
|
let sender = model.settings_dialog.sender().clone();
|
||||||
|
RelmAction::<SettingsAction>::new_stateless(move |_| {
|
||||||
|
sender
|
||||||
|
.send(dialogs::settings::SettingsInput::Show)
|
||||||
|
.unwrap_or_default();
|
||||||
|
})
|
||||||
|
};
|
||||||
let about_action = {
|
let about_action = {
|
||||||
let sender = model.about_dialog.sender().clone();
|
let sender = model.about_dialog.sender().clone();
|
||||||
RelmAction::<AboutAction>::new_stateless(move |_| {
|
RelmAction::<AboutAction>::new_stateless(move |_| {
|
||||||
|
@ -364,6 +376,7 @@ impl SimpleComponent for App {
|
||||||
group.add_action(profile_action);
|
group.add_action(profile_action);
|
||||||
group.add_action(login_action);
|
group.add_action(login_action);
|
||||||
group.add_action(site_info_action);
|
group.add_action(site_info_action);
|
||||||
|
group.add_action(settings_action);
|
||||||
group.add_action(about_action);
|
group.add_action(about_action);
|
||||||
group.register_for_widget(&widgets.main_window);
|
group.register_for_widget(&widgets.main_window);
|
||||||
|
|
||||||
|
@ -493,6 +506,7 @@ relm4::new_stateless_action!(AccountsAction, WindowActionGroup, "accounts");
|
||||||
relm4::new_stateless_action!(LoginAction, WindowActionGroup, "login");
|
relm4::new_stateless_action!(LoginAction, WindowActionGroup, "login");
|
||||||
relm4::new_stateless_action!(ProfileAction, WindowActionGroup, "profile");
|
relm4::new_stateless_action!(ProfileAction, WindowActionGroup, "profile");
|
||||||
relm4::new_stateless_action!(SiteInfoAction, WindowActionGroup, "site_info");
|
relm4::new_stateless_action!(SiteInfoAction, WindowActionGroup, "site_info");
|
||||||
|
relm4::new_stateless_action!(SettingsAction, WindowActionGroup, "settings");
|
||||||
relm4::new_stateless_action!(AboutAction, WindowActionGroup, "about");
|
relm4::new_stateless_action!(AboutAction, WindowActionGroup, "about");
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -12,10 +12,21 @@ pub struct Account {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Default)]
|
#[derive(Deserialize, Serialize)]
|
||||||
pub struct Preferences {
|
pub struct Preferences {
|
||||||
pub accounts: Vec<Account>,
|
pub accounts: Vec<Account>,
|
||||||
pub current_account_index: u32,
|
pub current_account_index: u32,
|
||||||
|
pub infinite_scroll: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Preferences {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
accounts: vec![],
|
||||||
|
current_account_index: 0,
|
||||||
|
infinite_scroll: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn data_path() -> PathBuf {
|
pub fn data_path() -> PathBuf {
|
||||||
|
|
Loading…
Reference in New Issue