Save language chosen for spell check for each room
Before, when a user changed the language for spell check, that language was saved by gtk application-wide. With this commit, the language chosen by the user for spell check gets saved in the Matrix account data of the particular room the language was chosen in; and, by syncronizing, it also gets saved in the new field `language` of Room. When the user enters a room, gspell gets set for the language saved for that room.
This commit is contained in:
parent
1dac3f21d4
commit
d78b52a371
10 changed files with 119 additions and 1 deletions
|
@ -236,6 +236,9 @@ pub fn backend_loop(rx: Receiver<BKResponse>) {
|
|||
APPOP!(show_error, (error));
|
||||
APPOP!(set_state, (state));
|
||||
}
|
||||
BKResponse::ChangeLanguage(Err(err)) => {
|
||||
error!("Error forming url to set room language: {:?}", err);
|
||||
}
|
||||
BKResponse::LoginError(_) => {
|
||||
let error = i18n("Can’t login, try again");
|
||||
let st = AppState::Login;
|
||||
|
|
40
fractal-gtk/src/app/connect/language.rs
Normal file
40
fractal-gtk/src/app/connect/language.rs
Normal file
|
@ -0,0 +1,40 @@
|
|||
use crate::app::App;
|
||||
use crate::backend::BKCommand;
|
||||
|
||||
use gtk::prelude::*;
|
||||
|
||||
// The TextBufferExt alias is necessary to avoid conflict with gtk's TextBufferExt
|
||||
use gspell::{CheckerExt, TextBuffer, TextBufferExt as GspellTextBufferExt};
|
||||
|
||||
impl App {
|
||||
pub fn connect_language(&self) {
|
||||
let textview = self.ui.sventry.view.upcast_ref::<gtk::TextView>();
|
||||
if let Some(checker) = textview
|
||||
.get_buffer()
|
||||
.and_then(|gtk_buffer| TextBuffer::get_from_gtk_text_buffer(>k_buffer))
|
||||
.and_then(|gs_buffer| gs_buffer.get_spell_checker())
|
||||
{
|
||||
let op = self.op.clone();
|
||||
let _signal_handler = checker.connect_property_language_notify(move |checker| {
|
||||
if let Some(lang_code) = checker
|
||||
.get_language()
|
||||
.and_then(|lang| lang.get_code())
|
||||
.map(|lang_code| String::from(lang_code))
|
||||
{
|
||||
/*If the checker is modified by fn set_language in fractal-gtk/src/appop/room.rs
|
||||
due to the user switching rooms, the op mutex is locked already.
|
||||
If the checker is modified by gtk due to the user switching the language, the op mutex is unlocked. */
|
||||
if let Ok(op) = op.try_lock() {
|
||||
if let Some(active_room) = &op.active_room {
|
||||
let server = &op.server_url;
|
||||
let access_token = unwrap_or_unit_return!(op.access_token.clone());
|
||||
op.backend
|
||||
.send(BKCommand::ChangeLanguage(access_token, server.clone(), lang_code, active_room.clone()))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ mod directory;
|
|||
mod headerbar;
|
||||
mod invite;
|
||||
mod join_room;
|
||||
mod language;
|
||||
mod leave_room;
|
||||
mod markdown;
|
||||
mod new_room;
|
||||
|
@ -20,6 +21,7 @@ impl App {
|
|||
self.connect_send();
|
||||
self.connect_markdown();
|
||||
self.connect_autocomplete();
|
||||
self.connect_language();
|
||||
|
||||
self.connect_directory();
|
||||
self.connect_leave_room_dialog();
|
||||
|
|
|
@ -34,7 +34,7 @@ mod member;
|
|||
mod message;
|
||||
mod notifications;
|
||||
mod notify;
|
||||
mod room;
|
||||
pub mod room;
|
||||
mod room_settings;
|
||||
mod start_chat;
|
||||
pub mod state;
|
||||
|
|
|
@ -27,6 +27,9 @@ use rand::{thread_rng, Rng};
|
|||
|
||||
use glib::functions::markup_escape_text;
|
||||
|
||||
// The TextBufferExt alias is necessary to avoid conflict with gtk's TextBufferExt
|
||||
use gspell::{CheckerExt, TextBuffer, TextBufferExt as GspellTextBufferExt};
|
||||
|
||||
use std::time::Instant;
|
||||
|
||||
pub struct Force(pub bool);
|
||||
|
@ -63,6 +66,10 @@ impl AppOp {
|
|||
} else if self.rooms.contains_key(&room.id) {
|
||||
// TODO: update the existing rooms
|
||||
let update_room = self.rooms.get_mut(&room.id).unwrap();
|
||||
if room.language.is_some() {
|
||||
update_room.language = room.language.clone();
|
||||
};
|
||||
|
||||
let typing_users: Vec<Member> = room
|
||||
.typing_users
|
||||
.iter()
|
||||
|
@ -152,6 +159,9 @@ impl AppOp {
|
|||
pub fn set_active_room_by_id(&mut self, id: String) {
|
||||
let access_token = unwrap_or_unit_return!(self.access_token.clone());
|
||||
if let Some(room) = self.rooms.get(&id) {
|
||||
if let Some(language) = room.language.clone() {
|
||||
self.set_language(language);
|
||||
}
|
||||
if let RoomMembership::Invited(ref sender) = room.membership {
|
||||
self.show_inv_dialog(Some(sender), room.name.as_ref());
|
||||
self.invitation_roomid = Some(room.id.clone());
|
||||
|
@ -698,4 +708,17 @@ impl AppOp {
|
|||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_language(&self, lang_code: String) {
|
||||
if let Some(language) = &gspell::Language::lookup(&lang_code) {
|
||||
let textview = self.ui.sventry.view.upcast_ref::<gtk::TextView>();
|
||||
if let Some(gs_checker) = textview
|
||||
.get_buffer()
|
||||
.and_then(|gtk_buffer| TextBuffer::get_from_gtk_text_buffer(>k_buffer))
|
||||
.and_then(|gs_buffer| GspellTextBufferExt::get_spell_checker(&gs_buffer))
|
||||
{
|
||||
CheckerExt::set_language(&gs_checker, Some(language))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -308,6 +308,10 @@ impl Backend {
|
|||
let r = room::invite(self, server, access_token, room, userid);
|
||||
bkerror!(r, tx, BKResponse::InviteError);
|
||||
}
|
||||
Ok(BKCommand::ChangeLanguage(access_token, server, lang, room)) => {
|
||||
let r = room::set_language(self, access_token, server, &room, &lang);
|
||||
bkerror2!(r, tx, BKResponse::ChangeLanguage);
|
||||
}
|
||||
|
||||
// Media module
|
||||
Ok(BKCommand::GetThumbAsync(server, media, ctx)) => {
|
||||
|
|
|
@ -30,6 +30,7 @@ use crate::backend::types::BackendData;
|
|||
use crate::backend::types::RoomType;
|
||||
|
||||
use crate::r0::filter::RoomEventFilter;
|
||||
use crate::r0::sync::sync_events::Language;
|
||||
use crate::r0::AccessToken;
|
||||
use crate::types::ExtraContent;
|
||||
use crate::types::Member;
|
||||
|
@ -954,3 +955,34 @@ fn put_media(url: &str, file: Vec<u8>) -> Result<JsonValue, Error> {
|
|||
.json()
|
||||
.or(Err(Error::BackendError))
|
||||
}
|
||||
|
||||
pub fn set_language(
|
||||
bk: &Backend,
|
||||
access_token: AccessToken,
|
||||
server: Url,
|
||||
roomid: &str,
|
||||
language_code: &str,
|
||||
) -> Result<(), Error> {
|
||||
let userid = bk.data.lock().unwrap().user_id.clone();
|
||||
let url = bk.url(
|
||||
server,
|
||||
&access_token,
|
||||
&format!(
|
||||
"user/{}/rooms/{}/account_data/org.gnome.fractal.language",
|
||||
userid,
|
||||
roomid.clone()
|
||||
),
|
||||
vec![],
|
||||
)?;
|
||||
let body = json!(Language {
|
||||
input_language: language_code.to_string(),
|
||||
});
|
||||
|
||||
put!(url, &body, |_| {}, |err| {
|
||||
error!(
|
||||
"Matrix failed to set room language with error code: {:?}",
|
||||
err
|
||||
)
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -86,6 +86,7 @@ pub enum BKCommand {
|
|||
ListStickers(AccessToken),
|
||||
SendSticker(Url, AccessToken, String, Sticker),
|
||||
PurchaseSticker(AccessToken, StickerGroup),
|
||||
ChangeLanguage(AccessToken, Url, String, String),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -144,6 +145,7 @@ pub enum BKResponse {
|
|||
SetRoomError(Error),
|
||||
GetFileAsyncError(Error),
|
||||
InviteError(Error),
|
||||
ChangeLanguage(Result<(), Error>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
|
|
|
@ -94,6 +94,7 @@ pub struct Room {
|
|||
pub direct: bool,
|
||||
pub prev_batch: Option<String>,
|
||||
pub typing_users: Vec<Member>,
|
||||
pub language: Option<String>,
|
||||
|
||||
/// Hashmap with the room users power levels
|
||||
/// the key will be the userid and the value will be the level
|
||||
|
@ -131,6 +132,11 @@ impl Room {
|
|||
.find_map(|tag| tag["content"]["tags"]["m.favourite"].as_object())
|
||||
.and(Some(RoomTag::Favourite))
|
||||
.unwrap_or(RoomTag::None);
|
||||
let room_lang = dataevs
|
||||
.iter()
|
||||
.filter(|x| x["type"] == "org.gnome.fractal.language")
|
||||
.find_map(|entry| entry["content"]["input_language"].as_str())
|
||||
.map(|lang| lang.to_string());
|
||||
|
||||
let mut r = Self {
|
||||
name: calculate_room_name(stevents, userid),
|
||||
|
@ -150,6 +156,7 @@ impl Room {
|
|||
.filter_map(parse_room_member)
|
||||
.map(|m| (m.uid.clone(), m))
|
||||
.collect(),
|
||||
language: room_lang,
|
||||
..Self::new(k.clone(), RoomMembership::Joined(room_tag))
|
||||
};
|
||||
|
||||
|
|
|
@ -173,6 +173,11 @@ pub struct AccountData {
|
|||
pub events: Vec<JsonValue>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
pub struct Language {
|
||||
pub input_language: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
pub struct ToDevice {
|
||||
// TODO: Implement Event
|
||||
|
|
Loading…
Reference in a new issue