[fractal] Save language chosen for spell check for each room
- From: Daniel Garcia Moreno <danigm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [fractal] Save language chosen for spell check for each room
- Date: Tue, 3 Dec 2019 07:20:05 +0000 (UTC)
commit d78b52a3711e52e0681788c207bc6d7b446afee8
Author: sonjita <sonjaleaheinze gmail com>
Date: Tue Nov 5 13:24:31 2019 +0100
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.
fractal-gtk/src/app/backend_loop.rs | 3 ++
fractal-gtk/src/app/connect/language.rs | 40 +++++++++++++++++++++++++++
fractal-gtk/src/app/connect/mod.rs | 2 ++
fractal-gtk/src/appop/mod.rs | 2 +-
fractal-gtk/src/appop/room.rs | 23 +++++++++++++++
fractal-matrix-api/src/backend/mod.rs | 4 +++
fractal-matrix-api/src/backend/room.rs | 32 +++++++++++++++++++++
fractal-matrix-api/src/backend/types.rs | 2 ++
fractal-matrix-api/src/model/room.rs | 7 +++++
fractal-matrix-api/src/r0/sync/sync_events.rs | 5 ++++
10 files changed, 119 insertions(+), 1 deletion(-)
---
diff --git a/fractal-gtk/src/app/backend_loop.rs b/fractal-gtk/src/app/backend_loop.rs
index dd0bc2d7..dcc87d5c 100644
--- a/fractal-gtk/src/app/backend_loop.rs
+++ b/fractal-gtk/src/app/backend_loop.rs
@@ -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;
diff --git a/fractal-gtk/src/app/connect/language.rs b/fractal-gtk/src/app/connect/language.rs
new file mode 100644
index 00000000..86889576
--- /dev/null
+++ b/fractal-gtk/src/app/connect/language.rs
@@ -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();
+ }
+ }
+ }
+ });
+ }
+ }
+}
diff --git a/fractal-gtk/src/app/connect/mod.rs b/fractal-gtk/src/app/connect/mod.rs
index 037eb15a..a180abed 100644
--- a/fractal-gtk/src/app/connect/mod.rs
+++ b/fractal-gtk/src/app/connect/mod.rs
@@ -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();
diff --git a/fractal-gtk/src/appop/mod.rs b/fractal-gtk/src/appop/mod.rs
index c2ae85cf..ffd5abc6 100644
--- a/fractal-gtk/src/appop/mod.rs
+++ b/fractal-gtk/src/appop/mod.rs
@@ -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;
diff --git a/fractal-gtk/src/appop/room.rs b/fractal-gtk/src/appop/room.rs
index 19b61698..f2ca6d13 100644
--- a/fractal-gtk/src/appop/room.rs
+++ b/fractal-gtk/src/appop/room.rs
@@ -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))
+ }
+ }
+ }
}
diff --git a/fractal-matrix-api/src/backend/mod.rs b/fractal-matrix-api/src/backend/mod.rs
index 2e470fe3..6ac048b8 100644
--- a/fractal-matrix-api/src/backend/mod.rs
+++ b/fractal-matrix-api/src/backend/mod.rs
@@ -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)) => {
diff --git a/fractal-matrix-api/src/backend/room.rs b/fractal-matrix-api/src/backend/room.rs
index a38b9926..e3568300 100644
--- a/fractal-matrix-api/src/backend/room.rs
+++ b/fractal-matrix-api/src/backend/room.rs
@@ -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(())
+}
diff --git a/fractal-matrix-api/src/backend/types.rs b/fractal-matrix-api/src/backend/types.rs
index 34a8909d..928381cf 100644
--- a/fractal-matrix-api/src/backend/types.rs
+++ b/fractal-matrix-api/src/backend/types.rs
@@ -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)]
diff --git a/fractal-matrix-api/src/model/room.rs b/fractal-matrix-api/src/model/room.rs
index 027ad176..7186d5a6 100644
--- a/fractal-matrix-api/src/model/room.rs
+++ b/fractal-matrix-api/src/model/room.rs
@@ -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))
};
diff --git a/fractal-matrix-api/src/r0/sync/sync_events.rs b/fractal-matrix-api/src/r0/sync/sync_events.rs
index e23c3298..95bae1ac 100644
--- a/fractal-matrix-api/src/r0/sync/sync_events.rs
+++ b/fractal-matrix-api/src/r0/sync/sync_events.rs
@@ -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
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]