Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hide message text input bar if the user cannot send messages in a room #253

Merged
merged 23 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 35 additions & 1 deletion src/home/room_screen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ live_design! {
COLOR_PROFILE_CIRCLE = #xfff8ee
TYPING_NOTICE_ANIMATION_DURATION = 0.3

CAN_NOT_SEND_NOTICE = "You don't have permission to post to this room."

FillerY = <View> {width: Fill}

FillerX = <View> {height: Fill}
Expand Down Expand Up @@ -810,7 +812,7 @@ live_design! {
location_preview = <LocationPreview> { }

// Below that, display a view that holds the message input bar and send button.
<View> {
input_bar = <View> {
width: Fill, height: Fit
flow: Right,
align: {y: 0.5},
Expand Down Expand Up @@ -917,6 +919,24 @@ live_design! {
icon_walk: {width: 18.0, height: Fit},
}
}
can_not_send_message_notice = <View> {
visible: false
show_bg: true
draw_bg: {
color: (COLOR_SECONDARY)
}
padding: {left: 75}
align: {y: 0.3}
width: Fill, height: 37.5

text = <Label> {
draw_text: {
color: (COLOR_TEXT)
text_style: <THEME_FONT_ITALIC>{font_size: 12.2}
}
text: (CAN_NOT_SEND_NOTICE)
}
}
}

// The top space should be displayed on top of the timeline
Expand Down Expand Up @@ -1714,6 +1734,14 @@ impl RoomScreen {
// if the list of typing users gets updated many times in a row.
typing_users = users;
}

TimelineUpdate::CanUserSendMessage(can_user_send_message) => {
let input_bar = self.view.view(id!(input_bar));
let can_not_send_message_notice = self.view.view(id!(can_not_send_message_notice));

input_bar.set_visible(can_user_send_message);
can_not_send_message_notice.set_visible(!can_user_send_message);
}
}
}

Expand Down Expand Up @@ -1845,6 +1873,9 @@ impl RoomScreen {
Did you forget to save the timeline state back to the global map of states?",
);

// Send request as `MatrixRequest` to check post permission.
submit_async_request(MatrixRequest::CheckCanUserSendMessage { room_id: room_id.clone() });

let (mut tl_state, first_time_showing_room) = if let Some(existing) = TIMELINE_STATES.lock().unwrap().remove(&room_id) {
(existing, false)
} else {
Expand Down Expand Up @@ -2181,6 +2212,9 @@ pub enum TimelineUpdate {
/// The list of users (their displayable name) who are currently typing in this room.
users: Vec<String>,
},
/// A notice that the permission of user's ability to send messages in this room,
/// this condition is simple so that we only use `bool`
CanUserSendMessage (bool)
}

/// The global set of all timeline states, one entry per room.
Expand Down
61 changes: 49 additions & 12 deletions src/sliding_sync.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use anyhow::{Result, bail};
use anyhow::{bail, Result};
use clap::Parser;
use eyeball::Subscriber;
use eyeball_im::VectorDiff;
Expand Down Expand Up @@ -102,7 +102,7 @@ async fn build_client(
let homeserver_url = cli.homeserver.as_deref()
.unwrap_or("https://matrix-client.matrix.org/");
// .unwrap_or("https://matrix.org/");

let mut builder = Client::builder()
.server_name_or_homeserver_url(homeserver_url)
// Use a sqlite database to persist the client's encryption setup.
Expand Down Expand Up @@ -180,7 +180,7 @@ async fn login(
bail!("Failed to login as {}: {login_result:?}", cli.username);
}
}

LoginRequest::LoginBySSOSuccess(client, client_session) => {
if let Err(e) = persistent_state::save_session(&client, client_session).await {
error!("Failed to save session state to storage: {e:?}");
Expand Down Expand Up @@ -226,7 +226,7 @@ async fn populate_login_types(
}

/// Which direction to paginate in.
///
///
/// * `Forwards` will retrieve later events (towards the end of the timeline),
/// which only works if the timeline is *focused* on a specific event.
/// * `Backwards`: the more typical choice, in which earlier events are retrieved
Expand Down Expand Up @@ -357,6 +357,12 @@ pub enum MatrixRequest {
FullyReadReceipt{
room_id: OwnedRoomId,
event_id: OwnedEventId,
},
/// Sends a request checking if the currently logged-in user can send a message to the given room.
///
/// The response is delivered back to the main UI thread via a `TimelineUpdate::CanUserSendMessage`.
CheckCanUserSendMessage{
room_id: OwnedRoomId,
}
}

Expand All @@ -374,7 +380,7 @@ pub enum LoginRequest{
LoginBySSOSuccess(Client, ClientSessionPersisted),
LoginByCli,
HomeserverLoginTypesQuery(String),

}
/// Information needed to log in to a Matrix homeserver.
pub struct LoginByPassword {
Expand Down Expand Up @@ -774,7 +780,34 @@ async fn async_worker(
Err(_e) => error!("Failed to send fully read receipt to room {room_id}, event {event_id}; error: {_e:?}"),
}
});
}
},

MatrixRequest::CheckCanUserSendMessage { room_id } => {
let (timeline, sender) = {
let all_room_info = ALL_ROOM_INFO.lock().unwrap();
let Some(room_info) = all_room_info.get(&room_id) else {
log!("BUG: room info not found for fetch members request {room_id}");
continue;
};

(room_info.timeline.clone(), room_info.timeline_update_sender.clone())
};

let Some(user_id) = current_user_id() else { continue };

let _check_can_user_send_message_task = Handle::current().spawn(async move {
let can_user_send_message = timeline.room().can_user_send_message(
&user_id,
matrix_sdk::ruma::events::MessageLikeEventType::Message
)
.await
.unwrap_or(false);

if let Err(e) = sender.send(TimelineUpdate::CanUserSendMessage(can_user_send_message)) {
error!("Failed to send the result of if user can send message: {e}")
}
});
}
}
}

Expand All @@ -798,7 +831,7 @@ pub fn start_matrix_tokio() -> Result<()> {
// Create a channel to be used between UI thread(s) and the async worker thread.
let (sender, receiver) = tokio::sync::mpsc::unbounded_channel::<MatrixRequest>();
REQUEST_SENDER.set(sender).expect("BUG: REQUEST_SENDER already set!");

let (login_sender, login_receiver) = tokio::sync::mpsc::channel(1);
// Start a high-level async task that will start and monitor all other tasks.
let _monitor = rt.spawn(async move {
Expand Down Expand Up @@ -949,7 +982,7 @@ pub fn is_user_ignored(user_id: &UserId) -> bool {


/// Returns three channel endpoints related to the timeline for the given room.
///
///
/// 1. A timeline update sender.
/// 2. The timeline update receiver, which is a singleton, and can only be taken once.
/// 3. A `tokio::watch` sender that can be used to send requests to the timeline subscriber handler.
Expand Down Expand Up @@ -1804,6 +1837,7 @@ async fn timeline_subscriber_handler(
}
}


if num_updates > 0 {
let new_latest_event = if reobtain_latest_event {
timeline.latest_event().await
Expand Down Expand Up @@ -1889,6 +1923,9 @@ fn update_latest_event(
AnyOtherFullStateEventContent::RoomAvatar(_avatar_event) => {
room_avatar_changed = true;
}
AnyOtherFullStateEventContent::RoomPowerLevels(_power_level_event) => {
submit_async_request(MatrixRequest::CheckCanUserSendMessage { room_id: room_id.clone() })
}
_ => { }
}
}
Expand Down Expand Up @@ -1955,10 +1992,10 @@ async fn spawn_sso_server(
..Default::default()
};
Handle::current().spawn(async move {
let Ok((client, client_session)) = build_client(&cli, app_data_dir()).await else {
Cx::post_action(LoginAction::LoginFailure("Failed to establish client".to_string()));
return;
};
let Ok((client, client_session)) = build_client(&cli, app_data_dir()).await else {
Cx::post_action(LoginAction::LoginFailure("Failed to establish client".to_string()));
return;
};
let mut is_logged_in = false;
match client
.matrix_auth()
Expand Down
Loading