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

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
42 changes: 41 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

NO_POST_PERMISSIOM_NOTICE = "You don't have permission to post to this room."
aaravlu marked this conversation as resolved.
Show resolved Hide resolved

FillerY = <View> {width: Fill}

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

// Below that, display a view that holds the message input bar and send button.
<View> {
bottom_input = <View> {
aaravlu marked this conversation as resolved.
Show resolved Hide resolved
aaravlu marked this conversation as resolved.
Show resolved Hide resolved
width: Fill, height: Fit
flow: Right,
align: {y: 0.5},
Expand Down Expand Up @@ -914,6 +916,24 @@ live_design! {
icon_walk: {width: 18.0, height: Fit},
}
}
no_send_permisson_notice = <View> {
visible: false
show_bg: true
draw_bg: {
color: (COLOR_SECONDARY)
}
padding: {left: 75}
align: {y: 0.5}
width: Fill, height: 32

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

// The top space should be displayed on top of the timeline
Expand Down Expand Up @@ -1486,6 +1506,9 @@ impl RoomScreen {
///
/// Redraws this RoomScreen view if any updates were applied.
fn process_timeline_updates(&mut self, cx: &mut Cx, portal_list: &PortalListRef) {
let bottom_input = self.view(id!(bottom_input));
let no_send_permisson_notice = self.view(id!(no_send_permisson_notice));

let top_space = self.view(id!(top_space));
let jump_to_bottom = self.jump_to_bottom_button(id!(jump_to_bottom));
let curr_first_id = portal_list.first_id();
Expand Down Expand Up @@ -1711,6 +1734,13 @@ impl RoomScreen {
// if the list of typing users gets updated many times in a row.
typing_users = users;
}

TimelineUpdate::CanUserPost(can_user_post) => {
let (bottom_input_visible, no_send_permisson_notice_visible) = if can_user_post { (true, false) } else { (false, true) };

bottom_input.set_visible(bottom_input_visible);
no_send_permisson_notice.set_visible(no_send_permisson_notice_visible)
}
aaravlu marked this conversation as resolved.
Show resolved Hide resolved
}
}

Expand Down Expand Up @@ -1834,6 +1864,8 @@ impl RoomScreen {
/// Invoke this when this timeline is being shown,
/// e.g., when the user navigates to this timeline.
fn show_timeline(&mut self, cx: &mut Cx) {
self.check_user_post_permission();

let room_id = self.room_id.clone()
.expect("BUG: Timeline::show_timeline(): no room_id was set.");
// just an optional sanity check
Expand Down Expand Up @@ -2098,6 +2130,13 @@ impl RoomScreen {
}
tl.last_scrolled_index = first_index;
}

/// Send request as `MatrixRequest` to check post permission.
fn check_user_post_permission(&self) {
if let Some(room_id) = self.room_id.clone() {
submit_async_request(MatrixRequest::CheckUserPostPermission { room_id })
}
}
}

impl RoomScreenRef {
Expand Down Expand Up @@ -2178,6 +2217,7 @@ pub enum TimelineUpdate {
/// The list of users (their displayable name) who are currently typing in this room.
users: Vec<String>,
},
CanUserPost (bool)
}

/// The global set of all timeline states, one entry per room.
Expand Down
69 changes: 51 additions & 18 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};
aaravlu marked this conversation as resolved.
Show resolved Hide resolved
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,10 @@ pub enum MatrixRequest {
FullyReadReceipt{
room_id: OwnedRoomId,
event_id: OwnedEventId,
},
/// Sends user permission's checking once user entered room.
aaravlu marked this conversation as resolved.
Show resolved Hide resolved
CheckUserPostPermission{
room_id: OwnedRoomId,
}
}

Expand All @@ -374,7 +378,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 +778,32 @@ async fn async_worker(
Err(_e) => error!("Failed to send fully read receipt to room {room_id}, event {event_id}; error: {_e:?}"),
}
});
}
},

MatrixRequest::CheckUserPostPermission { 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(client) = CLIENT.get() else { continue };
let Some(user_id) = client.user_id() else { continue };
aaravlu marked this conversation as resolved.
Show resolved Hide resolved

let _check_user_send_permission_task = Handle::current().spawn(async move {
let room = timeline.room();

let can_user_post = room.can_user_send_message(user_id, matrix_sdk::ruma::events::MessageLikeEventType::Message).await.unwrap_or(true);
aaravlu marked this conversation as resolved.
Show resolved Hide resolved

if let Err(_) = sender.send(TimelineUpdate::CanUserPost(can_user_post)) {
error!("Failed to send the result of user send permission")
}
});
}
}
}

Expand All @@ -798,7 +827,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 @@ -942,7 +971,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 @@ -1699,7 +1728,7 @@ async fn timeline_subscriber_handler(
} else {
found_target_event_id = find_target_event(&mut target_event_id, std::iter::once(&value));
}

clear_cache = true;
timeline_items.push_front(value);
reobtain_latest_event |= latest_event.is_none();
Expand Down Expand Up @@ -1772,7 +1801,7 @@ async fn timeline_subscriber_handler(
if index <= *i {
*i = i.saturating_sub(1);
}
}
}
timeline_items.remove(index);
if LOG_TIMELINE_DIFFS { log!("timeline_subscriber: room {room_id} diff Remove at {index}. Changes: {index_of_first_change}..{index_of_last_change}"); }
reobtain_latest_event = true;
Expand All @@ -1796,16 +1825,16 @@ async fn timeline_subscriber_handler(
}
}
}

if num_updates > 0 {
let new_latest_event = if reobtain_latest_event {
timeline.latest_event().await
} else {
None
};

let changed_indices = index_of_first_change..index_of_last_change;

if LOG_TIMELINE_DIFFS {
log!("timeline_subscriber: applied {num_updates} updates for room {room_id}, timeline now has {} items. is_append? {is_append}, clear_cache? {clear_cache}. Changes: {changed_indices:?}.", timeline_items.len());
}
Expand All @@ -1832,7 +1861,7 @@ async fn timeline_subscriber_handler(

// Send a Makepad-level signal to update this room's timeline UI view.
SignalToUI::set_ui_signal();

// Update the latest event for this room.
if let Some(new_latest) = new_latest_event {
if latest_event.as_ref().map_or(true, |ev| ev.timestamp() < new_latest.timestamp()) {
Expand Down Expand Up @@ -1886,6 +1915,10 @@ fn update_latest_event(
AnyOtherFullStateEventContent::RoomAvatar(_avatar_event) => {
room_avatar_changed = true;
}
AnyOtherFullStateEventContent::RoomPowerLevels(_power_level_event) => {
let id = room_id.clone();
submit_async_request(MatrixRequest::CheckUserPostPermission { room_id: id })
}
_ => { }
}
}
Expand Down Expand Up @@ -1952,10 +1985,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