Initial support for multiple account profiles
This commit is contained in:
parent
cd0fd30e69
commit
29e661ec5e
|
@ -0,0 +1,100 @@
|
|||
use gtk::prelude::*;
|
||||
use relm4::prelude::*;
|
||||
|
||||
use crate::settings::{self, Account};
|
||||
|
||||
use super::accounts_page::AccountsPageInput;
|
||||
|
||||
pub struct AccountRow {
|
||||
account: Account,
|
||||
index: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AccountRowInput {
|
||||
Select,
|
||||
Logout,
|
||||
Delete,
|
||||
}
|
||||
|
||||
#[relm4::factory(pub)]
|
||||
impl FactoryComponent for AccountRow {
|
||||
type Init = Account;
|
||||
type Input = AccountRowInput;
|
||||
type Output = AccountsPageInput;
|
||||
type ParentInput = AccountsPageInput;
|
||||
type ParentWidget = gtk::Box;
|
||||
type CommandOutput = ();
|
||||
|
||||
view! {
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Horizontal,
|
||||
|
||||
gtk::Label {
|
||||
#[watch]
|
||||
set_label: &format!("{} ({})", self.account.name, self.account.instance_url),
|
||||
add_controller = gtk::GestureClick {
|
||||
connect_pressed[sender] => move |_, _, _, _| {
|
||||
sender.input(AccountRowInput::Select);
|
||||
}
|
||||
},
|
||||
},
|
||||
gtk::Box {
|
||||
set_hexpand: true,
|
||||
},
|
||||
gtk::Button {
|
||||
set_icon_name: "system-log-out-symbolic",
|
||||
connect_clicked => AccountRowInput::Logout,
|
||||
},
|
||||
gtk::Button {
|
||||
set_icon_name: "edit-delete",
|
||||
connect_clicked => AccountRowInput::Delete,
|
||||
set_margin_start: 5,
|
||||
},
|
||||
},
|
||||
|
||||
gtk::Separator {
|
||||
set_margin_all: 10,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn init_model(init: Self::Init, index: &Self::Index, _sender: FactorySender<Self>) -> Self {
|
||||
Self {
|
||||
account: init,
|
||||
index: index.current_index(),
|
||||
}
|
||||
}
|
||||
|
||||
fn forward_to_parent(output: Self::Output) -> Option<Self::ParentInput> {
|
||||
Some(output)
|
||||
}
|
||||
|
||||
fn update(&mut self, message: Self::Input, sender: FactorySender<Self>) {
|
||||
match message {
|
||||
AccountRowInput::Select => {
|
||||
settings::update_account_index(self.index);
|
||||
let message = if self.account.instance_url.is_empty() {
|
||||
crate::AppMsg::ChooseInstance
|
||||
} else {
|
||||
crate::AppMsg::OpenPosts
|
||||
};
|
||||
sender
|
||||
.output_sender()
|
||||
.emit(AccountsPageInput::Forward(message))
|
||||
}
|
||||
AccountRowInput::Logout => {
|
||||
self.account.name = "".to_string();
|
||||
self.account.id = 0;
|
||||
self.account.jwt = None;
|
||||
settings::update_account(self.account.clone(), self.index);
|
||||
}
|
||||
AccountRowInput::Delete => sender
|
||||
.output_sender()
|
||||
.emit(AccountsPageInput::Remove(self.index)),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
use gtk::prelude::*;
|
||||
use relm4::{factory::FactoryVecDeque, prelude::*};
|
||||
|
||||
use crate::settings::{self, get_prefs, Account};
|
||||
|
||||
use super::account_row::AccountRow;
|
||||
|
||||
pub struct AccountsPage {
|
||||
accounts: FactoryVecDeque<AccountRow>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AccountsPageInput {
|
||||
Update,
|
||||
CreateNew,
|
||||
Remove(usize),
|
||||
Forward(crate::AppMsg),
|
||||
}
|
||||
|
||||
#[relm4::component(pub)]
|
||||
impl SimpleComponent for AccountsPage {
|
||||
type Init = ();
|
||||
type Input = AccountsPageInput;
|
||||
type Output = crate::AppMsg;
|
||||
|
||||
view! {
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
|
||||
gtk::Label {
|
||||
set_label: "Accounts",
|
||||
add_css_class: "font-very-bold",
|
||||
set_margin_top: 10,
|
||||
},
|
||||
|
||||
gtk::ScrolledWindow {
|
||||
set_vexpand: true,
|
||||
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
set_vexpand: true,
|
||||
set_margin_all: 10,
|
||||
|
||||
#[local_ref]
|
||||
accounts -> gtk::Box {
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
},
|
||||
|
||||
gtk::Button {
|
||||
set_label: "New",
|
||||
connect_clicked => AccountsPageInput::CreateNew,
|
||||
set_margin_top: 10,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn init(
|
||||
_init: Self::Init,
|
||||
root: &Self::Root,
|
||||
sender: ComponentSender<Self>,
|
||||
) -> ComponentParts<Self> {
|
||||
let accounts = FactoryVecDeque::new(gtk::Box::builder().build(), sender.input_sender());
|
||||
sender.input(AccountsPageInput::Update);
|
||||
|
||||
let model = Self { accounts };
|
||||
let accounts = model.accounts.widget();
|
||||
let widgets = view_output!();
|
||||
ComponentParts { model, widgets }
|
||||
}
|
||||
|
||||
fn update(&mut self, message: Self::Input, sender: ComponentSender<Self>) {
|
||||
match message {
|
||||
AccountsPageInput::Update => {
|
||||
self.accounts.guard().clear();
|
||||
for account in get_prefs().accounts {
|
||||
self.accounts.guard().push_back(account);
|
||||
}
|
||||
}
|
||||
AccountsPageInput::CreateNew => {
|
||||
self.accounts.guard().push_back(Account::default());
|
||||
settings::create_account(false);
|
||||
}
|
||||
AccountsPageInput::Remove(index) => {
|
||||
if index as u32 != get_prefs().current_account_index {
|
||||
self.accounts.guard().remove(index);
|
||||
settings::remove_account(index);
|
||||
// for now: update all to fix broken indexes
|
||||
sender.input(AccountsPageInput::Update);
|
||||
}
|
||||
}
|
||||
AccountsPageInput::Forward(msg) => {
|
||||
sender.output_sender().emit(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -128,7 +128,7 @@ impl SimpleComponent for InstancesPage {
|
|||
current_account.instance_url = url[0..url.len() - 1].to_string();
|
||||
current_account.jwt = None;
|
||||
settings::update_current_account(current_account);
|
||||
crate::AppMsg::ShowLogin
|
||||
crate::AppMsg::UpdateState(crate::AppState::Login)
|
||||
}
|
||||
Err(err) => crate::AppMsg::ShowMessage(err.to_string()),
|
||||
};
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
pub mod account_row;
|
||||
pub mod accounts_page;
|
||||
pub mod comment_row;
|
||||
pub mod communities_page;
|
||||
pub mod community_page;
|
||||
|
|
41
src/main.rs
41
src/main.rs
|
@ -7,6 +7,7 @@ pub mod util;
|
|||
|
||||
use api::{community::default_community, post::default_post, user::default_person};
|
||||
use components::{
|
||||
accounts_page::AccountsPage,
|
||||
communities_page::{CommunitiesPage, CommunitiesPageInput},
|
||||
community_page::{self, CommunityPage},
|
||||
inbox_page::{InboxInput, InboxPage},
|
||||
|
@ -45,6 +46,7 @@ pub enum AppState {
|
|||
Login,
|
||||
Message,
|
||||
Inbox,
|
||||
AccountsPage,
|
||||
}
|
||||
|
||||
struct App {
|
||||
|
@ -59,6 +61,7 @@ struct App {
|
|||
post_page: Controller<PostPage>,
|
||||
inbox_page: Controller<InboxPage>,
|
||||
login_page: Controller<LoginPage>,
|
||||
accounts_page: Controller<AccountsPage>,
|
||||
logged_in: bool,
|
||||
about_dialog: Controller<AboutDialog>,
|
||||
}
|
||||
|
@ -66,7 +69,6 @@ struct App {
|
|||
#[derive(Debug, Clone)]
|
||||
pub enum AppMsg {
|
||||
ChooseInstance,
|
||||
ShowLogin,
|
||||
LoggedIn,
|
||||
Logout,
|
||||
ShowMessage(String),
|
||||
|
@ -194,16 +196,22 @@ impl SimpleComponent for App {
|
|||
inbox_page -> gtk::Box {}
|
||||
}
|
||||
}
|
||||
AppState::AccountsPage => {
|
||||
gtk::Box {
|
||||
#[local_ref]
|
||||
accounts_page -> gtk::Box {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
menu! {
|
||||
menu_model: {
|
||||
"Choose Instance" => ChangeInstanceAction,
|
||||
"Profile" => ProfileAction,
|
||||
"Change Instance" => ChangeInstanceAction,
|
||||
"Accounts" => AccountsAction,
|
||||
"Login" => LoginAction,
|
||||
"Logout" => LogoutAction,
|
||||
"Profile" => ProfileAction,
|
||||
"About" => AboutAction
|
||||
}
|
||||
}
|
||||
|
@ -250,6 +258,9 @@ impl SimpleComponent for App {
|
|||
let login_page = LoginPage::builder()
|
||||
.launch(())
|
||||
.forward(sender.input_sender(), |msg| msg);
|
||||
let accounts_page = AccountsPage::builder()
|
||||
.launch(())
|
||||
.forward(sender.input_sender(), |msg| msg);
|
||||
|
||||
let model = App {
|
||||
state,
|
||||
|
@ -263,6 +274,7 @@ impl SimpleComponent for App {
|
|||
inbox_page,
|
||||
communities_page,
|
||||
login_page,
|
||||
accounts_page,
|
||||
message: None,
|
||||
about_dialog,
|
||||
};
|
||||
|
@ -281,6 +293,7 @@ impl SimpleComponent for App {
|
|||
let inbox_page = model.inbox_page.widget();
|
||||
let communities_page = model.communities_page.widget();
|
||||
let login_page = model.login_page.widget();
|
||||
let accounts_page = model.accounts_page.widget();
|
||||
|
||||
let widgets = view_output!();
|
||||
|
||||
|
@ -290,6 +303,10 @@ impl SimpleComponent for App {
|
|||
RelmAction::new_stateless(move |_| {
|
||||
instance_sender.input(AppMsg::ChooseInstance);
|
||||
});
|
||||
let accounts_sender = sender.clone();
|
||||
let accounts_action: RelmAction<AccountsAction> = RelmAction::new_stateless(move |_| {
|
||||
accounts_sender.input(AppMsg::UpdateState(AppState::AccountsPage));
|
||||
});
|
||||
let profile_sender = sender.clone();
|
||||
let profile_action: RelmAction<ProfileAction> = RelmAction::new_stateless(move |_| {
|
||||
let person = settings::get_current_account();
|
||||
|
@ -299,10 +316,7 @@ impl SimpleComponent for App {
|
|||
});
|
||||
let login_sender = sender.clone();
|
||||
let login_action: RelmAction<LoginAction> = RelmAction::new_stateless(move |_| {
|
||||
login_sender.input(AppMsg::ShowLogin);
|
||||
});
|
||||
let logout_action: RelmAction<LogoutAction> = RelmAction::new_stateless(move |_| {
|
||||
sender.input(AppMsg::Logout);
|
||||
login_sender.input(AppMsg::UpdateState(AppState::Login));
|
||||
});
|
||||
let about_action = {
|
||||
let sender = model.about_dialog.sender().clone();
|
||||
|
@ -313,9 +327,9 @@ impl SimpleComponent for App {
|
|||
|
||||
let mut group = RelmActionGroup::<WindowActionGroup>::new();
|
||||
group.add_action(instance_action);
|
||||
group.add_action(accounts_action);
|
||||
group.add_action(profile_action);
|
||||
group.add_action(login_action);
|
||||
group.add_action(logout_action);
|
||||
group.add_action(about_action);
|
||||
group.register_for_widget(&widgets.main_window);
|
||||
|
||||
|
@ -390,12 +404,11 @@ impl SimpleComponent for App {
|
|||
.emit(post_page::PostPageInput::UpdatePost(post));
|
||||
self.state = AppState::Post;
|
||||
}
|
||||
AppMsg::ShowLogin => {
|
||||
self.state = AppState::Login;
|
||||
}
|
||||
AppMsg::Logout => {
|
||||
let mut account = settings::get_current_account();
|
||||
account.jwt = None;
|
||||
account.name = "".to_string();
|
||||
account.id = 0;
|
||||
settings::update_current_account(account);
|
||||
self.logged_in = false;
|
||||
}
|
||||
|
@ -434,9 +447,9 @@ impl SimpleComponent for App {
|
|||
|
||||
relm4::new_action_group!(WindowActionGroup, "win");
|
||||
relm4::new_stateless_action!(ChangeInstanceAction, WindowActionGroup, "instance");
|
||||
relm4::new_stateless_action!(ProfileAction, WindowActionGroup, "profile");
|
||||
relm4::new_stateless_action!(AccountsAction, WindowActionGroup, "accounts");
|
||||
relm4::new_stateless_action!(LoginAction, WindowActionGroup, "login");
|
||||
relm4::new_stateless_action!(LogoutAction, WindowActionGroup, "logout");
|
||||
relm4::new_stateless_action!(ProfileAction, WindowActionGroup, "profile");
|
||||
relm4::new_stateless_action!(AboutAction, WindowActionGroup, "about");
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -45,14 +45,40 @@ pub fn get_prefs() -> Preferences {
|
|||
pub fn get_current_account() -> Account {
|
||||
let mut prefs = get_prefs();
|
||||
if prefs.accounts.len() == 0 {
|
||||
prefs.accounts.push(Account::default());
|
||||
save_prefs(&prefs);
|
||||
prefs = create_account(true);
|
||||
}
|
||||
prefs.accounts[prefs.current_account_index as usize].clone()
|
||||
}
|
||||
|
||||
pub fn update_current_account(account: Account) {
|
||||
let settings = get_prefs();
|
||||
update_account(account, settings.current_account_index as usize)
|
||||
}
|
||||
|
||||
pub fn update_account(account: Account, index: usize) {
|
||||
let mut settings = get_prefs();
|
||||
settings.accounts[settings.current_account_index as usize] = account;
|
||||
settings.accounts[index] = account;
|
||||
save_prefs(&settings);
|
||||
}
|
||||
|
||||
pub fn remove_account(index: usize) {
|
||||
let mut settings = get_prefs();
|
||||
settings.accounts.remove(index);
|
||||
save_prefs(&settings);
|
||||
}
|
||||
|
||||
pub fn create_account(reset_index: bool) -> Preferences {
|
||||
let mut prefs = get_prefs();
|
||||
prefs.accounts.push(Account::default());
|
||||
if reset_index {
|
||||
prefs.current_account_index = 0;
|
||||
}
|
||||
save_prefs(&prefs);
|
||||
prefs
|
||||
}
|
||||
|
||||
pub fn update_account_index(index: usize) {
|
||||
let mut prefs = get_prefs();
|
||||
prefs.current_account_index = index as u32;
|
||||
save_prefs(&prefs);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue