[fractal] session: Allow to join a room by ID, alias or permalink
- From: Kévin Commaille <kcommaille src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [fractal] session: Allow to join a room by ID, alias or permalink
- Date: Fri, 7 Oct 2022 18:40:59 +0000 (UTC)
commit 5d7d49a9733d6e0c275df33b2cdd8218f88cf7bd
Author: Kévin Commaille <zecakeh tedomum fr>
Date: Tue Oct 4 16:25:05 2022 +0200
session: Allow to join a room by ID, alias or permalink
data/resources/resources.gresource.xml | 1 +
data/resources/ui/join-room-dialog.ui | 18 +++++++
data/resources/ui/sidebar.ui | 5 +-
po/POTFILES.in | 1 +
src/session/content/explore/public_room.rs | 2 +-
src/session/mod.rs | 79 +++++++++++++++++++++++++++---
src/session/room/mod.rs | 12 +++++
src/session/room_list.rs | 24 +++++++--
8 files changed, 129 insertions(+), 13 deletions(-)
---
diff --git a/data/resources/resources.gresource.xml b/data/resources/resources.gresource.xml
index 58d0a9fb1..1ab003879 100644
--- a/data/resources/resources.gresource.xml
+++ b/data/resources/resources.gresource.xml
@@ -112,6 +112,7 @@
<file compressed="true" preprocess="xml-stripblanks"
alias="event-source-dialog.ui">ui/event-source-dialog.ui</file>
<file compressed="true" preprocess="xml-stripblanks" alias="greeter.ui">ui/greeter.ui</file>
<file compressed="true" preprocess="xml-stripblanks"
alias="identity-verification-widget.ui">ui/identity-verification-widget.ui</file>
+ <file compressed="true" preprocess="xml-stripblanks"
alias="join-room-dialog.ui">ui/join-room-dialog.ui</file>
<file compressed="true" preprocess="xml-stripblanks"
alias="login-advanced-dialog.ui">ui/login-advanced-dialog.ui</file>
<file compressed="true" preprocess="xml-stripblanks"
alias="login-idp-button.ui">ui/login-idp-button.ui</file>
<file compressed="true" preprocess="xml-stripblanks" alias="login.ui">ui/login.ui</file>
diff --git a/data/resources/ui/join-room-dialog.ui b/data/resources/ui/join-room-dialog.ui
new file mode 100644
index 000000000..d12ba2e7e
--- /dev/null
+++ b/data/resources/ui/join-room-dialog.ui
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <object class="AdwMessageDialog" id="dialog">
+ <property name="heading" translatable="yes">Join a Room</property>
+ <property name="body" translatable="yes">Enter a room ID, room alias, or permalink.</property>
+ <property name="default-response">join</property>
+ <property name="close-response">cancel</property>
+ <responses>
+ <response id="cancel" translatable="yes">_Cancel</response>
+ <response id="join" translatable="yes" appearance="suggested" enabled="false">_Join</response>
+ </responses>
+ <property name="extra-child">
+ <object class="GtkEntry" id="entry">
+ <property name="activates-default">True</property>
+ </object>
+ </property>
+ </object>
+</interface>
diff --git a/data/resources/ui/sidebar.ui b/data/resources/ui/sidebar.ui
index 69b31d73a..1b4c94617 100644
--- a/data/resources/ui/sidebar.ui
+++ b/data/resources/ui/sidebar.ui
@@ -6,6 +6,10 @@
<attribute name="label" translatable="yes">_New Room</attribute>
<attribute name="action">session.room-creation</attribute>
</item>
+ <item>
+ <attribute name="label" translatable="yes">_Join Room</attribute>
+ <attribute name="action">session.show-join-room</attribute>
+ </item>
</section>
<section>
<item>
@@ -170,4 +174,3 @@
</child>
</template>
</interface>
-
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 78987dfa3..abc18a60c 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -34,6 +34,7 @@ data/resources/ui/event-menu.ui
data/resources/ui/event-source-dialog.ui
data/resources/ui/greeter.ui
data/resources/ui/identity-verification-widget.ui
+data/resources/ui/join-room-dialog.ui
data/resources/ui/login-advanced-dialog.ui
data/resources/ui/login.ui
data/resources/ui/member-menu.ui
diff --git a/src/session/content/explore/public_room.rs b/src/session/content/explore/public_room.rs
index 9995251d3..50b668b97 100644
--- a/src/session/content/explore/public_room.rs
+++ b/src/session/content/explore/public_room.rs
@@ -193,7 +193,7 @@ impl PublicRoom {
} else if let Some(matrix_public_room) = self.matrix_public_room() {
let room_id: &RoomId = matrix_public_room.room_id.as_ref();
self.room_list()
- .join_by_id_or_alias(<&RoomOrAliasId>::from(room_id).to_owned());
+ .join_by_id_or_alias(<&RoomOrAliasId>::from(room_id).to_owned(), vec![]);
}
}
}
diff --git a/src/session/mod.rs b/src/session/mod.rs
index 53265685f..780469688 100644
--- a/src/session/mod.rs
+++ b/src/session/mod.rs
@@ -13,16 +13,12 @@ pub mod verification;
use std::{collections::HashSet, fs, path::PathBuf, time::Duration};
-use adw::subclass::prelude::BinImpl;
+use adw::{prelude::*, subclass::prelude::*};
use futures::StreamExt;
use gettextrs::gettext;
use gtk::{
- self, gdk, gio,
- gio::prelude::*,
- glib,
+ self, gdk, gio, glib,
glib::{clone, signal::SignalHandlerId},
- prelude::*,
- subclass::prelude::*,
CompositeTemplate,
};
use log::{debug, error, warn};
@@ -44,7 +40,8 @@ use matrix_sdk::{
direct::DirectEventContent, room::encryption::SyncRoomEncryptionEvent,
GlobalAccountDataEvent,
},
- RoomId,
+ matrix_uri::MatrixId,
+ MatrixUri, OwnedRoomOrAliasId, OwnedServerName, RoomId, RoomOrAliasId,
},
store::{MigrationConflictStrategy, OpenStoreError, SledStateStore},
Client, ClientBuildError, Error, HttpError, RumaApiError, StoreError,
@@ -74,7 +71,7 @@ use crate::{
secret::{Secret, StoredSession},
session::sidebar::ItemList,
spawn, spawn_tokio, toast,
- utils::check_if_reachable,
+ utils::{check_if_reachable, parse_matrix_to_uri},
UserFacingError, Window,
};
@@ -174,6 +171,12 @@ mod imp {
session.show_room_creation_dialog();
});
+ klass.install_action("session.show-join-room", None, move |widget, _, _| {
+ spawn!(clone!(@weak widget => async move {
+ widget.show_join_room_dialog().await;
+ }));
+ });
+
klass.add_binding_action(
gdk::Key::Escape,
gdk::ModifierType::empty(),
@@ -821,6 +824,40 @@ impl Session {
window.show();
}
+ async fn show_join_room_dialog(&self) {
+ let builder = gtk::Builder::from_resource("/org/gnome/Fractal/join-room-dialog.ui");
+ let dialog = builder.object::<adw::MessageDialog>("dialog").unwrap();
+ let entry = builder.object::<gtk::Entry>("entry").unwrap();
+
+ entry.connect_changed(clone!(@weak self as obj, @weak dialog => move |entry| {
+ let room = parse_room(&entry.text());
+ dialog.set_response_enabled("join", room.is_some());
+
+ if room
+ .and_then(|(room_id, _)| obj.room_list().find_joined_room(&room_id))
+ .is_some()
+ {
+ dialog.set_response_label("join", &gettext("_View"));
+ } else {
+ dialog.set_response_label("join", &gettext("_Join"));
+ }
+ }));
+
+ dialog.set_transient_for(self.parent_window().as_ref());
+ if dialog.run_future().await == "join" {
+ let (room_id, via) = match parse_room(&entry.text()) {
+ Some(room) => room,
+ None => return,
+ };
+
+ if let Some(room) = self.room_list().find_joined_room(&room_id) {
+ self.select_room(Some(room));
+ } else {
+ self.room_list().join_by_id_or_alias(room_id, via)
+ }
+ }
+ }
+
pub async fn logout(&self, cleanup: bool) {
let stack = &self.imp().stack;
self.emit_by_name::<()>("logged-out", &[]);
@@ -1027,3 +1064,29 @@ async fn create_client(
.await
.map_err(Into::into)
}
+
+fn parse_room(room: &str) -> Option<(OwnedRoomOrAliasId, Vec<OwnedServerName>)> {
+ MatrixUri::parse(room)
+ .ok()
+ .and_then(|uri| match uri.id() {
+ MatrixId::Room(room_id) => Some((room_id.clone().into(), uri.via().to_owned())),
+ MatrixId::RoomAlias(room_alias) => {
+ Some((room_alias.clone().into(), uri.via().to_owned()))
+ }
+ _ => None,
+ })
+ .or_else(|| {
+ parse_matrix_to_uri(room)
+ .ok()
+ .and_then(|(id, via)| match id {
+ MatrixId::Room(room_id) => Some((room_id.into(), via)),
+ MatrixId::RoomAlias(room_alias) => Some((room_alias.into(), via)),
+ _ => None,
+ })
+ })
+ .or_else(|| {
+ RoomOrAliasId::parse(room)
+ .ok()
+ .map(|room_id| (room_id, vec![]))
+ })
+}
diff --git a/src/session/room/mod.rs b/src/session/room/mod.rs
index e5256d5bd..efbd5e09f 100644
--- a/src/session/room/mod.rs
+++ b/src/session/room/mod.rs
@@ -466,6 +466,18 @@ impl Room {
);
}
+ pub fn is_joined(&self) -> bool {
+ matches!(
+ self.category(),
+ RoomType::Favorite
+ | RoomType::Normal
+ | RoomType::LowPriority
+ | RoomType::Outdated
+ | RoomType::Space
+ | RoomType::Direct
+ )
+ }
+
pub fn category(&self) -> RoomType {
self.imp().category.get()
}
diff --git a/src/session/room_list.rs b/src/session/room_list.rs
index 7c7dbf52a..74c103475 100644
--- a/src/session/room_list.rs
+++ b/src/session/room_list.rs
@@ -5,7 +5,7 @@ use indexmap::map::IndexMap;
use log::error;
use matrix_sdk::{
deserialized_responses::Rooms as ResponseRooms,
- ruma::{OwnedRoomId, OwnedRoomOrAliasId, RoomId, RoomOrAliasId},
+ ruma::{OwnedRoomId, OwnedRoomOrAliasId, OwnedServerName, RoomId, RoomOrAliasId},
};
use crate::{
@@ -298,7 +298,7 @@ impl RoomList {
}
}
- pub fn join_by_id_or_alias(&self, identifier: OwnedRoomOrAliasId) {
+ pub fn join_by_id_or_alias(&self, identifier: OwnedRoomOrAliasId, via: Vec<OwnedServerName>) {
let client = self.session().client();
let identifier_clone = identifier.clone();
@@ -306,7 +306,7 @@ impl RoomList {
let handle = spawn_tokio!(async move {
client
- .join_room_by_id_or_alias(&identifier_clone, &[])
+ .join_room_by_id_or_alias(&identifier_clone, &via)
.await
});
@@ -344,4 +344,22 @@ impl RoomList {
None
})
}
+
+ pub fn find_joined_room(&self, room_id: &RoomOrAliasId) -> Option<Room> {
+ let room_id = room_id.as_str();
+ self.imp()
+ .list
+ .borrow()
+ .values()
+ .find(|room| {
+ (room.room_id() == room_id
+ || room
+ .matrix_room()
+ .canonical_alias()
+ .filter(|id| id == room_id)
+ .is_some())
+ && room.is_joined()
+ })
+ .cloned()
+ }
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]