Edit last message with up arrow key (#774)
This commit is contained in:
parent
80aa55b706
commit
b3bff6b43f
3 changed files with 75 additions and 10 deletions
|
@ -714,9 +714,9 @@ function getEditedBody(editedMEvent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function Message({
|
function Message({
|
||||||
mEvent, isBodyOnly, roomTimeline, focus, fullTime,
|
mEvent, isBodyOnly, roomTimeline,
|
||||||
|
focus, fullTime, isEdit, setEdit, cancelEdit,
|
||||||
}) {
|
}) {
|
||||||
const [isEditing, setIsEditing] = useState(false);
|
|
||||||
const roomId = mEvent.getRoomId();
|
const roomId = mEvent.getRoomId();
|
||||||
const { editedTimeline, reactionTimeline } = roomTimeline ?? {};
|
const { editedTimeline, reactionTimeline } = roomTimeline ?? {};
|
||||||
|
|
||||||
|
@ -731,7 +731,7 @@ function Message({
|
||||||
const avatarSrc = mEvent.sender?.getAvatarUrl(initMatrix.matrixClient.baseUrl, 36, 36, 'crop') ?? null;
|
const avatarSrc = mEvent.sender?.getAvatarUrl(initMatrix.matrixClient.baseUrl, 36, 36, 'crop') ?? null;
|
||||||
|
|
||||||
const edit = useCallback(() => {
|
const edit = useCallback(() => {
|
||||||
setIsEditing(true);
|
setEdit(eventId);
|
||||||
}, []);
|
}, []);
|
||||||
const reply = useCallback(() => {
|
const reply = useCallback(() => {
|
||||||
replyTo(senderId, mEvent.getId(), body);
|
replyTo(senderId, mEvent.getId(), body);
|
||||||
|
@ -788,7 +788,7 @@ function Message({
|
||||||
eventId={mEvent.replyEventId}
|
eventId={mEvent.replyEventId}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{!isEditing && (
|
{!isEdit && (
|
||||||
<MessageBody
|
<MessageBody
|
||||||
senderName={username}
|
senderName={username}
|
||||||
isCustomHTML={isCustomHTML}
|
isCustomHTML={isCustomHTML}
|
||||||
|
@ -797,22 +797,22 @@ function Message({
|
||||||
isEdited={isEdited}
|
isEdited={isEdited}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{isEditing && (
|
{isEdit && (
|
||||||
<MessageEdit
|
<MessageEdit
|
||||||
body={body}
|
body={body}
|
||||||
onSave={(newBody) => {
|
onSave={(newBody) => {
|
||||||
if (newBody !== body) {
|
if (newBody !== body) {
|
||||||
initMatrix.roomsInput.sendEditedMessage(roomId, mEvent, newBody);
|
initMatrix.roomsInput.sendEditedMessage(roomId, mEvent, newBody);
|
||||||
}
|
}
|
||||||
setIsEditing(false);
|
cancelEdit();
|
||||||
}}
|
}}
|
||||||
onCancel={() => setIsEditing(false)}
|
onCancel={cancelEdit}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{haveReactions && (
|
{haveReactions && (
|
||||||
<MessageReactionGroup roomTimeline={roomTimeline} mEvent={mEvent} />
|
<MessageReactionGroup roomTimeline={roomTimeline} mEvent={mEvent} />
|
||||||
)}
|
)}
|
||||||
{roomTimeline && !isEditing && (
|
{roomTimeline && !isEdit && (
|
||||||
<MessageOptions
|
<MessageOptions
|
||||||
roomTimeline={roomTimeline}
|
roomTimeline={roomTimeline}
|
||||||
mEvent={mEvent}
|
mEvent={mEvent}
|
||||||
|
@ -829,6 +829,9 @@ Message.defaultProps = {
|
||||||
focus: false,
|
focus: false,
|
||||||
roomTimeline: null,
|
roomTimeline: null,
|
||||||
fullTime: false,
|
fullTime: false,
|
||||||
|
isEdit: false,
|
||||||
|
setEdit: null,
|
||||||
|
cancelEdit: null,
|
||||||
};
|
};
|
||||||
Message.propTypes = {
|
Message.propTypes = {
|
||||||
mEvent: PropTypes.shape({}).isRequired,
|
mEvent: PropTypes.shape({}).isRequired,
|
||||||
|
@ -836,6 +839,9 @@ Message.propTypes = {
|
||||||
roomTimeline: PropTypes.shape({}),
|
roomTimeline: PropTypes.shape({}),
|
||||||
focus: PropTypes.bool,
|
focus: PropTypes.bool,
|
||||||
fullTime: PropTypes.bool,
|
fullTime: PropTypes.bool,
|
||||||
|
isEdit: PropTypes.bool,
|
||||||
|
setEdit: PropTypes.func,
|
||||||
|
cancelEdit: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
export { Message, MessageReply, PlaceholderMessage };
|
export { Message, MessageReply, PlaceholderMessage };
|
||||||
|
|
|
@ -229,6 +229,8 @@
|
||||||
padding: var(--sp-extra-tight) 0;
|
padding: var(--sp-extra-tight) 0;
|
||||||
&-btns button {
|
&-btns button {
|
||||||
margin: var(--sp-tight) 0 0 0;
|
margin: var(--sp-tight) 0 0 0;
|
||||||
|
padding: var(--sp-ultra-tight) var(--sp-tight);
|
||||||
|
min-width: 0;
|
||||||
@include dir.side(margin, 0, var(--sp-tight));
|
@include dir.side(margin, 0, var(--sp-tight));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,7 +118,15 @@ function handleOnClickCapture(e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderEvent(roomTimeline, mEvent, prevMEvent, isFocus = false) {
|
function renderEvent(
|
||||||
|
roomTimeline,
|
||||||
|
mEvent,
|
||||||
|
prevMEvent,
|
||||||
|
isFocus,
|
||||||
|
isEdit,
|
||||||
|
setEdit,
|
||||||
|
cancelEdit,
|
||||||
|
) {
|
||||||
const isBodyOnly = (prevMEvent !== null
|
const isBodyOnly = (prevMEvent !== null
|
||||||
&& prevMEvent.getSender() === mEvent.getSender()
|
&& prevMEvent.getSender() === mEvent.getSender()
|
||||||
&& prevMEvent.getType() !== 'm.room.member'
|
&& prevMEvent.getType() !== 'm.room.member'
|
||||||
|
@ -147,6 +155,9 @@ function renderEvent(roomTimeline, mEvent, prevMEvent, isFocus = false) {
|
||||||
roomTimeline={roomTimeline}
|
roomTimeline={roomTimeline}
|
||||||
focus={isFocus}
|
focus={isFocus}
|
||||||
fullTime={false}
|
fullTime={false}
|
||||||
|
isEdit={isEdit}
|
||||||
|
setEdit={setEdit}
|
||||||
|
cancelEdit={cancelEdit}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -386,6 +397,8 @@ function RoomViewContent({ eventId, roomTimeline }) {
|
||||||
const timelineSVRef = useRef(null);
|
const timelineSVRef = useRef(null);
|
||||||
const timelineScrollRef = useRef(null);
|
const timelineScrollRef = useRef(null);
|
||||||
const eventLimitRef = useRef(null);
|
const eventLimitRef = useRef(null);
|
||||||
|
const [editEventId, setEditEventId] = useState(null);
|
||||||
|
const cancelEdit = () => setEditEventId(null);
|
||||||
|
|
||||||
const readUptoEvtStore = useStore(roomTimeline);
|
const readUptoEvtStore = useStore(roomTimeline);
|
||||||
const [onLimitUpdate, forceUpdateLimit] = useForceUpdate();
|
const [onLimitUpdate, forceUpdateLimit] = useForceUpdate();
|
||||||
|
@ -470,6 +483,42 @@ function RoomViewContent({ eventId, roomTimeline }) {
|
||||||
}
|
}
|
||||||
}, [newEvent]);
|
}, [newEvent]);
|
||||||
|
|
||||||
|
const listenKeyboard = useCallback((event) => {
|
||||||
|
if (event.ctrlKey || event.altKey || event.metaKey) return;
|
||||||
|
if (event.key !== 'ArrowUp') return;
|
||||||
|
if (navigation.isRawModalVisible) return;
|
||||||
|
|
||||||
|
if (document.activeElement.id !== 'message-textarea') return;
|
||||||
|
if (document.activeElement.value !== '') return;
|
||||||
|
|
||||||
|
const {
|
||||||
|
timeline: tl, activeTimeline, liveTimeline, matrixClient: mx,
|
||||||
|
} = roomTimeline;
|
||||||
|
const limit = eventLimitRef.current;
|
||||||
|
if (activeTimeline !== liveTimeline) return;
|
||||||
|
if (tl.length > limit.length) return;
|
||||||
|
|
||||||
|
const mTypes = ['m.text'];
|
||||||
|
for (let i = tl.length - 1; i >= 0; i -= 1) {
|
||||||
|
const mE = tl[i];
|
||||||
|
if (
|
||||||
|
mE.getSender() === mx.getUserId()
|
||||||
|
&& mE.getType() === 'm.room.message'
|
||||||
|
&& mTypes.includes(mE.getContent()?.msgtype)
|
||||||
|
) {
|
||||||
|
setEditEventId(mE.getId());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [roomTimeline]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
document.body.addEventListener('keydown', listenKeyboard);
|
||||||
|
return () => {
|
||||||
|
document.body.removeEventListener('keydown', listenKeyboard);
|
||||||
|
};
|
||||||
|
}, [listenKeyboard]);
|
||||||
|
|
||||||
const handleTimelineScroll = (event) => {
|
const handleTimelineScroll = (event) => {
|
||||||
const timelineScroll = timelineScrollRef.current;
|
const timelineScroll = timelineScrollRef.current;
|
||||||
if (!event.target) return;
|
if (!event.target) return;
|
||||||
|
@ -535,7 +584,15 @@ function RoomViewContent({ eventId, roomTimeline }) {
|
||||||
const isFocus = focusId === mEvent.getId();
|
const isFocus = focusId === mEvent.getId();
|
||||||
if (isFocus) jumpToItemIndex = itemCountIndex;
|
if (isFocus) jumpToItemIndex = itemCountIndex;
|
||||||
|
|
||||||
tl.push(renderEvent(roomTimeline, mEvent, isNewEvent ? null : prevMEvent, isFocus));
|
tl.push(renderEvent(
|
||||||
|
roomTimeline,
|
||||||
|
mEvent,
|
||||||
|
isNewEvent ? null : prevMEvent,
|
||||||
|
isFocus,
|
||||||
|
editEventId === mEvent.getId(),
|
||||||
|
setEditEventId,
|
||||||
|
cancelEdit,
|
||||||
|
));
|
||||||
itemCountIndex += 1;
|
itemCountIndex += 1;
|
||||||
}
|
}
|
||||||
if (roomTimeline.canPaginateForward() || limit.length < timeline.length) {
|
if (roomTimeline.canPaginateForward() || limit.length < timeline.length) {
|
||||||
|
|
Loading…
Reference in a new issue