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 7d2cd34
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 6 deletions.
82 changes: 82 additions & 0 deletions src/windows/room/chat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,80 @@ impl ChatState {
&self.room_id
}

pub fn auto_toggle_focus(
&mut self,
act: &EditorAction,
ctx: &ProgramContext,
store: &mut ProgramStore,

Check warning on line 656 in src/windows/room/chat.rs

View workflow job for this annotation

GitHub Actions / clippy

[clippy] src/windows/room/chat.rs#L656

warning: unused variable: `store` --> src/windows/room/chat.rs:656:9 | 656 | store: &mut ProgramStore, | ^^^^^ help: if this is intentional, prefix it with an underscore: `_store` | = note: `#[warn(unused_variables)]` on by default
Raw output
src/windows/room/chat.rs:656:9:w:warning: unused variable: `store`
   --> src/windows/room/chat.rs:656:9
    |
656 |         store: &mut ProgramStore,
    |         ^^^^^ help: if this is intentional, prefix it with an underscore: `_store`
    |
    = note: `#[warn(unused_variables)]` on by default


__END__
) -> 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 +825,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
23 changes: 17 additions & 6 deletions src/windows/room/scrollback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,26 +79,33 @@ 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() {

Check warning on line 95 in src/windows/room/scrollback.rs

View workflow job for this annotation

GitHub Actions / clippy

[clippy] src/windows/room/scrollback.rs#L95

warning: this loop could be written as a `for` loop --> src/windows/room/scrollback.rs:95:5 | 95 | while let Some((i, (key, _))) = iter.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for (i, (key, _)) in iter.by_ref()` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#while_let_on_iterator = note: `#[warn(clippy::while_let_on_iterator)]` on by default
Raw output
src/windows/room/scrollback.rs:95:5:w:warning: this loop could be written as a `for` loop
  --> src/windows/room/scrollback.rs:95:5
   |
95 |     while let Some((i, (key, _))) = iter.next() {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for (i, (key, _)) in iter.by_ref()`
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#while_let_on_iterator
   = note: `#[warn(clippy::while_let_on_iterator)]` on by default


__END__
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 +157,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 7d2cd34

Please sign in to comment.