Skip to content

Commit

Permalink
Support automatically toggling room focus
Browse files Browse the repository at this point in the history
  • Loading branch information
ulyssa committed Aug 23, 2024
1 parent 3355eb2 commit 14c8d0c
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 6 deletions.
76 changes: 76 additions & 0 deletions src/windows/room/chat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,74 @@ impl ChatState {
&self.room_id
}

pub fn auto_toggle_focus(
&mut self,
act: &EditorAction,
ctx: &ProgramContext,
store: &mut ProgramStore,
) ->Option<EditorAction> {
let is_insert = ctx.get_insert_style().is_some();

match (self.focus, act) {
(RoomFocus::Scrollback, _) if is_insert => {
// Insert mode commands should switch focus.
self.focus = RoomFocus::MessageBar;
None
},
(RoomFocus::Scrollback, EditorAction::InsertText(_)) => {
// Pasting or otherwise inserting text should switch.
self.focus = RoomFocus::MessageBar;
None
},
(
RoomFocus::Scrollback,
EditorAction::Edit(op, EditTarget::Motion(mov @ MoveType::Line(MoveDir1D::Next), count)),
) if ctx.resolve(op).is_motion() => {
let count = ctx.resolve(count);

if count > 0 && self.scrollback.is_latest() {
// Trying to move down a line when already at the end of room history should
// switch.
self.focus = RoomFocus::MessageBar;

// And decrement the count for the action.
let count = count.saturating_sub(1).into();
let target = EditTarget::Motion(mov.clone(), count);
let dec = EditorAction::Edit(op.clone(), target);

Some(dec)
} else {
None
}
},
(
RoomFocus::MessageBar,
EditorAction::Edit(op, EditTarget::Motion(mov @ MoveType::Line(MoveDir1D::Previous), count)),
) if !is_insert && ctx.resolve(op).is_motion() => {
let count = ctx.resolve(count);

if count > 0 && self.tbox.get_cursor().y == 0 {
// Trying to move up a line when already at the top of the msgbar should
// switch as long as we're not in Insert mode.
self.focus = RoomFocus::Scrollback;

// And decrement the count for the action.
let count = count.saturating_sub(1).into();
let target = EditTarget::Motion(mov.clone(), count);
let dec = EditorAction::Edit(op.clone(), target);

Some(dec)
} else {
None
}
},
(RoomFocus::Scrollback, _) | (RoomFocus::MessageBar, _) => {
// Do not switch.
None
},
}
}

pub fn typing_notice(
&self,
act: &EditorAction,
Expand Down Expand Up @@ -751,8 +819,16 @@ impl Editable<ProgramContext, ProgramStore, IambInfo> for ChatState {
ctx: &ProgramContext,
store: &mut ProgramStore,
) -> EditResult<EditInfo, IambInfo> {
// Check whether we should automatically switch between
// the message bar or message scrollback, and use an
// adjusted action if we do so.
let adjusted = self.auto_toggle_focus(act, ctx, store);
let act = adjusted.as_ref().unwrap_or(act);

// Send typing notice if needed.
self.typing_notice(act, ctx, store);

// And now we can finally run the editor command.
match delegate!(self, w => w.editor_command(act, ctx, store)) {
res @ Ok(_) => res,
Err(EditError::WrongBuffer(IambBufferId::Room(room_id, thread, focus)))
Expand Down
25 changes: 19 additions & 6 deletions src/windows/room/scrollback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,26 +79,35 @@ fn nth_key_before(pos: MessageKey, n: usize, thread: &Messages) -> MessageKey {
}

fn nth_before(pos: MessageKey, n: usize, thread: &Messages) -> MessageCursor {
nth_key_before(pos, n, thread).into()
let key = nth_key_before(pos, n, thread);

if matches!(thread.last_key_value(), Some((last, _)) if &key == last) {
MessageCursor::latest()
} else {
MessageCursor::from(key)
}
}

fn nth_key_after(pos: MessageKey, n: usize, thread: &Messages) -> MessageKey {
fn nth_key_after(pos: MessageKey, n: usize, thread: &Messages) -> Option<MessageKey> {
let mut end = &pos;
let iter = thread.range(&pos..).enumerate();
let mut iter = thread.range(&pos..).enumerate();

for (i, (key, _)) in iter {
while let Some((i, (key, _))) = iter.next(){
end = key;

if i >= n {
break;
}
}

end.clone()
// Avoid returning the key if it's at the end.
iter.next().map(|_| end.clone())
}

fn nth_after(pos: MessageKey, n: usize, thread: &Messages) -> MessageCursor {
nth_key_after(pos, n, thread).into()
nth_key_after(pos, n, thread)
.map(MessageCursor::from)
.unwrap_or_default()
}

fn prevmsg<'a>(key: &MessageKey, thread: &'a Messages) -> Option<&'a Message> {
Expand Down Expand Up @@ -150,6 +159,10 @@ impl ScrollbackState {
}
}

pub fn is_latest(&self) -> bool {
self.cursor.timestamp.is_none()
}

pub fn goto_latest(&mut self) {
self.cursor = MessageCursor::latest();
}
Expand Down

0 comments on commit 14c8d0c

Please sign in to comment.