Skip to content

Commit

Permalink
fix(autofocus): don't focus on input bar when editing or reacting (#726)
Browse files Browse the repository at this point in the history
Co-authored-by: Sara Tavares <29093946+stavares843@users.noreply.github.com>
  • Loading branch information
sdwoodbury and stavares843 authored Apr 26, 2023
1 parent b4ccbb7 commit 520c2ce
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 24 deletions.
2 changes: 2 additions & 0 deletions common/src/state/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ pub struct UI {
pub show_settings_welcome: bool,
// Cached username used in login page
pub cached_username: Option<String>,
#[serde(skip)]
pub ignore_focus: bool,
}

#[derive(Default, Deserialize, Serialize)]
Expand Down
2 changes: 1 addition & 1 deletion kit/src/components/message/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ fn EditMsg<'a>(cx: Scope<'a, EditProps<'a>>) -> Element<'a> {
log::trace!("rendering EditMsg");
cx.render(rsx!(textarea::Input {
id: cx.props.id.clone(),
focus: true,
ignore_focus: false,
value: cx.props.text.clone(),
onchange: move |_| {},
onreturn: move |(s, is_valid, _): (String, bool, _)| {
Expand Down
15 changes: 9 additions & 6 deletions kit/src/elements/textarea/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub struct Props<'a> {
#[props(default = "".to_owned())]
id: String,
#[props(default = false)]
focus: bool,
ignore_focus: bool,
#[props(default = false)]
loading: bool,
#[props(default = "".to_owned())]
Expand All @@ -54,7 +54,7 @@ pub fn Input<'a>(cx: Scope<'a, Props<'a>>) -> Element<'a> {

let Props {
id: _,
focus,
ignore_focus: _,
loading,
placeholder,
max_length,
Expand All @@ -73,7 +73,12 @@ pub fn Input<'a>(cx: Scope<'a, Props<'a>>) -> Element<'a> {
};

let height_script = include_str!("./update_input_height.js");
let focus_script = include_str!("./focus.js").replace("$UUID", &id);
let focus_script = if cx.props.ignore_focus {
String::new()
} else {
include_str!("./focus.js").replace("$UUID", &id)
};

eval(height_script.to_string());
eval(focus_script.clone());

Expand All @@ -99,11 +104,9 @@ pub fn Input<'a>(cx: Scope<'a, Props<'a>>) -> Element<'a> {
class: format_args!("input {}", if disabled { "disabled" } else { " " }),
height: "{size.get_height()}",
textarea {
key: "{element_id}",
key: "textarea-key-{id}",
class: "input_textarea",
id: "{id}",
// todo: troubleshoot this. it isn't working
autofocus: *focus,
aria_label: "{aria_label}",
disabled: "{disabled}",
value: "{current_val}",
Expand Down
3 changes: 2 additions & 1 deletion kit/src/layout/chatbar/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pub struct Props<'a> {
onreturn: EventHandler<'a, String>,
#[props(default = false)]
is_disabled: bool,
ignore_focus: bool,
}

#[derive(Props)]
Expand Down Expand Up @@ -128,7 +129,7 @@ pub fn Chatbar<'a>(cx: Scope<'a, Props<'a>>) -> Element<'a> {
id: controlled_input_id.clone(),
loading: cx.props.loading.unwrap_or_default(),
placeholder: cx.props.placeholder.clone(),
focus: cx.props.with_replying_to.is_some(),
ignore_focus: cx.props.ignore_focus,
value: if cx.props.is_disabled { get_local_text("messages.not-friends")} else { cx.props.value.clone().unwrap_or_default()},
onchange: move |(v, _)| cx.props.onchange.call(v),
onreturn: move |(v, is_valid, _)| {
Expand Down
2 changes: 1 addition & 1 deletion launch_docker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@
#
# CMD ["bash"]

docker run -ti --rm --net=host -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix -v `pwd`/target:/root/bin -v $2:/root/.uplink $1 /bin/bash
docker run -ti --rm --net=host --ipc=host -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix -v `pwd`/target:/root/bin -v $2:/root/.uplink $1 /bin/bash
13 changes: 8 additions & 5 deletions ui/src/components/chat/compose/chatbar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ pub fn get_chatbar<'a>(cx: &'a Scoped<'a, super::ComposeProps>) -> Element<'a> {
let active_chat_id = data.as_ref().map(|d| d.active_chat.id);
let can_send = use_state(cx, || state.read().active_chat_has_draft());

let files_to_upload: &UseState<Vec<PathBuf>> = cx.props.upload_files.as_ref().unwrap();
let files_to_upload = cx.props.upload_files.clone();
// used to render the typing indicator
// for now it doesn't quite work for group messages
let my_id = state.read().did_key();
Expand Down Expand Up @@ -211,7 +211,7 @@ pub fn get_chatbar<'a>(cx: &'a Scoped<'a, super::ComposeProps>) -> Element<'a> {

let msg_valid = |msg: &[String]| {
(!msg.is_empty() && msg.iter().any(|line| !line.trim().is_empty()))
|| !files_to_upload.current().is_empty()
|| !cx.props.upload_files.current().is_empty()
};

let submit_fn = move || {
Expand Down Expand Up @@ -273,6 +273,7 @@ pub fn get_chatbar<'a>(cx: &'a Scoped<'a, super::ComposeProps>) -> Element<'a> {
loading: is_loading,
placeholder: get_local_text("messages.say-something-placeholder"),
is_disabled: disabled,
ignore_focus: cx.props.ignore_focus,
onchange: move |v: String| {
if let Some(id) = &active_chat_id {
can_send.set(!v.is_empty() || !files_to_upload.get().is_empty());
Expand Down Expand Up @@ -357,14 +358,16 @@ pub fn get_chatbar<'a>(cx: &'a Scoped<'a, super::ComposeProps>) -> Element<'a> {
.set_directory(dirs::home_dir().unwrap_or_default())
.pick_files()
{
let mut new_files_to_upload: Vec<_> = files_to_upload
let mut new_files_to_upload: Vec<_> = cx
.props
.upload_files
.current()
.iter()
.filter(|file_name| !new_files.contains(file_name))
.cloned()
.collect();
new_files_to_upload.extend(new_files);
files_to_upload.set(new_files_to_upload);
cx.props.upload_files.set(new_files_to_upload);
can_send.set(true);
}
},
Expand Down Expand Up @@ -398,7 +401,7 @@ pub fn get_chatbar<'a>(cx: &'a Scoped<'a, super::ComposeProps>) -> Element<'a> {
})
})
chatbar,
Attachments {files: files_to_upload.clone(), on_remove: move |b| {
Attachments {files: cx.props.upload_files.clone(), on_remove: move |b| {
can_send.set(b | state
.read()
.active_chat_has_draft());
Expand Down
7 changes: 7 additions & 0 deletions ui/src/components/chat/compose/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,7 @@ fn render_messages<'a>(cx: Scope<'a, MessagesProps<'a>>) -> Element<'a> {
let _message_key = format!("{}-{:?}", &message.key, is_editing);
let _msg_uuid = message.inner.id();

// todo: add onblur event
rsx!(ContextMenu {
key: "{context_key}",
id: context_key,
Expand Down Expand Up @@ -503,6 +504,7 @@ fn render_messages<'a>(cx: Scope<'a, MessagesProps<'a>>) -> Element<'a> {
icon: Icon::FaceSmile,
text: get_local_text("messages.react"),
onpress: move |_| {
state.write().ui.ignore_focus = true;
reacting_to.set(Some(_msg_uuid));
}
},
Expand All @@ -513,6 +515,7 @@ fn render_messages<'a>(cx: Scope<'a, MessagesProps<'a>>) -> Element<'a> {
&& edit_msg.get().map(|id| id != _msg_uuid).unwrap_or(true),
onpress: move |_| {
edit_msg.set(Some(_msg_uuid));
state.write().ui.ignore_focus = true;
}
},
ContextItem {
Expand All @@ -522,6 +525,7 @@ fn render_messages<'a>(cx: Scope<'a, MessagesProps<'a>>) -> Element<'a> {
&& edit_msg.get().map(|id| id == _msg_uuid).unwrap_or(false),
onpress: move |_| {
edit_msg.set(None);
state.write().ui.ignore_focus = false;
}
},
ContextItem {
Expand Down Expand Up @@ -618,13 +622,15 @@ fn render_message<'a>(cx: Scope<'a, MessageProps<'a>>) -> Element<'a> {
}
},
onblur: move |_| {
state.write().ui.ignore_focus = false;
reacting_to.set(None);
},
reactions.iter().cloned().map(|reaction| {
rsx!(
div {
onclick: move |_| {
reacting_to.set(None);
state.write().ui.ignore_focus = false;
ch.send(MessagesCommand::React((state.read().did_key(), message.inner.clone(), reaction.to_string())));
},
"{reaction}"
Expand Down Expand Up @@ -683,6 +689,7 @@ fn render_message<'a>(cx: Scope<'a, MessageProps<'a>>) -> Element<'a> {
},
on_edit: move |update: String| {
edit_msg.set(None);
state.write().ui.ignore_focus = false;
let msg = update.split('\n').map(|x| x.to_string()).collect::<Vec<String>>();
if message.inner.value() == msg || !msg.iter().any(|x| !x.trim().is_empty()) {
return;
Expand Down
29 changes: 19 additions & 10 deletions ui/src/components/chat/compose/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ impl PartialEq for ComposeData {
pub struct ComposeProps {
#[props(!optional)]
data: Option<Rc<ComposeData>>,
upload_files: Option<UseState<Vec<PathBuf>>>,
show_edit_group: Option<UseState<Option<Uuid>>>,
upload_files: UseState<Vec<PathBuf>>,
show_edit_group: UseState<Option<Uuid>>,
ignore_focus: bool,
}

#[allow(non_snake_case)]
Expand Down Expand Up @@ -114,6 +115,7 @@ pub fn Compose(cx: Scope) -> Element {
}
});
let show_edit_group = use_state(cx, || None);
let should_ignore_focus = state.read().ui.ignore_focus;

cx.render(rsx!(
div {
Expand Down Expand Up @@ -150,12 +152,16 @@ pub fn Compose(cx: Scope) -> Element {
state.write().mutate(Action::SidebarHidden(!current));
},
controls: cx.render(rsx!(get_controls{
data: data2,
data: data2.clone(),
show_edit_group: show_edit_group.clone(),
upload_files: files_to_upload.clone(),
ignore_focus: should_ignore_focus,
})),
get_topbar_children {
data: data.clone(),
show_edit_group: show_edit_group.clone(),
upload_files: files_to_upload.clone(),
ignore_focus: should_ignore_focus,
}
},
data.as_ref().and_then(|data| data.active_media.then(|| rsx!(
Expand Down Expand Up @@ -186,11 +192,13 @@ pub fn Compose(cx: Scope) -> Element {
MessageGroupSkeletal { alt: true }
}
),
Some(data) => rsx!(messages::get_messages{data: data.clone()}),
Some(_data) => rsx!(messages::get_messages{data: _data.clone()}),
},
chatbar::get_chatbar {
data: data,
upload_files: files_to_upload.clone()
data: data.clone(),
show_edit_group: show_edit_group.clone(),
upload_files: files_to_upload.clone(),
ignore_focus: should_ignore_focus,
}
)),
}
Expand Down Expand Up @@ -253,7 +261,6 @@ fn get_compose_data(cx: Scope) -> Option<Rc<ComposeData>> {

fn get_controls(cx: Scope<ComposeProps>) -> Element {
let state = use_shared_state::<State>(cx)?;
let show_edit_group = cx.props.show_edit_group.as_ref().unwrap();
let desktop = use_window(cx);
let data = &cx.props.data;
let active_chat = data.as_ref().map(|x| &x.active_chat);
Expand All @@ -266,7 +273,9 @@ fn get_controls(cx: Scope<ComposeProps>) -> Element {
} else {
(ConversationType::Direct, None)
};
let edit_group_activated = show_edit_group
let edit_group_activated = cx
.props
.show_edit_group
.get()
.map(|group_chat_id| active_chat.map_or(false, |chat| group_chat_id == chat.id))
.unwrap_or(false);
Expand Down Expand Up @@ -299,9 +308,9 @@ fn get_controls(cx: Scope<ComposeProps>) -> Element {
onpress: move |_| {
if is_creator {
if edit_group_activated {
show_edit_group.set(None);
cx.props.show_edit_group.set(None);
} else if let Some(chat) = active_chat.as_ref() {
show_edit_group.set(Some(chat.id));
cx.props.show_edit_group.set(Some(chat.id));
}
}

Expand Down

0 comments on commit 520c2ce

Please sign in to comment.