Skip to content

feat: Press ArrowUp to edit last message in chats / threads #8542

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

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/ui/src/components/Component.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@
on:validate
on:submit
on:select
on:keydown
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these are too specific, please try to avoid using them, especially editingEnded

on:editingEnded
>
<slot />
</svelte:component>
Expand All @@ -140,6 +142,8 @@
on:validate
on:submit
on:select
on:keydown
on:editingEnded
/>
{/if}
</ErrorBoundary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,6 @@
on:close
on:open
on:submit
on:keydown
/>
{/if}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
export let readonly = false
export let onClick: (() => void) | undefined = undefined
export let onReply: ((message: ActivityMessage) => void) | undefined = undefined
export let isEditing = false

const client = getClient()
const hierarchy = client.getHierarchy()
Expand Down Expand Up @@ -76,7 +77,9 @@
compact,
readonly,
onClick,
onReply
onReply,
isEditing
}}
on:editingEnded
/>
{/if}
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,7 @@
on:message={onMessage}
on:update={onUpdate}
onPaste={pasteAction}
on:keydown
{placeholder}
>
<div slot="header">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
kind="input"
{extensions}
props={{ object, boundary, collection, autofocus, withTypingInfo: true }}
on:keydown
/>
</div>
{:else}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
// limitations under the License.
-->
<script lang="ts">
import { getCurrentEmployee } from '@hcengineering/contact'
import { personByPersonIdStore } from '@hcengineering/contact-resources'
import activity, { ActivityMessage } from '@hcengineering/activity'
import { ActivityMessagePresenter, canGroupMessages, messageInFocus } from '@hcengineering/activity-resources'
import core, { Doc, generateId, getCurrentAccount, Ref, Space, Timestamp, Tx, TxCUD } from '@hcengineering/core'
Expand Down Expand Up @@ -58,6 +60,8 @@
const contextByDocStore = inboxClient.contextByDoc
const notificationsByContextStore = inboxClient.inboxNotificationsByContext

const me = getCurrentEmployee()

// Stores
const metadataStore = provider.metadataStore
const messagesStore = provider.messagesStore
Expand All @@ -74,6 +78,8 @@
let messages: ActivityMessage[] = []
let messagesCount = 0

let editingMessageId: Ref<ActivityMessage> | undefined = undefined

// Elements
let scroller: Scroller | undefined | null = undefined
let scrollDiv: HTMLDivElement | undefined | null = undefined
Expand Down Expand Up @@ -128,6 +134,15 @@
$: adjustScrollPosition(selectedMessageId)
$: void handleMessagesUpdated(messages.length)

function getLastOwnMessage (): ActivityMessage | undefined {
return [...messages].reverse().find((message) => {
const personId = message.createdBy
if (personId === undefined) return false
const person = $personByPersonIdStore.get(personId)
return person?._id === me
})
}

function adjustScrollPosition (selectedMessageId?: Ref<ActivityMessage>): void {
if ($isLoadingStore || !isScrollInitialized) {
return
Expand Down Expand Up @@ -537,6 +552,21 @@
loadMore()
}

function onKeydown (key: KeyboardEvent): void {
if (key.code !== 'ArrowUp') return

const target = key.target as HTMLElement
const isEmpty = target.textContent?.trim() === ''
if (isEmpty) {
const ownLastMessage = getLastOwnMessage()
if (ownLastMessage !== undefined) {
key.preventDefault()
key.stopPropagation()
editingMessageId = ownLastMessage._id
}
}
}

const newMessageTxListener = (txes: Tx[]): void => {
const ctx = txes
.map((it) => it as TxCUD<ActivityMessage>)
Expand Down Expand Up @@ -603,6 +633,7 @@

{#each messages as message, index (message._id)}
{@const isSelected = message._id === selectedMessageId}
{@const isEditing = message._id === editingMessageId}
{@const canGroup = canGroupChatMessages(message, messages[index - 1])}
{#if separatorIndex === index}
<ActivityMessagesSeparator bind:element={separatorDiv} label={activity.string.New} />
Expand All @@ -626,6 +657,12 @@
type={canGroup ? 'short' : 'default'}
isHighlighted={isSelected}
shouldScroll={false}
isEditing={isEditing}
on:editingEnded={() => {
if (editingMessageId === message._id) {
editingMessageId = undefined
}
}}
{readonly}
{onReply}
/>
Expand All @@ -639,7 +676,7 @@
<HistoryLoading isLoading={$isLoadingMoreStore} />
{/if}
{#if !fixedInput && withInput && !readonly}
<ChannelInput {object} {readonly} boundary={scrollDiv} {collection} {isThread} {autofocus} />
<ChannelInput {object} {readonly} boundary={scrollDiv} {collection} {isThread} {autofocus} on:keydown={(event) => { onKeydown(event) }}/>
{/if}
</BaseChatScroller>
{#if !isThread && isLatestMessageButtonVisible}
Expand All @@ -656,7 +693,7 @@
</div>

{#if fixedInput && withInput && !readonly}
<ChannelInput {object} {readonly} boundary={scrollDiv} {collection} {isThread} {autofocus} />
<ChannelInput {object} {readonly} boundary={scrollDiv} {collection} {isThread} {autofocus} on:keydown={(event) => { onKeydown(event) }} />
{/if}

{#if readonly}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@
on:update={onUpdate}
on:focus
on:blur
on:keydown
bind:loading
/>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import { Action, Button, IconEdit, ShowMore } from '@hcengineering/ui'
import view from '@hcengineering/view'
import { getDocLinkTitle } from '@hcengineering/view-resources'
import { createEventDispatcher } from 'svelte'

import { shownTranslatedMessagesStore, translatedMessagesStore, translatingMessagesStore } from '../../stores'
import ChatMessageHeader from './ChatMessageHeader.svelte'
Expand Down Expand Up @@ -59,11 +60,13 @@
export let type: ActivityMessageViewType = 'default'
export let onClick: (() => void) | undefined = undefined
export let onReply: ((message: ActivityMessage) => void) | undefined = undefined
export let isEditing = false

const client = getClient()
const hierarchy = client.getHierarchy()
const STALE_TIMEOUT_MS = 5000
const me = getCurrentEmployee()
const dispatch = createEventDispatcher()

let parentMessage: DisplayActivityMessage | undefined = undefined
let object: Doc | undefined
Expand Down Expand Up @@ -146,7 +149,6 @@
isEditing = true
}

let isEditing = false
let additionalActions: Action[] = []

$: isOwn = person !== undefined && person._id === me
Expand Down Expand Up @@ -291,13 +293,15 @@
{object}
on:submit={() => {
isEditing = false
dispatch('editingEnded')
}}
/>
<div class="flex-row-center gap-2 justify-end mt-2">
<Button
label={view.string.Cancel}
on:click={() => {
isEditing = false
dispatch('editingEnded')
}}
/>
<Button label={activity.string.Update} accent on:click={() => refInput.submit()} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
export let videoPreload = false
export let readonly = false
export let onClick: (() => void) | undefined = undefined
export let isEditing = false

const client = getClient()
</script>
Expand Down Expand Up @@ -76,5 +77,6 @@
{videoPreload}
{onClick}
{readonly}
{isEditing}
/>
{/if}
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@
updateFocus()
dispatch('focus')
}}
on:keydown
extensions={[
completionPlugin,
EmojiExtension.configure(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,4 +235,4 @@
<TextEditorToolbar bind:toolbar={imageToolbarElement} kind="image" {editor} on:focus={handleFocus} />
{/if}

<div class="select-text" style="width: 100%;" bind:this={element} />
<div class="select-text" style="width: 100%;" bind:this={element} on:keydown />
2 changes: 1 addition & 1 deletion plugins/view/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ export interface Action<T extends Doc = Doc, P = Record<string, any>> extends Do
// If defined, types should be matched to proposed list
inputProps?: Record<string, Ref<Class<Doc>>>

// Kayboard bindings
// Keyboard bindings
keyBinding?: KeyBinding[]

// short description for action.
Expand Down