|
@@ -3,24 +3,19 @@ mod message;
|
|
|
mod persistence;
|
|
mod persistence;
|
|
|
mod ui;
|
|
mod ui;
|
|
|
|
|
|
|
|
|
|
+use cursive::align::Align;
|
|
|
use cursive::reexports::log;
|
|
use cursive::reexports::log;
|
|
|
-use cursive::views::{
|
|
|
|
|
- Button, Dialog, DummyView, EditView, LinearLayout, NamedView, Panel, ScrollView, SelectView,
|
|
|
|
|
- TextArea, TextView,
|
|
|
|
|
-};
|
|
|
|
|
|
|
+use cursive::views::TextView;
|
|
|
use cursive::{event, Cursive};
|
|
use cursive::{event, Cursive};
|
|
|
use cursive::{traits::*, CursiveExt as _};
|
|
use cursive::{traits::*, CursiveExt as _};
|
|
|
use message::Message;
|
|
use message::Message;
|
|
|
use std::collections::HashMap;
|
|
use std::collections::HashMap;
|
|
|
use std::io::{Read as _, Write as _};
|
|
use std::io::{Read as _, Write as _};
|
|
|
use std::thread;
|
|
use std::thread;
|
|
|
|
|
+use std::time::Duration;
|
|
|
use utils::serialize::Serialize;
|
|
use utils::serialize::Serialize;
|
|
|
|
|
|
|
|
-use ui::{
|
|
|
|
|
- DIALOGUE_MIN_SIZE, INPUT_BUTTON_ID, INPUT_CLEAR_BUTTON_ID, INPUT_FIELD_ID, INPUT_PANEL_ID,
|
|
|
|
|
- LANGUAGE_BUTTON_ID, MESSAGE_PANEL_ID, REFRESH_BUTTON_ID, USERNAME_BUTTON_ID, USERNAME_FIELD_ID,
|
|
|
|
|
- USERS_PANEL_ID, USER_PANEL_SIZE,
|
|
|
|
|
-};
|
|
|
|
|
|
|
+use ui::INPUT_FIELD_ID;
|
|
|
|
|
|
|
|
const MAX_MESSAGE_LENGTH: usize = 512;
|
|
const MAX_MESSAGE_LENGTH: usize = 512;
|
|
|
const MAX_USERNAME_LENGTH: usize = 16;
|
|
const MAX_USERNAME_LENGTH: usize = 16;
|
|
@@ -28,6 +23,8 @@ const DEFAULT_USERNAME_PREFIX: &str = "Myst";
|
|
|
const DEFAULT_CHANNEL: &str = "Root";
|
|
const DEFAULT_CHANNEL: &str = "Root";
|
|
|
const DEFAULT_PASSWORD: &str = "null";
|
|
const DEFAULT_PASSWORD: &str = "null";
|
|
|
|
|
|
|
|
|
|
+const LOGO: &str = include_str!("../assets/logo.txt");
|
|
|
|
|
+
|
|
|
const SAVE_FILE: &str = "savedata.bin";
|
|
const SAVE_FILE: &str = "savedata.bin";
|
|
|
const SAVE_FILE_FUZZY: u64 = 0b0110110001101001011001110110110101100001001000000101100001000100;
|
|
const SAVE_FILE_FUZZY: u64 = 0b0110110001101001011001110110110101100001001000000101100001000100;
|
|
|
|
|
|
|
@@ -45,6 +42,7 @@ pub struct Appdata {
|
|
|
pub messages: HashMap<String, Message>,
|
|
pub messages: HashMap<String, Message>,
|
|
|
pub quick_close_window_count: usize,
|
|
pub quick_close_window_count: usize,
|
|
|
pub local_channels: Vec<String>,
|
|
pub local_channels: Vec<String>,
|
|
|
|
|
+ pub intro_screen_shown_until: u128,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
impl Default for Appdata {
|
|
impl Default for Appdata {
|
|
@@ -71,6 +69,7 @@ impl Appdata {
|
|
|
current_channel: DEFAULT_CHANNEL.to_string(),
|
|
current_channel: DEFAULT_CHANNEL.to_string(),
|
|
|
local_channels: vec![DEFAULT_CHANNEL.to_string()],
|
|
local_channels: vec![DEFAULT_CHANNEL.to_string()],
|
|
|
api_password: DEFAULT_PASSWORD.to_string(),
|
|
api_password: DEFAULT_PASSWORD.to_string(),
|
|
|
|
|
+ intro_screen_shown_until: 0,
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -138,460 +137,53 @@ fn main() {
|
|
|
let _ = siv.focus_name(INPUT_FIELD_ID);
|
|
let _ = siv.focus_name(INPUT_FIELD_ID);
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+ // Logo intro screen
|
|
|
|
|
+ siv.add_fullscreen_layer(TextView::new(LOGO).align(Align::center()).full_screen());
|
|
|
|
|
+
|
|
|
// Background thread
|
|
// Background thread
|
|
|
{
|
|
{
|
|
|
let cb_sink = siv.cb_sink().clone();
|
|
let cb_sink = siv.cb_sink().clone();
|
|
|
- let mut timer = 0;
|
|
|
|
|
- thread::spawn(move || loop {
|
|
|
|
|
- cb_sink
|
|
|
|
|
- .send(Box::new(move |siv| {
|
|
|
|
|
- let appdata = get_appdata(siv);
|
|
|
|
|
- ui::visual_update(siv);
|
|
|
|
|
-
|
|
|
|
|
- if timer % appdata.api_refresh_rate == 0 {
|
|
|
|
|
- // TODO (low): Add a notice when automatic refresh fails.
|
|
|
|
|
- let _ = actions::load_messages(siv);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- save_appdata(siv);
|
|
|
|
|
- }))
|
|
|
|
|
- .expect("Failed to send callback from background thread.");
|
|
|
|
|
-
|
|
|
|
|
- timer += 1;
|
|
|
|
|
- thread::sleep(std::time::Duration::from_secs(1));
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Channels
|
|
|
|
|
- let channels_panel = {
|
|
|
|
|
- let mut view: SelectView<String> = SelectView::new();
|
|
|
|
|
- view.set_on_submit(move |siv, channel_id: &str| {
|
|
|
|
|
- siv.with_user_data(|appdata: &mut Appdata| {
|
|
|
|
|
- appdata.current_channel = channel_id.to_string();
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- ui::visual_update(siv);
|
|
|
|
|
- });
|
|
|
|
|
- Panel::new(ScrollView::new(view)).with_name(ui::CHANNEL_VIEW_ID)
|
|
|
|
|
- };
|
|
|
|
|
|
|
|
|
|
- let channel_current_panel = {
|
|
|
|
|
- let view = TextView::new("");
|
|
|
|
|
- Panel::new(view).with_name(ui::CHANNEL_CURRENT_PANEL_ID)
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- let channels_new_button = Button::new("", move |siv| {
|
|
|
|
|
- ui::keybind_setup_close_once(siv);
|
|
|
|
|
-
|
|
|
|
|
- let language = get_appdata(siv).language;
|
|
|
|
|
-
|
|
|
|
|
- siv.add_layer(
|
|
|
|
|
- cursive::views::Dialog::new()
|
|
|
|
|
- .title(ui::Labels::NewChannel.localize(language))
|
|
|
|
|
- .content(
|
|
|
|
|
- LinearLayout::vertical().child(
|
|
|
|
|
- EditView::new()
|
|
|
|
|
- .with_name(ui::CHANNEL_NEW_FIELD_ID)
|
|
|
|
|
- .fixed_width(DIALOGUE_MIN_SIZE.0.into()),
|
|
|
|
|
- ),
|
|
|
|
|
- )
|
|
|
|
|
- .button(ui::Labels::Ok.localize(language), move |siv| {
|
|
|
|
|
- let input = siv
|
|
|
|
|
- .call_on_name(ui::CHANNEL_NEW_FIELD_ID, |view: &mut EditView| {
|
|
|
|
|
- view.get_content()
|
|
|
|
|
- })
|
|
|
|
|
- .expect("Failed to retrieve channel creation input.");
|
|
|
|
|
-
|
|
|
|
|
- if message::is_valid_username(&input) {
|
|
|
|
|
- // Valid
|
|
|
|
|
- siv.with_user_data(|appdata: &mut Appdata| {
|
|
|
|
|
- appdata.local_channels.push(input.to_string());
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ thread::spawn(move || {
|
|
|
|
|
+ let mut timer = 0;
|
|
|
|
|
+
|
|
|
|
|
+ loop {
|
|
|
|
|
+ cb_sink
|
|
|
|
|
+ .send(Box::new(move |siv| {
|
|
|
|
|
+ let appdata = get_appdata(siv);
|
|
|
|
|
+
|
|
|
|
|
+ if appdata.intro_screen_shown_until > utils::time::time_millis() {
|
|
|
|
|
+ thread::sleep(Duration::from_millis(
|
|
|
|
|
+ appdata
|
|
|
|
|
+ .intro_screen_shown_until
|
|
|
|
|
+ .saturating_sub(utils::time::time_millis())
|
|
|
|
|
+ as u64,
|
|
|
|
|
+ ));
|
|
|
|
|
+ // Main layout
|
|
|
|
|
+ let main_layout = ui::setup_ui(siv);
|
|
|
|
|
+ siv.pop_layer();
|
|
|
|
|
+ siv.add_fullscreen_layer(main_layout);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- save_appdata(siv);
|
|
|
|
|
ui::visual_update(siv);
|
|
ui::visual_update(siv);
|
|
|
- ui::keybind_close_manual_end(siv, false);
|
|
|
|
|
- } else {
|
|
|
|
|
- // Invalid
|
|
|
|
|
- ui::keybind_close_manual_end(siv, false); // NOTE: Error dialogue overwrites this one, so end it here beforehand.
|
|
|
|
|
- ui::error(
|
|
|
|
|
- siv,
|
|
|
|
|
- ui::Labels::InvalidChannelNameExplination.localize(language),
|
|
|
|
|
- );
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- .button(ui::Labels::Cancel.localize(language), |siv| {
|
|
|
|
|
- ui::keybind_close_manual_end(siv, false);
|
|
|
|
|
- })
|
|
|
|
|
- .min_size(DIALOGUE_MIN_SIZE),
|
|
|
|
|
- );
|
|
|
|
|
- })
|
|
|
|
|
- .with_name(ui::CHANNEL_NEW_BUTTON_ID);
|
|
|
|
|
-
|
|
|
|
|
- // Users
|
|
|
|
|
- let users_panel = {
|
|
|
|
|
- let mut users_view: SelectView<String> = SelectView::new();
|
|
|
|
|
- users_view.set_on_submit(move |siv, user: &String| actions::on_user_click(siv, user));
|
|
|
|
|
- Panel::new(ScrollView::new(users_view)).with_name(USERS_PANEL_ID)
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- // Messages
|
|
|
|
|
- let messages_panel = {
|
|
|
|
|
- let mut view: SelectView<String> = SelectView::new();
|
|
|
|
|
- view.set_on_submit(move |siv, message_id: &str| actions::on_message_click(siv, message_id));
|
|
|
|
|
- Panel::new(ScrollView::new(view)).with_name(MESSAGE_PANEL_ID)
|
|
|
|
|
- };
|
|
|
|
|
|
|
|
|
|
- // Input
|
|
|
|
|
- let input_panel = {
|
|
|
|
|
- let input_field = TextArea::new()
|
|
|
|
|
- .with_name(INPUT_FIELD_ID)
|
|
|
|
|
- .full_width()
|
|
|
|
|
- .max_height(10); // NOTE: 10 seems to be the size of 2 vertical buttons
|
|
|
|
|
- let input_button =
|
|
|
|
|
- Button::new("", move |siv| actions::on_input_submit(siv, INPUT_FIELD_ID))
|
|
|
|
|
- .with_name(INPUT_BUTTON_ID);
|
|
|
|
|
-
|
|
|
|
|
- let input_clear_button =
|
|
|
|
|
- Button::new("", actions::clear_input_field).with_name(INPUT_CLEAR_BUTTON_ID);
|
|
|
|
|
-
|
|
|
|
|
- Panel::new(
|
|
|
|
|
- LinearLayout::horizontal().child(input_field).child(
|
|
|
|
|
- LinearLayout::vertical()
|
|
|
|
|
- .child(input_button)
|
|
|
|
|
- .child(input_clear_button),
|
|
|
|
|
- ),
|
|
|
|
|
- )
|
|
|
|
|
- .with_name(INPUT_PANEL_ID)
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- // Language selector
|
|
|
|
|
- let language_button = Button::new("", move |siv| {
|
|
|
|
|
- // NOTE: This must match the order in the SelectView
|
|
|
|
|
- let current_language_index = match get_appdata(siv).language {
|
|
|
|
|
- ui::Language::English => 0,
|
|
|
|
|
- ui::Language::Dutch => 1,
|
|
|
|
|
- ui::Language::Japanese => 2,
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- let language = get_appdata(siv).language;
|
|
|
|
|
-
|
|
|
|
|
- ui::keybind_setup_close_once(siv);
|
|
|
|
|
-
|
|
|
|
|
- siv.add_layer(
|
|
|
|
|
- cursive::views::Dialog::new()
|
|
|
|
|
- .content(
|
|
|
|
|
- LinearLayout::vertical().child(
|
|
|
|
|
- SelectView::<ui::Language>::new()
|
|
|
|
|
- .item("English", ui::Language::English)
|
|
|
|
|
- .item("Nederlands", ui::Language::Dutch)
|
|
|
|
|
- .item("日本語", ui::Language::Japanese)
|
|
|
|
|
- .selected(current_language_index)
|
|
|
|
|
- .on_submit(move |siv, language| {
|
|
|
|
|
- ui::change_language(siv, *language);
|
|
|
|
|
- ui::keybind_close_manual_end(siv, false);
|
|
|
|
|
- }),
|
|
|
|
|
- ),
|
|
|
|
|
- )
|
|
|
|
|
- .title(ui::Labels::SetLanguage.localize(language))
|
|
|
|
|
- .button(ui::Labels::Cancel.localize(language), |siv| {
|
|
|
|
|
- ui::keybind_close_manual_end(siv, false);
|
|
|
|
|
- })
|
|
|
|
|
- .min_size(DIALOGUE_MIN_SIZE),
|
|
|
|
|
- );
|
|
|
|
|
- })
|
|
|
|
|
- .with_name(LANGUAGE_BUTTON_ID);
|
|
|
|
|
-
|
|
|
|
|
- // Current username panel
|
|
|
|
|
- let current_username_panel = {
|
|
|
|
|
- let current_username = get_appdata(&mut siv).username.clone();
|
|
|
|
|
- let view = TextView::new(current_username);
|
|
|
|
|
- Panel::new(view).with_name(ui::CURRENT_USERNAME_PANEL_ID)
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- // Set username
|
|
|
|
|
- let username_button = Button::new("", move |siv| {
|
|
|
|
|
- let current_name = get_appdata(siv).username.clone();
|
|
|
|
|
- let language = get_appdata(siv).language;
|
|
|
|
|
-
|
|
|
|
|
- ui::keybind_setup_close_once(siv);
|
|
|
|
|
-
|
|
|
|
|
- siv.add_layer(
|
|
|
|
|
- cursive::views::Dialog::new()
|
|
|
|
|
- .title(ui::Labels::Username.localize(language))
|
|
|
|
|
- .content(
|
|
|
|
|
- LinearLayout::vertical().child(
|
|
|
|
|
- EditView::new()
|
|
|
|
|
- .content(current_name)
|
|
|
|
|
- .with_name(USERNAME_FIELD_ID)
|
|
|
|
|
- .fixed_width(DIALOGUE_MIN_SIZE.0.into()),
|
|
|
|
|
- ),
|
|
|
|
|
- )
|
|
|
|
|
- .button(ui::Labels::Ok.localize(language), |siv| {
|
|
|
|
|
- let input = siv
|
|
|
|
|
- .call_on_name(USERNAME_FIELD_ID, |view: &mut EditView| view.get_content())
|
|
|
|
|
- .expect("Failed to retrieve username input.");
|
|
|
|
|
-
|
|
|
|
|
- if message::is_valid_username(&input) {
|
|
|
|
|
- // Valid
|
|
|
|
|
- siv.with_user_data(|appdata: &mut Appdata| {
|
|
|
|
|
- appdata.username = input.to_string();
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ if timer % appdata.api_refresh_rate == 0 {
|
|
|
|
|
+ // TODO (low): Add a notice when automatic refresh fails.
|
|
|
|
|
+ let _ = actions::load_messages(siv);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
save_appdata(siv);
|
|
save_appdata(siv);
|
|
|
- ui::visual_update(siv);
|
|
|
|
|
- ui::keybind_close_manual_end(siv, false);
|
|
|
|
|
- } else {
|
|
|
|
|
- // Invalid
|
|
|
|
|
- let language = get_appdata(siv).language;
|
|
|
|
|
- ui::keybind_close_manual_end(siv, false); // NOTE: Error dialogue overwrites this one, so end it here beforehand.
|
|
|
|
|
- ui::error(
|
|
|
|
|
- siv,
|
|
|
|
|
- ui::Labels::InvalidUsernameExplination.localize(language),
|
|
|
|
|
- );
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- .button(ui::Labels::Cancel.localize(language), |siv| {
|
|
|
|
|
- ui::keybind_close_manual_end(siv, false);
|
|
|
|
|
- })
|
|
|
|
|
- .min_size(DIALOGUE_MIN_SIZE),
|
|
|
|
|
- );
|
|
|
|
|
- })
|
|
|
|
|
- .with_name(USERNAME_BUTTON_ID);
|
|
|
|
|
-
|
|
|
|
|
- // Refresh button
|
|
|
|
|
- let refresh_button = Button::new("", move |siv| {
|
|
|
|
|
- if let Err(e) = actions::load_messages(siv) {
|
|
|
|
|
- let language = get_appdata(siv).language;
|
|
|
|
|
- ui::error(siv, ui::Labels::FailedToLoadMessages(e).localize(language));
|
|
|
|
|
- }
|
|
|
|
|
- ui::visual_update(siv);
|
|
|
|
|
- })
|
|
|
|
|
- .with_name(REFRESH_BUTTON_ID);
|
|
|
|
|
-
|
|
|
|
|
- // Blocked words list
|
|
|
|
|
- let blocked_words_list_button = {
|
|
|
|
|
- Button::new("", move |siv| {
|
|
|
|
|
- let appdata = get_appdata(siv);
|
|
|
|
|
- let language = appdata.language;
|
|
|
|
|
-
|
|
|
|
|
- let wordslist_id = utils::new_id();
|
|
|
|
|
- let wordslist_id_clone = wordslist_id.clone();
|
|
|
|
|
- let wordslist_id_typingarea_clone = wordslist_id.clone();
|
|
|
|
|
- let mut wordslist_view =
|
|
|
|
|
- SelectView::<String>::new().on_submit(move |siv, word: &str| {
|
|
|
|
|
- siv.with_user_data(|appdata: &mut Appdata| {
|
|
|
|
|
- appdata.blocked_phrases.retain(|x| x != word);
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- siv.call_on_name(&wordslist_id_clone, |view: &mut NamedView<SelectView>| {
|
|
|
|
|
- let idx = view
|
|
|
|
|
- .get_mut()
|
|
|
|
|
- .selected_id()
|
|
|
|
|
- .expect("Selection should exist when fired from submit.");
|
|
|
|
|
- view.get_mut().remove_item(idx);
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- save_appdata(siv);
|
|
|
|
|
- ui::visual_update(siv);
|
|
|
|
|
- });
|
|
|
|
|
- wordslist_view.add_all_str(&appdata.blocked_phrases);
|
|
|
|
|
-
|
|
|
|
|
- let typingarea_id = utils::new_id();
|
|
|
|
|
- let typing_area = EditView::new().with_name(&typingarea_id);
|
|
|
|
|
- let typing_button = Button::new(ui::Labels::Submit.localize(language), move |siv| {
|
|
|
|
|
- let text = siv
|
|
|
|
|
- .call_on_name(&typingarea_id, |view: &mut EditView| {
|
|
|
|
|
- let s = utils::strings::insensitive_string(&view.get_content());
|
|
|
|
|
- view.set_content("");
|
|
|
|
|
- s
|
|
|
|
|
- })
|
|
|
|
|
- .map(|x| x.to_string())
|
|
|
|
|
- .unwrap_or("".to_string());
|
|
|
|
|
-
|
|
|
|
|
- if get_appdata(siv).blocked_phrases.contains(&text) || text.is_empty() {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- siv.with_user_data(|appdata: &mut Appdata| {
|
|
|
|
|
- appdata.blocked_phrases.push(text.clone());
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- siv.call_on_name(
|
|
|
|
|
- &wordslist_id_typingarea_clone,
|
|
|
|
|
- |view: &mut NamedView<SelectView>| {
|
|
|
|
|
- view.get_mut().add_item_str(text);
|
|
|
|
|
- },
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- save_appdata(siv);
|
|
|
|
|
- ui::visual_update(siv);
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- let d = Dialog::new()
|
|
|
|
|
- .title(ui::Labels::BlockedWords.localize(language))
|
|
|
|
|
- .button(ui::Labels::Close.localize(language), |siv| {
|
|
|
|
|
- ui::keybind_close_manual_end(siv, false);
|
|
|
|
|
- })
|
|
|
|
|
- .content(
|
|
|
|
|
- LinearLayout::vertical()
|
|
|
|
|
- .child(ScrollView::new(wordslist_view.with_name(wordslist_id)))
|
|
|
|
|
- .child(DummyView.fixed_height(1))
|
|
|
|
|
- .child(
|
|
|
|
|
- LinearLayout::horizontal()
|
|
|
|
|
- .child(typing_area.min_width(DIALOGUE_MIN_SIZE.0 as usize))
|
|
|
|
|
- .child(typing_button),
|
|
|
|
|
- ),
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- ui::keybind_setup_close_once(siv);
|
|
|
|
|
- siv.add_layer(d);
|
|
|
|
|
- })
|
|
|
|
|
- .with_name(ui::BLOCKED_WORDS_BUTTON_ID)
|
|
|
|
|
- };
|
|
|
|
|
|
|
+ }))
|
|
|
|
|
+ .expect("Failed to send callback from background thread.");
|
|
|
|
|
|
|
|
- // Server settings
|
|
|
|
|
- let server_settings_button = Button::new("", |siv| {
|
|
|
|
|
- let appdata = get_appdata(siv);
|
|
|
|
|
- let language = appdata.language;
|
|
|
|
|
-
|
|
|
|
|
- ui::keybind_setup_close_once(siv);
|
|
|
|
|
-
|
|
|
|
|
- siv.add_layer(
|
|
|
|
|
- cursive::views::Dialog::new()
|
|
|
|
|
- .title(ui::Labels::ServerSettings.localize(language))
|
|
|
|
|
- .content(
|
|
|
|
|
- LinearLayout::vertical()
|
|
|
|
|
- .child(
|
|
|
|
|
- LinearLayout::horizontal()
|
|
|
|
|
- .child(
|
|
|
|
|
- TextView::new(ui::Labels::ServerAddress.localize(language))
|
|
|
|
|
- .fixed_width(ui::SERVER_SETTINGS_FIELD_SIZE.0 / 2),
|
|
|
|
|
- )
|
|
|
|
|
- .child(DummyView.fixed_width(1))
|
|
|
|
|
- .child(
|
|
|
|
|
- EditView::new()
|
|
|
|
|
- .content(appdata.api_endpoint)
|
|
|
|
|
- .with_name(ui::SERVER_SETTINGS_ADDRESS_FIELD_ID)
|
|
|
|
|
- .min_width(ui::SERVER_SETTINGS_FIELD_SIZE.0)
|
|
|
|
|
- .max_height(ui::SERVER_SETTINGS_FIELD_SIZE.1),
|
|
|
|
|
- ),
|
|
|
|
|
- )
|
|
|
|
|
- .child(
|
|
|
|
|
- LinearLayout::horizontal()
|
|
|
|
|
- .child(
|
|
|
|
|
- TextView::new(ui::Labels::ServerRefreshRate.localize(language))
|
|
|
|
|
- .fixed_width(ui::SERVER_SETTINGS_FIELD_SIZE.0 / 2),
|
|
|
|
|
- )
|
|
|
|
|
- .child(DummyView.fixed_width(1))
|
|
|
|
|
- .child(
|
|
|
|
|
- EditView::new()
|
|
|
|
|
- .content(appdata.api_refresh_rate.to_string())
|
|
|
|
|
- .with_name(ui::SERVER_SETTINGS_REFRESH_FIELD_ID)
|
|
|
|
|
- .min_width(ui::SERVER_SETTINGS_FIELD_SIZE.0)
|
|
|
|
|
- .max_height(ui::SERVER_SETTINGS_FIELD_SIZE.1),
|
|
|
|
|
- ),
|
|
|
|
|
- )
|
|
|
|
|
- .child(
|
|
|
|
|
- LinearLayout::horizontal()
|
|
|
|
|
- .child(
|
|
|
|
|
- TextView::new(ui::Labels::Password.localize(language))
|
|
|
|
|
- .fixed_width(ui::SERVER_SETTINGS_FIELD_SIZE.0 / 2),
|
|
|
|
|
- )
|
|
|
|
|
- .child(DummyView.fixed_width(1))
|
|
|
|
|
- .child(
|
|
|
|
|
- EditView::new()
|
|
|
|
|
- .content(appdata.api_password.to_string())
|
|
|
|
|
- .with_name(ui::SERVER_SETTINGS_PASSWORD_FIELD_ID)
|
|
|
|
|
- .min_width(ui::SERVER_SETTINGS_FIELD_SIZE.0)
|
|
|
|
|
- .max_height(ui::SERVER_SETTINGS_FIELD_SIZE.1),
|
|
|
|
|
- ),
|
|
|
|
|
- ),
|
|
|
|
|
- )
|
|
|
|
|
- .button(ui::Labels::Ok.localize(language), |siv| {
|
|
|
|
|
- let input_addr = siv
|
|
|
|
|
- .call_on_name(
|
|
|
|
|
- ui::SERVER_SETTINGS_ADDRESS_FIELD_ID,
|
|
|
|
|
- |view: &mut EditView| view.get_content(),
|
|
|
|
|
- )
|
|
|
|
|
- .expect("Failed to retrieve server settings address input.");
|
|
|
|
|
-
|
|
|
|
|
- let input_refresh = siv
|
|
|
|
|
- .call_on_name(
|
|
|
|
|
- ui::SERVER_SETTINGS_REFRESH_FIELD_ID,
|
|
|
|
|
- |view: &mut EditView| view.get_content(),
|
|
|
|
|
- )
|
|
|
|
|
- .expect("Failed to retrieve server settings refresh rate input.");
|
|
|
|
|
-
|
|
|
|
|
- let input_password = siv
|
|
|
|
|
- .call_on_name(
|
|
|
|
|
- ui::SERVER_SETTINGS_PASSWORD_FIELD_ID,
|
|
|
|
|
- |view: &mut EditView| view.get_content(),
|
|
|
|
|
- )
|
|
|
|
|
- .expect("Failed to retrieve server settings password input.");
|
|
|
|
|
-
|
|
|
|
|
- siv.with_user_data(|appdata: &mut Appdata| {
|
|
|
|
|
- appdata.api_endpoint = input_addr.to_string();
|
|
|
|
|
-
|
|
|
|
|
- let mut password = input_password.to_string();
|
|
|
|
|
- if password.is_empty() {
|
|
|
|
|
- password = DEFAULT_PASSWORD.to_string();
|
|
|
|
|
- }
|
|
|
|
|
- appdata.api_password = password;
|
|
|
|
|
|
|
+ timer += 1;
|
|
|
|
|
+ thread::sleep(Duration::from_secs(1));
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- if let Ok(rate) = input_refresh.parse() {
|
|
|
|
|
- appdata.api_refresh_rate = rate;
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- save_appdata(siv);
|
|
|
|
|
- ui::visual_update(siv);
|
|
|
|
|
- ui::keybind_close_manual_end(siv, false);
|
|
|
|
|
- })
|
|
|
|
|
- .button(ui::Labels::Cancel.localize(language), |siv| {
|
|
|
|
|
- ui::keybind_close_manual_end(siv, false);
|
|
|
|
|
- })
|
|
|
|
|
- .min_size(DIALOGUE_MIN_SIZE),
|
|
|
|
|
- );
|
|
|
|
|
- })
|
|
|
|
|
- .with_name(ui::SERVER_SETTINGS_BUTTON_ID);
|
|
|
|
|
-
|
|
|
|
|
- // Main layout
|
|
|
|
|
- let main_layout = LinearLayout::vertical()
|
|
|
|
|
- .child(
|
|
|
|
|
- LinearLayout::horizontal()
|
|
|
|
|
- .child(
|
|
|
|
|
- LinearLayout::vertical()
|
|
|
|
|
- .child(channels_panel.fixed_width(USER_PANEL_SIZE).full_height())
|
|
|
|
|
- .child(channel_current_panel),
|
|
|
|
|
- )
|
|
|
|
|
- .child(
|
|
|
|
|
- LinearLayout::vertical()
|
|
|
|
|
- .child(users_panel.resized(
|
|
|
|
|
- cursive::view::SizeConstraint::Fixed(USER_PANEL_SIZE),
|
|
|
|
|
- cursive::view::SizeConstraint::Full,
|
|
|
|
|
- ))
|
|
|
|
|
- .child(current_username_panel),
|
|
|
|
|
- )
|
|
|
|
|
- .child(messages_panel.full_width()),
|
|
|
|
|
- )
|
|
|
|
|
- .child(input_panel)
|
|
|
|
|
- .child(
|
|
|
|
|
- LinearLayout::horizontal()
|
|
|
|
|
- .child(language_button)
|
|
|
|
|
- .child(DummyView.full_width())
|
|
|
|
|
- .child(username_button)
|
|
|
|
|
- .child(DummyView.full_width())
|
|
|
|
|
- .child(channels_new_button)
|
|
|
|
|
- .child(DummyView.full_width())
|
|
|
|
|
- .child(blocked_words_list_button)
|
|
|
|
|
- .child(DummyView.full_width())
|
|
|
|
|
- .child(server_settings_button)
|
|
|
|
|
- .child(DummyView.full_width())
|
|
|
|
|
- .child(refresh_button)
|
|
|
|
|
- .full_width(),
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- siv.add_fullscreen_layer(main_layout);
|
|
|
|
|
|
|
+ siv.with_user_data(|appdata: &mut Appdata| {
|
|
|
|
|
+ appdata.intro_screen_shown_until = utils::time::time_millis() + 2000;
|
|
|
|
|
+ });
|
|
|
siv.run();
|
|
siv.run();
|
|
|
}
|
|
}
|