|
@@ -1,4 +1,8 @@
|
|
|
use cli_clipboard::ClipboardProvider as _;
|
|
use cli_clipboard::ClipboardProvider as _;
|
|
|
|
|
+use client_shared::message::{self, MessageSanitized};
|
|
|
|
|
+use client_shared::utils::ConnectionError;
|
|
|
|
|
+use client_shared::{DEFAULT_PASSWORD, MAX_MESSAGE_LENGTH, MAX_USERNAME_LENGTH};
|
|
|
|
|
+use client_shared::ui::Language;
|
|
|
use cursive::view::{Nameable as _, Resizable as _};
|
|
use cursive::view::{Nameable as _, Resizable as _};
|
|
|
use cursive::views::{
|
|
use cursive::views::{
|
|
|
Button, Dialog, DummyView, EditView, LinearLayout, NamedView, Panel, ScrollView, SelectView,
|
|
Button, Dialog, DummyView, EditView, LinearLayout, NamedView, Panel, ScrollView, SelectView,
|
|
@@ -7,11 +11,9 @@ use cursive::views::{
|
|
|
use cursive::{event, Cursive};
|
|
use cursive::{event, Cursive};
|
|
|
use utils::hash::Hashable as _;
|
|
use utils::hash::Hashable as _;
|
|
|
|
|
|
|
|
-use crate::actions::{self, NetworkError};
|
|
|
|
|
-use crate::message::MessageSanitized;
|
|
|
|
|
|
|
+use crate::actions;
|
|
|
use crate::{
|
|
use crate::{
|
|
|
- get_appdata, message, save_appdata, Appdata, DEFAULT_PASSWORD, MAX_MESSAGE_LENGTH,
|
|
|
|
|
- MAX_USERNAME_LENGTH,
|
|
|
|
|
|
|
+ get_appdata, save_appdata, Appdata
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
pub const USERS_PANEL_ID: &str = "users_view_id";
|
|
pub const USERS_PANEL_ID: &str = "users_view_id";
|
|
@@ -29,6 +31,7 @@ pub const CURRENT_USERNAME_PANEL_ID: &str = "current_username_view_id";
|
|
|
pub const USERNAME_FIELD_ID: &str = "username_field_id";
|
|
pub const USERNAME_FIELD_ID: &str = "username_field_id";
|
|
|
pub const USERNAME_BUTTON_ID: &str = "username_button_id";
|
|
pub const USERNAME_BUTTON_ID: &str = "username_button_id";
|
|
|
pub const REFRESH_BUTTON_ID: &str = "refresh_button_id";
|
|
pub const REFRESH_BUTTON_ID: &str = "refresh_button_id";
|
|
|
|
|
+pub const QUIT_BUTTON_ID: &str = "quit_button_id";
|
|
|
pub const BLOCKED_WORDS_BUTTON_ID: &str = "blocked_words_view_id";
|
|
pub const BLOCKED_WORDS_BUTTON_ID: &str = "blocked_words_view_id";
|
|
|
pub const SERVER_SETTINGS_ADDRESS_FIELD_ID: &str = "server_settings_address_field_id";
|
|
pub const SERVER_SETTINGS_ADDRESS_FIELD_ID: &str = "server_settings_address_field_id";
|
|
|
pub const SERVER_SETTINGS_REFRESH_FIELD_ID: &str = "server_settings_refresh_field_id";
|
|
pub const SERVER_SETTINGS_REFRESH_FIELD_ID: &str = "server_settings_refresh_field_id";
|
|
@@ -38,7 +41,7 @@ pub const INFO_BUTTON_ID: &str = "INFO_BUTTON_ID";
|
|
|
|
|
|
|
|
pub const DIALOGUE_MIN_SIZE: (u16, u16) = (20, 5);
|
|
pub const DIALOGUE_MIN_SIZE: (u16, u16) = (20, 5);
|
|
|
pub const SERVER_SETTINGS_FIELD_SIZE: (usize, usize) = (60, 1);
|
|
pub const SERVER_SETTINGS_FIELD_SIZE: (usize, usize) = (60, 1);
|
|
|
-pub const USER_PANEL_SIZE: usize = crate::MAX_USERNAME_LENGTH + 2;
|
|
|
|
|
|
|
+pub const USER_PANEL_SIZE: usize = MAX_USERNAME_LENGTH + 2;
|
|
|
|
|
|
|
|
#[allow(unused)]
|
|
#[allow(unused)]
|
|
|
pub enum Labels {
|
|
pub enum Labels {
|
|
@@ -67,8 +70,8 @@ pub enum Labels {
|
|
|
InvalidMessage,
|
|
InvalidMessage,
|
|
|
Success,
|
|
Success,
|
|
|
SuccessfullySentMessage,
|
|
SuccessfullySentMessage,
|
|
|
- FailedToSendMessage(NetworkError),
|
|
|
|
|
- FailedToLoadMessages(NetworkError),
|
|
|
|
|
|
|
+ FailedToSendMessage(ConnectionError),
|
|
|
|
|
+ FailedToLoadMessages(ConnectionError),
|
|
|
RefreshButton,
|
|
RefreshButton,
|
|
|
BlockedWords,
|
|
BlockedWords,
|
|
|
ServerSettings,
|
|
ServerSettings,
|
|
@@ -79,17 +82,11 @@ pub enum Labels {
|
|
|
Time,
|
|
Time,
|
|
|
Sender,
|
|
Sender,
|
|
|
Content,
|
|
Content,
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-#[derive(Debug, Clone, Copy)]
|
|
|
|
|
-pub enum Language {
|
|
|
|
|
- English,
|
|
|
|
|
- Dutch,
|
|
|
|
|
- Japanese,
|
|
|
|
|
|
|
+ QuitButton,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
impl Labels {
|
|
impl Labels {
|
|
|
- // TODO: Double check the translations
|
|
|
|
|
|
|
+ // TODO (low): Double check the translations
|
|
|
pub fn localize<'a>(&self, language: Language) -> String {
|
|
pub fn localize<'a>(&self, language: Language) -> String {
|
|
|
let buf: [String; 3];
|
|
let buf: [String; 3];
|
|
|
|
|
|
|
@@ -121,14 +118,14 @@ impl Labels {
|
|
|
let reason_buf: [String; 3];
|
|
let reason_buf: [String; 3];
|
|
|
|
|
|
|
|
match e {
|
|
match e {
|
|
|
- NetworkError::ReqwestError(_) => {
|
|
|
|
|
|
|
+ ConnectionError::ReqwestError(_) => {
|
|
|
reason_buf = [
|
|
reason_buf = [
|
|
|
"Connection error.".to_string(),
|
|
"Connection error.".to_string(),
|
|
|
"Verbindingsfout.".to_string(),
|
|
"Verbindingsfout.".to_string(),
|
|
|
"接続エラー。".to_string(),
|
|
"接続エラー。".to_string(),
|
|
|
];
|
|
];
|
|
|
}
|
|
}
|
|
|
- NetworkError::StatusCodeError(code) => {
|
|
|
|
|
|
|
+ ConnectionError::StatusCodeError(code) => {
|
|
|
// NOTE: Needs to match the server
|
|
// NOTE: Needs to match the server
|
|
|
if *code == 400 {
|
|
if *code == 400 {
|
|
|
reason_buf = [
|
|
reason_buf = [
|
|
@@ -144,20 +141,21 @@ impl Labels {
|
|
|
]
|
|
]
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- NetworkError::InvalidUrl => {
|
|
|
|
|
|
|
+ ConnectionError::UrlError(_) => {
|
|
|
reason_buf = [
|
|
reason_buf = [
|
|
|
"Invalid URL.".to_string(),
|
|
"Invalid URL.".to_string(),
|
|
|
"Ongeldig URL.".to_string(),
|
|
"Ongeldig URL.".to_string(),
|
|
|
"無効なURL。".to_string(),
|
|
"無効なURL。".to_string(),
|
|
|
];
|
|
];
|
|
|
}
|
|
}
|
|
|
- NetworkError::EncryptionError(_) => {
|
|
|
|
|
- reason_buf = [
|
|
|
|
|
- "Encryption error.".to_string(),
|
|
|
|
|
- "Encryptiefout.".to_string(),
|
|
|
|
|
- "暗号化エラー。".to_string(),
|
|
|
|
|
- ];
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // TODO: Check if it's safe to remove this.
|
|
|
|
|
+ // ConnectionError::EncryptionError(_) => {
|
|
|
|
|
+ // reason_buf = [
|
|
|
|
|
+ // "Encryption error.".to_string(),
|
|
|
|
|
+ // "Encryptiefout.".to_string(),
|
|
|
|
|
+ // "暗号化エラー。".to_string(),
|
|
|
|
|
+ // ];
|
|
|
|
|
+ // }
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
buf = [
|
|
buf = [
|
|
@@ -172,34 +170,35 @@ impl Labels {
|
|
|
let reason_buf: [String; 3];
|
|
let reason_buf: [String; 3];
|
|
|
|
|
|
|
|
match error {
|
|
match error {
|
|
|
- NetworkError::ReqwestError(_) => {
|
|
|
|
|
|
|
+ ConnectionError::ReqwestError(_) => {
|
|
|
reason_buf = [
|
|
reason_buf = [
|
|
|
"Connection error.".to_string(),
|
|
"Connection error.".to_string(),
|
|
|
"Verbindingsfout.".to_string(),
|
|
"Verbindingsfout.".to_string(),
|
|
|
"接続エラー。".to_string(),
|
|
"接続エラー。".to_string(),
|
|
|
];
|
|
];
|
|
|
}
|
|
}
|
|
|
- NetworkError::StatusCodeError(code) => {
|
|
|
|
|
|
|
+ ConnectionError::StatusCodeError(code) => {
|
|
|
reason_buf = [
|
|
reason_buf = [
|
|
|
format!("Status code: {code}"),
|
|
format!("Status code: {code}"),
|
|
|
format!("Statuscode: {code}"),
|
|
format!("Statuscode: {code}"),
|
|
|
format!("ステータスコード: {code}"),
|
|
format!("ステータスコード: {code}"),
|
|
|
];
|
|
];
|
|
|
}
|
|
}
|
|
|
- NetworkError::InvalidUrl => {
|
|
|
|
|
|
|
+ ConnectionError::UrlError(_) => {
|
|
|
reason_buf = [
|
|
reason_buf = [
|
|
|
"Invalid URL.".to_string(),
|
|
"Invalid URL.".to_string(),
|
|
|
"Ongeldig URL.".to_string(),
|
|
"Ongeldig URL.".to_string(),
|
|
|
"無効なURL。".to_string(),
|
|
"無効なURL。".to_string(),
|
|
|
];
|
|
];
|
|
|
}
|
|
}
|
|
|
- NetworkError::EncryptionError(_) => {
|
|
|
|
|
- reason_buf = [
|
|
|
|
|
- "Decryption error.".to_string(),
|
|
|
|
|
- "Fout bij het ontcijferen.".to_string(),
|
|
|
|
|
- "復号エラー".to_string(),
|
|
|
|
|
- ];
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // TODO: Check if it's safe to remove this.
|
|
|
|
|
+ // ConnectionError::EncryptionError(_) => {
|
|
|
|
|
+ // reason_buf = [
|
|
|
|
|
+ // "Decryption error.".to_string(),
|
|
|
|
|
+ // "Fout bij het ontcijferen.".to_string(),
|
|
|
|
|
+ // "復号エラー".to_string(),
|
|
|
|
|
+ // ];
|
|
|
|
|
+ // }
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
buf = [
|
|
buf = [
|
|
@@ -210,6 +209,7 @@ impl Labels {
|
|
|
|
|
|
|
|
[buf[0].as_str(), buf[1].as_str(), buf[2].as_str()]
|
|
[buf[0].as_str(), buf[1].as_str(), buf[2].as_str()]
|
|
|
}
|
|
}
|
|
|
|
|
+ Labels::QuitButton => ["Quit", "Verlaten", "終了する"],
|
|
|
Labels::RefreshButton => ["Refresh", "Vernieuwen", "更新する"],
|
|
Labels::RefreshButton => ["Refresh", "Vernieuwen", "更新する"],
|
|
|
Labels::InvalidUsernameExplination => {
|
|
Labels::InvalidUsernameExplination => {
|
|
|
buf = [
|
|
buf = [
|
|
@@ -256,11 +256,11 @@ impl Labels {
|
|
|
Labels::NewChannel => ["New Channel", "Nieuw kanaal", "新しいチャンネル"],
|
|
Labels::NewChannel => ["New Channel", "Nieuw kanaal", "新しいチャンネル"],
|
|
|
Labels::InvalidChannelNameExplination => {
|
|
Labels::InvalidChannelNameExplination => {
|
|
|
buf = [
|
|
buf = [
|
|
|
- r"Invalid channel name. Must match ^[a-zA-Z0-9#_\-\.]{2,${MAX_USERNAME_LENGTH}}$"
|
|
|
|
|
|
|
+ r"Invalid channel name. Must match ^[a-z0-9#_\-\.]{2,${MAX_USERNAME_LENGTH}}$"
|
|
|
.replace("${MAX_USERNAME_LENGTH}", &MAX_USERNAME_LENGTH.to_string()),
|
|
.replace("${MAX_USERNAME_LENGTH}", &MAX_USERNAME_LENGTH.to_string()),
|
|
|
- r"Ongeldige kanaalnaam. Moet overeenkomen met ^[a-zA-Z0-9#_\-\.]{2,${MAX_USERNAME_LENGTH}}$"
|
|
|
|
|
|
|
+ r"Ongeldige kanaalnaam. Moet overeenkomen met ^[a-z0-9#_\-\.]{2,${MAX_USERNAME_LENGTH}}$"
|
|
|
.replace("${MAX_USERNAME_LENGTH}", &MAX_USERNAME_LENGTH.to_string()),
|
|
.replace("${MAX_USERNAME_LENGTH}", &MAX_USERNAME_LENGTH.to_string()),
|
|
|
- r"無効なチャンネル名。 ^[a-zA-Z0-9#_\-\.]{2,${MAX_USERNAME_LENGTH}}$ に一致する必要があります"
|
|
|
|
|
|
|
+ r"無効なチャンネル名。 ^[a-z0-9#_\-\.]{2,${MAX_USERNAME_LENGTH}}$ に一致する必要があります"
|
|
|
.replace("${MAX_USERNAME_LENGTH}", &MAX_USERNAME_LENGTH.to_string()),
|
|
.replace("${MAX_USERNAME_LENGTH}", &MAX_USERNAME_LENGTH.to_string()),
|
|
|
];
|
|
];
|
|
|
|
|
|
|
@@ -299,7 +299,7 @@ pub fn alert<S>(siv: &mut Cursive, title: S, text: S)
|
|
|
where
|
|
where
|
|
|
S: Into<String>,
|
|
S: Into<String>,
|
|
|
{
|
|
{
|
|
|
- let language = get_appdata(siv).language;
|
|
|
|
|
|
|
+ let language = get_appdata(siv).persistent_data.language;
|
|
|
|
|
|
|
|
keybind_setup_close_once(siv);
|
|
keybind_setup_close_once(siv);
|
|
|
|
|
|
|
@@ -317,7 +317,7 @@ pub fn copyable<S>(siv: &mut Cursive, title: S, text: S)
|
|
|
where
|
|
where
|
|
|
S: Into<String> + Clone,
|
|
S: Into<String> + Clone,
|
|
|
{
|
|
{
|
|
|
- let language = get_appdata(siv).language;
|
|
|
|
|
|
|
+ let language = get_appdata(siv).persistent_data.language;
|
|
|
|
|
|
|
|
keybind_setup_close_once(siv);
|
|
keybind_setup_close_once(siv);
|
|
|
|
|
|
|
@@ -345,7 +345,7 @@ pub fn error<S>(siv: &mut Cursive, text: S)
|
|
|
where
|
|
where
|
|
|
S: Into<String>,
|
|
S: Into<String>,
|
|
|
{
|
|
{
|
|
|
- let language = get_appdata(siv).language;
|
|
|
|
|
|
|
+ let language = get_appdata(siv).persistent_data.language;
|
|
|
alert(siv, Labels::Error.localize(language), text.into());
|
|
alert(siv, Labels::Error.localize(language), text.into());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -380,23 +380,23 @@ pub fn keybind_close_manual_end(siv: &mut Cursive, close_all: bool) {
|
|
|
|
|
|
|
|
pub fn visual_update(siv: &mut Cursive) {
|
|
pub fn visual_update(siv: &mut Cursive) {
|
|
|
let appdata = get_appdata(siv);
|
|
let appdata = get_appdata(siv);
|
|
|
- let current_channel = appdata.current_channel;
|
|
|
|
|
- let language = get_appdata(siv).language;
|
|
|
|
|
|
|
+ let current_channel = appdata.persistent_data.current_channel;
|
|
|
|
|
+ let language = get_appdata(siv).persistent_data.language;
|
|
|
|
|
|
|
|
// --- Messages ---
|
|
// --- Messages ---
|
|
|
|
|
|
|
|
- let mut messages: Vec<message::MessageSanitized> = appdata
|
|
|
|
|
|
|
+ let mut messages: Vec<MessageSanitized> = appdata
|
|
|
.messages
|
|
.messages
|
|
|
.clone()
|
|
.clone()
|
|
|
.values()
|
|
.values()
|
|
|
.cloned()
|
|
.cloned()
|
|
|
.map(MessageSanitized::from)
|
|
.map(MessageSanitized::from)
|
|
|
.collect::<Vec<_>>();
|
|
.collect::<Vec<_>>();
|
|
|
- messages.sort_by(|a, b| a.time.cmp(&b.time));
|
|
|
|
|
|
|
+ messages.sort_by(|a, b| b.time.cmp(&a.time));
|
|
|
|
|
|
|
|
// Remove blocked phrases
|
|
// Remove blocked phrases
|
|
|
for message in messages.iter_mut() {
|
|
for message in messages.iter_mut() {
|
|
|
- message.remove_blocked_phrases(siv);
|
|
|
|
|
|
|
+ message.remove_blocked_phrases(&appdata.persistent_data.blocked_phrases, appdata.persistent_data.blocked_phrases_censor_char);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
siv.call_on_name(
|
|
siv.call_on_name(
|
|
@@ -496,7 +496,7 @@ pub fn visual_update(siv: &mut Cursive) {
|
|
|
|view: &mut NamedView<Panel<TextView>>| {
|
|
|view: &mut NamedView<Panel<TextView>>| {
|
|
|
view.get_mut()
|
|
view.get_mut()
|
|
|
.get_inner_mut()
|
|
.get_inner_mut()
|
|
|
- .set_content(appdata_c.current_channel);
|
|
|
|
|
|
|
+ .set_content(appdata_c.persistent_data.current_channel);
|
|
|
|
|
|
|
|
view.get_mut().set_title(Labels::Channel.localize(language));
|
|
view.get_mut().set_title(Labels::Channel.localize(language));
|
|
|
},
|
|
},
|
|
@@ -507,7 +507,7 @@ pub fn visual_update(siv: &mut Cursive) {
|
|
|
siv.call_on_name(
|
|
siv.call_on_name(
|
|
|
CURRENT_USERNAME_PANEL_ID,
|
|
CURRENT_USERNAME_PANEL_ID,
|
|
|
|view: &mut NamedView<Panel<TextView>>| {
|
|
|view: &mut NamedView<Panel<TextView>>| {
|
|
|
- view.get_mut().get_inner_mut().set_content(appdata.username);
|
|
|
|
|
|
|
+ view.get_mut().get_inner_mut().set_content(appdata.persistent_data.username);
|
|
|
},
|
|
},
|
|
|
);
|
|
);
|
|
|
|
|
|
|
@@ -550,6 +550,11 @@ pub fn visual_update(siv: &mut Cursive) {
|
|
|
.set_label(Labels::SetUsername.localize(language));
|
|
.set_label(Labels::SetUsername.localize(language));
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+ siv.call_on_name(QUIT_BUTTON_ID, |view: &mut NamedView<Button>| {
|
|
|
|
|
+ view.get_mut()
|
|
|
|
|
+ .set_label(Labels::QuitButton.localize(language));
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
siv.call_on_name(REFRESH_BUTTON_ID, |view: &mut NamedView<Button>| {
|
|
siv.call_on_name(REFRESH_BUTTON_ID, |view: &mut NamedView<Button>| {
|
|
|
view.get_mut()
|
|
view.get_mut()
|
|
|
.set_label(Labels::RefreshButton.localize(language));
|
|
.set_label(Labels::RefreshButton.localize(language));
|
|
@@ -581,7 +586,7 @@ pub fn visual_update(siv: &mut Cursive) {
|
|
|
|
|
|
|
|
pub fn change_language(siv: &mut Cursive, language: Language) {
|
|
pub fn change_language(siv: &mut Cursive, language: Language) {
|
|
|
siv.with_user_data(|appdata: &mut Appdata| {
|
|
siv.with_user_data(|appdata: &mut Appdata| {
|
|
|
- appdata.language = language;
|
|
|
|
|
|
|
+ appdata.persistent_data.language = language;
|
|
|
})
|
|
})
|
|
|
.expect("Failed to set language.");
|
|
.expect("Failed to set language.");
|
|
|
|
|
|
|
@@ -598,7 +603,7 @@ pub fn setup_ui(siv: &mut Cursive) -> LinearLayout {
|
|
|
let mut view: SelectView<String> = SelectView::new();
|
|
let mut view: SelectView<String> = SelectView::new();
|
|
|
view.set_on_submit(move |siv, channel_id: &str| {
|
|
view.set_on_submit(move |siv, channel_id: &str| {
|
|
|
siv.with_user_data(|appdata: &mut Appdata| {
|
|
siv.with_user_data(|appdata: &mut Appdata| {
|
|
|
- appdata.current_channel = channel_id.to_string();
|
|
|
|
|
|
|
+ appdata.persistent_data.current_channel = channel_id.to_string();
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
visual_update(siv);
|
|
visual_update(siv);
|
|
@@ -614,7 +619,7 @@ pub fn setup_ui(siv: &mut Cursive) -> LinearLayout {
|
|
|
let channels_new_button = Button::new("", move |siv| {
|
|
let channels_new_button = Button::new("", move |siv| {
|
|
|
keybind_setup_close_once(siv);
|
|
keybind_setup_close_once(siv);
|
|
|
|
|
|
|
|
- let language = get_appdata(siv).language;
|
|
|
|
|
|
|
+ let language = get_appdata(siv).persistent_data.language;
|
|
|
|
|
|
|
|
siv.add_layer(
|
|
siv.add_layer(
|
|
|
cursive::views::Dialog::new()
|
|
cursive::views::Dialog::new()
|
|
@@ -633,14 +638,14 @@ pub fn setup_ui(siv: &mut Cursive) -> LinearLayout {
|
|
|
})
|
|
})
|
|
|
.expect("Failed to retrieve channel creation input.");
|
|
.expect("Failed to retrieve channel creation input.");
|
|
|
|
|
|
|
|
- if message::is_valid_username(&input) {
|
|
|
|
|
|
|
+ if message::is_valid_channel_name(&input) {
|
|
|
// Valid
|
|
// Valid
|
|
|
siv.with_user_data(|appdata: &mut Appdata| {
|
|
siv.with_user_data(|appdata: &mut Appdata| {
|
|
|
appdata.local_channels.push(input.to_string());
|
|
appdata.local_channels.push(input.to_string());
|
|
|
- appdata.current_channel = input.to_string();
|
|
|
|
|
|
|
+ appdata.persistent_data.current_channel = input.to_string();
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
- save_appdata(siv);
|
|
|
|
|
|
|
+ save_appdata(get_appdata(siv));
|
|
|
visual_update(siv);
|
|
visual_update(siv);
|
|
|
keybind_close_manual_end(siv, false);
|
|
keybind_close_manual_end(siv, false);
|
|
|
} else {
|
|
} else {
|
|
@@ -700,13 +705,13 @@ pub fn setup_ui(siv: &mut Cursive) -> LinearLayout {
|
|
|
// Language selector
|
|
// Language selector
|
|
|
let language_button = Button::new("", move |siv| {
|
|
let language_button = Button::new("", move |siv| {
|
|
|
// NOTE: This must match the order in the SelectView
|
|
// NOTE: This must match the order in the SelectView
|
|
|
- let current_language_index = match get_appdata(siv).language {
|
|
|
|
|
|
|
+ let current_language_index = match get_appdata(siv).persistent_data.language {
|
|
|
Language::English => 0,
|
|
Language::English => 0,
|
|
|
Language::Dutch => 1,
|
|
Language::Dutch => 1,
|
|
|
Language::Japanese => 2,
|
|
Language::Japanese => 2,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- let language = get_appdata(siv).language;
|
|
|
|
|
|
|
+ let language = get_appdata(siv).persistent_data.language;
|
|
|
|
|
|
|
|
keybind_setup_close_once(siv);
|
|
keybind_setup_close_once(siv);
|
|
|
|
|
|
|
@@ -736,15 +741,15 @@ pub fn setup_ui(siv: &mut Cursive) -> LinearLayout {
|
|
|
|
|
|
|
|
// Current username panel
|
|
// Current username panel
|
|
|
let current_username_panel = {
|
|
let current_username_panel = {
|
|
|
- let current_username = get_appdata(siv).username.clone();
|
|
|
|
|
|
|
+ let current_username = get_appdata(siv).persistent_data.username.clone();
|
|
|
let view = TextView::new(current_username);
|
|
let view = TextView::new(current_username);
|
|
|
Panel::new(view).with_name(CURRENT_USERNAME_PANEL_ID)
|
|
Panel::new(view).with_name(CURRENT_USERNAME_PANEL_ID)
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
// Set username
|
|
// Set username
|
|
|
let username_button = Button::new("", move |siv| {
|
|
let username_button = Button::new("", move |siv| {
|
|
|
- let current_name = get_appdata(siv).username.clone();
|
|
|
|
|
- let language = get_appdata(siv).language;
|
|
|
|
|
|
|
+ let current_name = get_appdata(siv).persistent_data.username.clone();
|
|
|
|
|
+ let language = get_appdata(siv).persistent_data.language;
|
|
|
|
|
|
|
|
keybind_setup_close_once(siv);
|
|
keybind_setup_close_once(siv);
|
|
|
|
|
|
|
@@ -767,15 +772,15 @@ pub fn setup_ui(siv: &mut Cursive) -> LinearLayout {
|
|
|
if message::is_valid_username(&input) {
|
|
if message::is_valid_username(&input) {
|
|
|
// Valid
|
|
// Valid
|
|
|
siv.with_user_data(|appdata: &mut Appdata| {
|
|
siv.with_user_data(|appdata: &mut Appdata| {
|
|
|
- appdata.username = input.to_string();
|
|
|
|
|
|
|
+ appdata.persistent_data.username = input.to_string();
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
- save_appdata(siv);
|
|
|
|
|
|
|
+ save_appdata(get_appdata(siv));
|
|
|
visual_update(siv);
|
|
visual_update(siv);
|
|
|
keybind_close_manual_end(siv, false);
|
|
keybind_close_manual_end(siv, false);
|
|
|
} else {
|
|
} else {
|
|
|
// Invalid
|
|
// Invalid
|
|
|
- let language = get_appdata(siv).language;
|
|
|
|
|
|
|
+ let language = get_appdata(siv).persistent_data.language;
|
|
|
keybind_close_manual_end(siv, false); // NOTE: Error dialogue overwrites this one, so end it here beforehand.
|
|
keybind_close_manual_end(siv, false); // NOTE: Error dialogue overwrites this one, so end it here beforehand.
|
|
|
error(siv, Labels::InvalidUsernameExplination.localize(language));
|
|
error(siv, Labels::InvalidUsernameExplination.localize(language));
|
|
|
}
|
|
}
|
|
@@ -788,10 +793,16 @@ pub fn setup_ui(siv: &mut Cursive) -> LinearLayout {
|
|
|
})
|
|
})
|
|
|
.with_name(USERNAME_BUTTON_ID);
|
|
.with_name(USERNAME_BUTTON_ID);
|
|
|
|
|
|
|
|
|
|
+ // Quit button
|
|
|
|
|
+ let quit_button = Button::new("", move |siv| {
|
|
|
|
|
+ siv.quit();
|
|
|
|
|
+ })
|
|
|
|
|
+ .with_name(QUIT_BUTTON_ID);
|
|
|
|
|
+
|
|
|
// Refresh button
|
|
// Refresh button
|
|
|
let refresh_button = Button::new("", move |siv| {
|
|
let refresh_button = Button::new("", move |siv| {
|
|
|
if let Err(e) = actions::load_messages(siv) {
|
|
if let Err(e) = actions::load_messages(siv) {
|
|
|
- let language = get_appdata(siv).language;
|
|
|
|
|
|
|
+ let language = get_appdata(siv).persistent_data.language;
|
|
|
error(siv, Labels::FailedToLoadMessages(e).localize(language));
|
|
error(siv, Labels::FailedToLoadMessages(e).localize(language));
|
|
|
}
|
|
}
|
|
|
visual_update(siv);
|
|
visual_update(siv);
|
|
@@ -802,7 +813,7 @@ pub fn setup_ui(siv: &mut Cursive) -> LinearLayout {
|
|
|
let blocked_words_list_button = {
|
|
let blocked_words_list_button = {
|
|
|
Button::new("", move |siv| {
|
|
Button::new("", move |siv| {
|
|
|
let appdata = get_appdata(siv);
|
|
let appdata = get_appdata(siv);
|
|
|
- let language = appdata.language;
|
|
|
|
|
|
|
+ let language = appdata.persistent_data.language;
|
|
|
|
|
|
|
|
let wordslist_id = utils::new_id();
|
|
let wordslist_id = utils::new_id();
|
|
|
let wordslist_id_clone = wordslist_id.clone();
|
|
let wordslist_id_clone = wordslist_id.clone();
|
|
@@ -810,7 +821,7 @@ pub fn setup_ui(siv: &mut Cursive) -> LinearLayout {
|
|
|
let mut wordslist_view =
|
|
let mut wordslist_view =
|
|
|
SelectView::<String>::new().on_submit(move |siv, word: &str| {
|
|
SelectView::<String>::new().on_submit(move |siv, word: &str| {
|
|
|
siv.with_user_data(|appdata: &mut Appdata| {
|
|
siv.with_user_data(|appdata: &mut Appdata| {
|
|
|
- appdata.blocked_phrases.retain(|x| x != word);
|
|
|
|
|
|
|
+ appdata.persistent_data.blocked_phrases.retain(|x| x != word);
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
siv.call_on_name(&wordslist_id_clone, |view: &mut NamedView<SelectView>| {
|
|
siv.call_on_name(&wordslist_id_clone, |view: &mut NamedView<SelectView>| {
|
|
@@ -821,10 +832,10 @@ pub fn setup_ui(siv: &mut Cursive) -> LinearLayout {
|
|
|
view.get_mut().remove_item(idx);
|
|
view.get_mut().remove_item(idx);
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
- save_appdata(siv);
|
|
|
|
|
|
|
+ save_appdata(get_appdata(siv));
|
|
|
visual_update(siv);
|
|
visual_update(siv);
|
|
|
});
|
|
});
|
|
|
- wordslist_view.add_all_str(&appdata.blocked_phrases);
|
|
|
|
|
|
|
+ wordslist_view.add_all_str(&appdata.persistent_data.blocked_phrases);
|
|
|
|
|
|
|
|
let typingarea_id = utils::new_id();
|
|
let typingarea_id = utils::new_id();
|
|
|
let typing_area = EditView::new().with_name(&typingarea_id);
|
|
let typing_area = EditView::new().with_name(&typingarea_id);
|
|
@@ -838,12 +849,12 @@ pub fn setup_ui(siv: &mut Cursive) -> LinearLayout {
|
|
|
.map(|x| x.to_string())
|
|
.map(|x| x.to_string())
|
|
|
.unwrap_or("".to_string());
|
|
.unwrap_or("".to_string());
|
|
|
|
|
|
|
|
- if get_appdata(siv).blocked_phrases.contains(&text) || text.is_empty() {
|
|
|
|
|
|
|
+ if get_appdata(siv).persistent_data.blocked_phrases.contains(&text) || text.is_empty() {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
siv.with_user_data(|appdata: &mut Appdata| {
|
|
siv.with_user_data(|appdata: &mut Appdata| {
|
|
|
- appdata.blocked_phrases.push(text.clone());
|
|
|
|
|
|
|
+ appdata.persistent_data.blocked_phrases.push(text.clone());
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
siv.call_on_name(
|
|
siv.call_on_name(
|
|
@@ -853,7 +864,7 @@ pub fn setup_ui(siv: &mut Cursive) -> LinearLayout {
|
|
|
},
|
|
},
|
|
|
);
|
|
);
|
|
|
|
|
|
|
|
- save_appdata(siv);
|
|
|
|
|
|
|
+ save_appdata(get_appdata(siv));
|
|
|
visual_update(siv);
|
|
visual_update(siv);
|
|
|
});
|
|
});
|
|
|
|
|
|
|
@@ -882,7 +893,7 @@ pub fn setup_ui(siv: &mut Cursive) -> LinearLayout {
|
|
|
// Server settings
|
|
// Server settings
|
|
|
let server_settings_button = Button::new("", |siv| {
|
|
let server_settings_button = Button::new("", |siv| {
|
|
|
let appdata = get_appdata(siv);
|
|
let appdata = get_appdata(siv);
|
|
|
- let language = appdata.language;
|
|
|
|
|
|
|
+ let language = appdata.persistent_data.language;
|
|
|
|
|
|
|
|
keybind_setup_close_once(siv);
|
|
keybind_setup_close_once(siv);
|
|
|
|
|
|
|
@@ -900,7 +911,7 @@ pub fn setup_ui(siv: &mut Cursive) -> LinearLayout {
|
|
|
.child(DummyView.fixed_width(1))
|
|
.child(DummyView.fixed_width(1))
|
|
|
.child(
|
|
.child(
|
|
|
EditView::new()
|
|
EditView::new()
|
|
|
- .content(appdata.api_endpoint)
|
|
|
|
|
|
|
+ .content(appdata.persistent_data.api_endpoint)
|
|
|
.with_name(SERVER_SETTINGS_ADDRESS_FIELD_ID)
|
|
.with_name(SERVER_SETTINGS_ADDRESS_FIELD_ID)
|
|
|
.min_width(SERVER_SETTINGS_FIELD_SIZE.0)
|
|
.min_width(SERVER_SETTINGS_FIELD_SIZE.0)
|
|
|
.max_height(SERVER_SETTINGS_FIELD_SIZE.1),
|
|
.max_height(SERVER_SETTINGS_FIELD_SIZE.1),
|
|
@@ -915,7 +926,7 @@ pub fn setup_ui(siv: &mut Cursive) -> LinearLayout {
|
|
|
.child(DummyView.fixed_width(1))
|
|
.child(DummyView.fixed_width(1))
|
|
|
.child(
|
|
.child(
|
|
|
EditView::new()
|
|
EditView::new()
|
|
|
- .content(appdata.api_refresh_rate.to_string())
|
|
|
|
|
|
|
+ .content(appdata.persistent_data.api_refresh_rate.to_string())
|
|
|
.with_name(SERVER_SETTINGS_REFRESH_FIELD_ID)
|
|
.with_name(SERVER_SETTINGS_REFRESH_FIELD_ID)
|
|
|
.min_width(SERVER_SETTINGS_FIELD_SIZE.0)
|
|
.min_width(SERVER_SETTINGS_FIELD_SIZE.0)
|
|
|
.max_height(SERVER_SETTINGS_FIELD_SIZE.1),
|
|
.max_height(SERVER_SETTINGS_FIELD_SIZE.1),
|
|
@@ -930,7 +941,7 @@ pub fn setup_ui(siv: &mut Cursive) -> LinearLayout {
|
|
|
.child(DummyView.fixed_width(1))
|
|
.child(DummyView.fixed_width(1))
|
|
|
.child(
|
|
.child(
|
|
|
EditView::new()
|
|
EditView::new()
|
|
|
- .content(appdata.api_password.to_string())
|
|
|
|
|
|
|
+ .content(appdata.persistent_data.api_password.to_string())
|
|
|
.with_name(SERVER_SETTINGS_PASSWORD_FIELD_ID)
|
|
.with_name(SERVER_SETTINGS_PASSWORD_FIELD_ID)
|
|
|
.min_width(SERVER_SETTINGS_FIELD_SIZE.0)
|
|
.min_width(SERVER_SETTINGS_FIELD_SIZE.0)
|
|
|
.max_height(SERVER_SETTINGS_FIELD_SIZE.1),
|
|
.max_height(SERVER_SETTINGS_FIELD_SIZE.1),
|
|
@@ -957,20 +968,20 @@ pub fn setup_ui(siv: &mut Cursive) -> LinearLayout {
|
|
|
.expect("Failed to retrieve server settings password input.");
|
|
.expect("Failed to retrieve server settings password input.");
|
|
|
|
|
|
|
|
siv.with_user_data(|appdata: &mut Appdata| {
|
|
siv.with_user_data(|appdata: &mut Appdata| {
|
|
|
- appdata.api_endpoint = input_addr.to_string();
|
|
|
|
|
|
|
+ appdata.persistent_data.api_endpoint = input_addr.to_string();
|
|
|
|
|
|
|
|
let mut password = input_password.to_string();
|
|
let mut password = input_password.to_string();
|
|
|
if password.is_empty() {
|
|
if password.is_empty() {
|
|
|
password = DEFAULT_PASSWORD.to_string();
|
|
password = DEFAULT_PASSWORD.to_string();
|
|
|
}
|
|
}
|
|
|
- appdata.api_password = password;
|
|
|
|
|
|
|
+ appdata.persistent_data.api_password = password;
|
|
|
|
|
|
|
|
if let Ok(rate) = input_refresh.parse() {
|
|
if let Ok(rate) = input_refresh.parse() {
|
|
|
- appdata.api_refresh_rate = rate;
|
|
|
|
|
|
|
+ appdata.persistent_data.api_refresh_rate = rate;
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
- save_appdata(siv);
|
|
|
|
|
|
|
+ save_appdata(get_appdata(siv));
|
|
|
visual_update(siv);
|
|
visual_update(siv);
|
|
|
keybind_close_manual_end(siv, false);
|
|
keybind_close_manual_end(siv, false);
|
|
|
})
|
|
})
|
|
@@ -984,7 +995,7 @@ pub fn setup_ui(siv: &mut Cursive) -> LinearLayout {
|
|
|
|
|
|
|
|
let info_button = Button::new("", move |siv| {
|
|
let info_button = Button::new("", move |siv| {
|
|
|
let appdata = get_appdata(siv);
|
|
let appdata = get_appdata(siv);
|
|
|
- let language = appdata.language;
|
|
|
|
|
|
|
+ let language = appdata.persistent_data.language;
|
|
|
|
|
|
|
|
alert(siv, Labels::Information.localize(language), "Rei <rain@skuld.network>".to_string());
|
|
alert(siv, Labels::Information.localize(language), "Rei <rain@skuld.network>".to_string());
|
|
|
})
|
|
})
|
|
@@ -1025,6 +1036,8 @@ pub fn setup_ui(siv: &mut Cursive) -> LinearLayout {
|
|
|
.child(server_settings_button)
|
|
.child(server_settings_button)
|
|
|
.child(DummyView.full_width())
|
|
.child(DummyView.full_width())
|
|
|
.child(refresh_button)
|
|
.child(refresh_button)
|
|
|
|
|
+ .child(DummyView.full_width())
|
|
|
|
|
+ .child(quit_button)
|
|
|
.full_width(),
|
|
.full_width(),
|
|
|
);
|
|
);
|
|
|
|
|
|