fix: adjust image size in message attachments (#6698)

Signed-off-by: Alexander Onnikov <Alexander.Onnikov@xored.com>
This commit is contained in:
Alexander Onnikov 2024-09-24 13:10:34 +07:00 committed by GitHub
parent b08749330d
commit ba5a7525d3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 106 additions and 69 deletions

View File

@ -0,0 +1,45 @@
<!--
// 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 { type AnySvelteComponent, ButtonIcon, IconSize } from '@hcengineering/ui'
import { Asset, IntlString } from '@hcengineering/platform'
import { ComponentType } from 'svelte'
export let label: IntlString
export let icon: Asset | AnySvelteComponent | ComponentType
export let iconProps: any | undefined = undefined
export let size: IconSize = 'small'
export let action: (ev: MouseEvent) => Promise<void> | void = async () => {}
export let opened: boolean = false
export let dataId: string | undefined = undefined
function onClick (ev: MouseEvent): void {
ev.stopPropagation()
ev.preventDefault()
void action(ev)
}
</script>
<ButtonIcon
{icon}
{iconProps}
iconSize={size}
size="small"
kind="tertiary"
pressed={opened}
{dataId}
tooltip={{ label }}
on:click={onClick}
/>

View File

@ -14,29 +14,21 @@
-->
<script lang="ts">
import { type Attachment } from '@hcengineering/attachment'
import { getEmbeddedLabel, getResource } from '@hcengineering/platform'
import {
import type { WithLookup } from '@hcengineering/core'
import { getResource } from '@hcengineering/platform'
import presentation, {
FilePreviewPopup,
canPreviewFile,
getFileUrl,
getPreviewAlignment,
previewTypes
} from '@hcengineering/presentation'
import {
ActionIcon,
IconMoreH,
IconOpen,
Menu,
Action as UIAction,
closeTooltip,
showPopup,
tooltip
} from '@hcengineering/ui'
import { IconMoreH, IconOpen, Menu, Action as UIAction, closeTooltip, showPopup, tooltip } from '@hcengineering/ui'
import view, { Action } from '@hcengineering/view'
import type { WithLookup } from '@hcengineering/core'
import attachmentPlugin from '../plugin'
import AttachmentAction from './AttachmentAction.svelte'
import FileDownload from './icons/FileDownload.svelte'
import attachmentPlugin from '../plugin'
export let attachment: WithLookup<Attachment>
export let isSaved = false
@ -131,30 +123,37 @@
</script>
<div class="flex">
{#if canPreview}
<AttachmentAction
label={view.string.Open}
icon={IconOpen}
size="small"
dataId="open-in-sidebar"
action={showPreview}
/>
{/if}
<a
class="mr-1 flex-row-center gap-2 p-1"
href={getFileUrl(attachment.file, attachment.name)}
download={attachment.name}
bind:this={download}
use:tooltip={{ label: getEmbeddedLabel(attachment.name) }}
use:tooltip={{ label: presentation.string.Download }}
on:click|stopPropagation
>
{#if canPreview}
<ActionIcon
icon={IconOpen}
size={'medium'}
action={(evt) => {
showPreview(evt)
}}
/>
{/if}
<ActionIcon
<AttachmentAction
label={presentation.string.Download}
icon={FileDownload}
size={'medium'}
size="small"
dataId="open-in-sidebar"
action={() => {
download.click()
}}
/>
</a>
<ActionIcon icon={IconMoreH} size={'medium'} action={showMenu} />
<AttachmentAction
label={view.string.MoreActions}
icon={IconMoreH}
size="small"
dataId="open-in-sidebar"
action={showMenu}
/>
</div>

View File

@ -26,6 +26,7 @@
interface Dimensions {
width: 'auto' | number
height: 'auto' | number
fit: 'cover' | 'contain'
}
const minSizeRem = 4
@ -45,7 +46,8 @@
if (size === 'auto') {
return {
width: 'auto',
height: 'auto'
height: 'auto',
fit: 'contain'
}
}
@ -55,42 +57,41 @@
if (!metadata) {
return {
width: preferredWidth,
height: preferredWidth
height: preferredWidth,
fit: 'contain'
}
}
const { originalWidth, originalHeight } = metadata
const maxSize = maxSizeRem * parseFloat(getComputedStyle(document.documentElement).fontSize)
const fontSize = parseFloat(getComputedStyle(document.documentElement).fontSize)
const maxSize = maxSizeRem * fontSize
const minSize = minSizeRem * fontSize
const width = Math.min(originalWidth, preferredWidth)
const ratio = originalHeight / originalWidth
const height = width * ratio
const fit = width < minSize || height < minSize ? 'cover' : 'contain'
if (height > maxSize) {
return {
width: maxSize / ratio,
height: maxSize
height: maxSize,
fit
}
} else if (height < minSize) {
return {
width,
height: minSize,
fit
}
} else {
return {
width,
height,
fit
}
}
return {
width,
height
}
}
function getObjectFit (size: Dimensions): 'contain' | 'cover' {
if (size.width === 'auto' || size.height === 'auto') {
return 'contain'
}
const minSize = minSizeRem * parseFloat(getComputedStyle(document.documentElement).fontSize)
if (size.width < minSize || size.height < minSize) {
return 'cover'
}
return 'contain'
}
function getUrlSize (size: AttachmentImageSize): IconSize {
@ -110,9 +111,9 @@
{#await getBlobRef(value.file, value.name, sizeToWidth(urlSize)) then blobSrc}
<img
src={blobSrc.src}
style:object-fit={getObjectFit(dimensions)}
width={dimensions.width}
height={dimensions.height}
style:object-fit={dimensions.fit}
width="100%"
height="100%"
srcset={blobSrc.srcset}
alt={value.name}
/>
@ -124,7 +125,6 @@
max-width: 20rem;
max-height: 20rem;
border-radius: 0.75rem;
object-fit: contain;
min-height: 4rem;
min-width: 4rem;
}

View File

@ -1,6 +1,6 @@
<!--
// Copyright © 2020, 2021 Anticrm Platform Contributors.
// Copyright © 2021 Hardcore Engineering Inc.
// Copyright © 2021, 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
@ -58,28 +58,28 @@
}}
>
<AttachmentImagePreview {value} size={imageSize} />
<div class="actions conner">
<div class="actions">
<AttachmentActions attachment={value} {isSaved} {removable} />
</div>
</div>
{:else if type === 'audio'}
<div class="buttonContainer">
<AudioPlayer {value} />
<div class="actions conner" style:padding={'0.125rem 0.25rem'}>
<div class="actions" style:padding={'0.125rem 0.25rem'}>
<AttachmentActions attachment={value} {isSaved} {removable} />
</div>
</div>
{:else if type === 'video'}
<div class="content buttonContainer flex-center">
<AttachmentVideoPreview {value} preload={videoPreload} />
<div class="actions conner">
<div class="actions">
<AttachmentActions attachment={value} {isSaved} {removable} />
</div>
</div>
{:else}
<div class="flex buttonContainer extraWidth">
<AttachmentPresenter {value} />
<div class="actions conner">
<div class="actions">
<AttachmentActions attachment={value} {isSaved} {removable} />
</div>
</div>
@ -100,17 +100,10 @@
position: absolute;
top: 0.25rem;
right: 0.25rem;
padding: 0.25rem;
padding: 0.125rem;
background-color: var(--theme-comp-header-color);
border: 1px solid var(--theme-divider-color);
border-radius: 0.75rem;
&.conner {
top: 0;
right: 0;
padding: 0.25rem;
border-radius: 0 0.4rem 0 0.25rem;
}
border-radius: 0.375rem;
}
}