mirror of
https://github.com/hcengineering/platform.git
synced 2025-05-11 18:01:59 +00:00
UBERF-9759 Scroll attachments in chat (#8523)
* UBERF-9759 Scroll attachments in chat Signed-off-by: Alexander Onnikov <Alexander.Onnikov@xored.com> * fix: use Array.from(...) Signed-off-by: Alexander Onnikov <Alexander.Onnikov@xored.com> --------- Signed-off-by: Alexander Onnikov <Alexander.Onnikov@xored.com>
This commit is contained in:
parent
afbaf26078
commit
11232c503c
@ -166,6 +166,7 @@
|
||||
updateToolbarPosition(readonly, board, toolbar)
|
||||
}}
|
||||
use:drawing={{
|
||||
autoSize: imageWidth === undefined || imageHeight === undefined,
|
||||
readonly,
|
||||
imageWidth,
|
||||
imageHeight,
|
||||
|
@ -47,10 +47,9 @@
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
onMount(() => {
|
||||
if (fullSize) {
|
||||
dispatch('fullsize')
|
||||
}
|
||||
$: void loadDrawings(file)
|
||||
|
||||
async function loadDrawings (file: Ref<Blob> | undefined): Promise<void> {
|
||||
if (props.drawingAvailable === true) {
|
||||
if (props.loadDrawings !== undefined) {
|
||||
drawingLoading = true
|
||||
@ -66,6 +65,14 @@
|
||||
console.error('Failed to load drawings for file', file, error)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
if (fullSize) {
|
||||
dispatch('fullsize')
|
||||
}
|
||||
if (props.drawingAvailable === true) {
|
||||
if (props.createDrawing !== undefined) {
|
||||
createDrawing = props.createDrawing
|
||||
props.createDrawing = async (data: any): Promise<any> => {
|
||||
|
@ -57,7 +57,7 @@ export function updatePopup (id: string, props: Partial<CompAndProps>): void {
|
||||
(p: CompAndProps) => p.id === id
|
||||
)
|
||||
if (popupIndex !== -1) {
|
||||
;(modals[popupIndex] as CompAndProps).update?.(props)
|
||||
;(modals[popupIndex] as CompAndProps).update?.(props.props)
|
||||
}
|
||||
return modals
|
||||
})
|
||||
|
@ -15,7 +15,8 @@
|
||||
<script lang="ts">
|
||||
import { Attachment } from '@hcengineering/attachment'
|
||||
import { Ref, type WithLookup } from '@hcengineering/core'
|
||||
import { Scroller } from '@hcengineering/ui'
|
||||
import { ListSelectionProvider } from '@hcengineering/view-resources'
|
||||
import { Scroller, updatePopup } from '@hcengineering/ui'
|
||||
import { AttachmentImageSize } from '../types'
|
||||
import AttachmentPreview from './AttachmentPreview.svelte'
|
||||
|
||||
@ -23,6 +24,22 @@
|
||||
export let savedAttachmentsIds: Ref<Attachment>[] = []
|
||||
export let imageSize: AttachmentImageSize | undefined = undefined
|
||||
export let videoPreload = false
|
||||
|
||||
let attachmentPopupId = ''
|
||||
|
||||
const listProvider = new ListSelectionProvider((offset: 1 | -1 | 0) => {
|
||||
const current = listProvider.current()
|
||||
if (current === undefined) return
|
||||
let pos = current + offset
|
||||
if (pos < 0) pos = 0
|
||||
if (pos >= attachments.length) pos = attachments.length - 1
|
||||
const doc = listProvider.docs()[pos] as Attachment
|
||||
if (doc !== undefined && attachmentPopupId !== '') {
|
||||
listProvider.updateFocus(doc)
|
||||
updatePopup(attachmentPopupId, { props: { value: doc } })
|
||||
}
|
||||
})
|
||||
$: listProvider.update(attachments.filter((p) => p.type.startsWith('image/')))
|
||||
</script>
|
||||
|
||||
{#if attachments.length}
|
||||
@ -33,6 +50,8 @@
|
||||
isSaved={savedAttachmentsIds?.includes(attachment._id) ?? false}
|
||||
{imageSize}
|
||||
{videoPreload}
|
||||
{listProvider}
|
||||
on:open={(res) => (attachmentPopupId = res.detail)}
|
||||
/>
|
||||
{/each}
|
||||
</Scroller>
|
||||
|
@ -99,7 +99,8 @@
|
||||
return
|
||||
}
|
||||
if (value.type.startsWith('image/') || value.type.startsWith('video/') || value.type.startsWith('audio/')) {
|
||||
showAttachmentPreviewPopup(value)
|
||||
const popup = showAttachmentPreviewPopup(value)
|
||||
dispatch('open', popup.id)
|
||||
} else {
|
||||
await openAttachmentInSidebar(value)
|
||||
}
|
||||
|
@ -0,0 +1,78 @@
|
||||
<!--
|
||||
// Copyright © 2024 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import attachment, { type Attachment, type Drawing } from '@hcengineering/attachment'
|
||||
import core, { SortingOrder } from '@hcengineering/core'
|
||||
import { DrawingData, FilePreviewPopup, getClient } from '@hcengineering/presentation'
|
||||
import { isAttachment } from '../utils'
|
||||
|
||||
export let value: Attachment
|
||||
|
||||
export let fullSize = false
|
||||
export let showIcon = true
|
||||
|
||||
$: drawingAvailable = value?.type?.startsWith('image/') && isAttachment(value)
|
||||
|
||||
async function loadDrawings (): Promise<Drawing[]> {
|
||||
const client = getClient()
|
||||
const drawings = await client.findAll(
|
||||
attachment.class.Drawing,
|
||||
{
|
||||
parent: value.file,
|
||||
space: value.space
|
||||
},
|
||||
{
|
||||
sort: {
|
||||
createdOn: SortingOrder.Descending
|
||||
},
|
||||
limit: 1
|
||||
}
|
||||
)
|
||||
|
||||
return Array.from(drawings ?? [])
|
||||
}
|
||||
|
||||
async function createDrawing (data: DrawingData): Promise<DrawingData> {
|
||||
const client = getClient()
|
||||
const newId = await client.createDoc(attachment.class.Drawing, value.space, {
|
||||
parent: value.file,
|
||||
parentClass: core.class.Blob,
|
||||
content: data.content
|
||||
})
|
||||
const newDrawing = await client.findOne(attachment.class.Drawing, { _id: newId })
|
||||
if (newDrawing === undefined) {
|
||||
throw new Error('Unable to find just created drawing')
|
||||
}
|
||||
return newDrawing
|
||||
}
|
||||
</script>
|
||||
|
||||
<FilePreviewPopup
|
||||
file={value.file}
|
||||
name={value.name}
|
||||
metadata={value.metadata}
|
||||
contentType={value.type}
|
||||
props={{
|
||||
drawingAvailable,
|
||||
loadDrawings,
|
||||
createDrawing
|
||||
}}
|
||||
{fullSize}
|
||||
{showIcon}
|
||||
on:open
|
||||
on:close
|
||||
on:update
|
||||
on:fullsize
|
||||
/>
|
@ -34,7 +34,7 @@
|
||||
const sel = listProvider.docs()[selected] as Attachment
|
||||
if (sel !== undefined && attachmentPopupId !== '') {
|
||||
listProvider.updateFocus(sel)
|
||||
updatePopup(attachmentPopupId, { props: { file: sel.file, name: sel.name, contentType: sel.type } })
|
||||
updatePopup(attachmentPopupId, { props: { value: sel } })
|
||||
}
|
||||
})
|
||||
$: listProvider.update(attachments.filter((p) => p.type.startsWith('image/')))
|
||||
@ -52,7 +52,13 @@
|
||||
on:open={(res) => (attachmentPopupId = res.detail)}
|
||||
/>
|
||||
{:else}
|
||||
<AttachmentPresenter value={attachment} removable={!readonly} showPreview on:remove />
|
||||
<AttachmentPresenter
|
||||
value={attachment}
|
||||
removable={!readonly}
|
||||
showPreview
|
||||
on:remove
|
||||
on:open={(res) => (attachmentPopupId = res.detail)}
|
||||
/>
|
||||
{/if}
|
||||
{/each}
|
||||
{#if progress}
|
||||
|
@ -14,10 +14,9 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { type Attachment, type Drawing } from '@hcengineering/attachment'
|
||||
import core, {
|
||||
import { type Attachment } from '@hcengineering/attachment'
|
||||
import {
|
||||
type BlobMetadata,
|
||||
SortingOrder,
|
||||
type Blob,
|
||||
type Class,
|
||||
type TxOperations as Client,
|
||||
@ -30,19 +29,18 @@ import core, {
|
||||
} from '@hcengineering/core'
|
||||
import { getResource, setPlatformStatus, unknownError } from '@hcengineering/platform'
|
||||
import {
|
||||
type DrawingData,
|
||||
type FileOrBlob,
|
||||
getClient,
|
||||
getFileMetadata,
|
||||
getPreviewAlignment,
|
||||
uploadFile,
|
||||
FilePreviewPopup
|
||||
uploadFile
|
||||
} from '@hcengineering/presentation'
|
||||
import { closeTooltip, showPopup, type PopupResult } from '@hcengineering/ui'
|
||||
import workbench, { type WidgetTab } from '@hcengineering/workbench'
|
||||
import view from '@hcengineering/view'
|
||||
|
||||
import attachment from './plugin'
|
||||
import AttachmentPreviewPopup from './components/AttachmentPreviewPopup.svelte'
|
||||
|
||||
export async function createAttachments (
|
||||
client: Client,
|
||||
@ -158,60 +156,8 @@ export function isAttachment (value: Attachment | BlobType): value is WithLookup
|
||||
}
|
||||
|
||||
export function showAttachmentPreviewPopup (value: WithLookup<Attachment> | BlobType): PopupResult {
|
||||
const props: Record<string, any> = {}
|
||||
|
||||
if (value?.type?.startsWith('image/') && isAttachment(value)) {
|
||||
props.drawingAvailable = true
|
||||
props.loadDrawings = async (): Promise<Drawing[] | undefined> => {
|
||||
const client = getClient()
|
||||
const drawings = await client.findAll(
|
||||
attachment.class.Drawing,
|
||||
{
|
||||
parent: value.file,
|
||||
space: value.space
|
||||
},
|
||||
{
|
||||
sort: {
|
||||
createdOn: SortingOrder.Descending
|
||||
},
|
||||
limit: 1
|
||||
}
|
||||
)
|
||||
const result = []
|
||||
if (drawings !== undefined) {
|
||||
for (const drawing of drawings) {
|
||||
result.push(drawing)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
props.createDrawing = async (data: DrawingData): Promise<DrawingData> => {
|
||||
const client = getClient()
|
||||
const newId = await client.createDoc(attachment.class.Drawing, value.space, {
|
||||
parent: value.file,
|
||||
parentClass: core.class.Blob,
|
||||
content: data.content
|
||||
})
|
||||
const newDrawing = await client.findOne(attachment.class.Drawing, { _id: newId })
|
||||
if (newDrawing === undefined) {
|
||||
throw new Error('Unable to find just created drawing')
|
||||
}
|
||||
return newDrawing
|
||||
}
|
||||
}
|
||||
|
||||
closeTooltip()
|
||||
return showPopup(
|
||||
FilePreviewPopup,
|
||||
{
|
||||
file: value.file,
|
||||
contentType: value.type,
|
||||
name: value.name,
|
||||
metadata: value.metadata,
|
||||
props
|
||||
},
|
||||
getPreviewAlignment(value.type ?? '')
|
||||
)
|
||||
return showPopup(AttachmentPreviewPopup, { value }, getPreviewAlignment(value.type ?? ''))
|
||||
}
|
||||
|
||||
interface ImageDimensions {
|
||||
|
Loading…
Reference in New Issue
Block a user