Skip to content

Commit c152038

Browse files
committed
fix: always use core viewType for compatibility
1 parent 566a0e6 commit c152038

7 files changed

Lines changed: 54 additions & 93 deletions

File tree

packages/frontend/src/components/attachment/Attachment.tsx

Lines changed: 15 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,60 +2,30 @@ import mimeTypes from 'mime-types'
22
import { Type } from '../../backend-com'
33
import { runtime } from '@deltachat-desktop/runtime-interface'
44

5-
/* Section - Data Copied in part from Signal */
6-
// Supported media types in google chrome
7-
// See: https://en.wikipedia.org/wiki/Comparison_of_web_browsers#Image_format_support
8-
const SUPPORTED_IMAGE_MIME_TYPES = Object.freeze([
9-
'image/bmp',
10-
'image/gif',
11-
'image/jpeg',
12-
'image/jpg',
13-
'image/svg+xml',
14-
'image/webp',
15-
'image/x-xbitmap',
16-
// ICO
17-
'image/vnd.microsoft.icon',
18-
'image/ico',
19-
'image/icon',
20-
'image/x-icon',
21-
// PNG
22-
'image/apng',
23-
'image/png',
24-
// for opening avatars
25-
'image/x',
26-
])
27-
// See: https://www.chromium.org/audio-video
28-
const SUPPORTED_VIDEO_MIME_TYPES = Object.freeze([
29-
'video/mp4',
30-
'video/ogg',
31-
'video/webm',
32-
'video/quicktime',
33-
])
34-
/* EndSection - Data Copied in part from Signal */
35-
36-
export function isImage(filemime: string | null) {
37-
return SUPPORTED_IMAGE_MIME_TYPES.includes(filemime || '')
5+
export function isImage(viewType: Type.Viewtype | null) {
6+
return viewType === 'Image' || viewType === 'Gif'
387
}
398

409
export function hasAttachment(attachment: MessageTypeAttachmentSubset | null) {
4110
return attachment && attachment.file
4211
}
4312

44-
export function isVideo(filemime: string | null) {
45-
return SUPPORTED_VIDEO_MIME_TYPES.includes(filemime || '')
46-
}
47-
48-
export function isAudio(filemime: string | null) {
49-
if (!filemime) return false
50-
return filemime.startsWith('audio/')
51-
}
13+
// note that we rely on the viewTypes from core here to make sure all Deltachat clients
14+
// display the same attachment types in the same way - although this could result in not
15+
// showing some attachments even if we could show them (like svg for example)
16+
// see guess_msgtype_from_path_suffix in https://github.com/chatmail/core/blob/main/src/message.rs
17+
const MEDIA_VIEW_TYPES = ['Image', 'Gif', 'Video', 'Audio', 'Voice'] as const
5218

53-
export function isDisplayableByFullscreenMedia(filemime: string | null) {
54-
return isImage(filemime) || isAudio(filemime) || isVideo(filemime)
19+
export function isDisplayableByFullscreenMedia(viewType: Type.Viewtype | null) {
20+
return MEDIA_VIEW_TYPES.includes(
21+
viewType as (typeof MEDIA_VIEW_TYPES)[number]
22+
)
5523
}
5624

57-
export function isGenericAttachment(filemime: string | null) {
58-
return !(isImage(filemime) || isVideo(filemime) || isAudio(filemime))
25+
export function isGenericAttachment(viewType: Type.Viewtype | null) {
26+
return !MEDIA_VIEW_TYPES.includes(
27+
viewType as (typeof MEDIA_VIEW_TYPES)[number]
28+
)
5929
}
6030

6131
export function getExtension({

packages/frontend/src/components/attachment/galleryAttachment.tsx

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,7 @@ import {
66
onDownload,
77
openWebxdc,
88
} from '../message/messageFunctions'
9-
import {
10-
isImage,
11-
isVideo,
12-
isAudio,
13-
getExtension,
14-
dragAttachmentOut,
15-
} from './Attachment'
9+
import { isImage, getExtension, dragAttachmentOut } from './Attachment'
1610
import Timestamp from '../conversations/Timestamp'
1711
import { makeContextMenu, OpenContextMenu } from '../ContextMenu'
1812
import { runtime } from '@deltachat-desktop/runtime-interface'
@@ -53,7 +47,7 @@ const contextMenuFactory = (
5347
openDialog: OpenDialog,
5448
jumpToMessage: JumpToMessage
5549
) => {
56-
const showCopyImage = message.viewType === 'Image'
50+
const showCopyImage = isImage(message.viewType)
5751
const tx = window.static_translate
5852
const { id: msgId, viewType } = message
5953
return [
@@ -235,7 +229,7 @@ export function ImageAttachment({
235229
accountId
236230
)
237231
const { file, fileMime } = message
238-
const hasSupportedFormat = isImage(fileMime)
232+
const hasSupportedFormat = isImage(message.viewType)
239233
const isBroken = !file || !hasSupportedFormat
240234

241235
return (
@@ -324,7 +318,7 @@ export function VideoAttachment({
324318
accountId
325319
)
326320
const { file, fileMime } = message
327-
const hasSupportedFormat = isVideo(fileMime)
321+
const hasSupportedFormat = message.viewType === 'Video'
328322
const isBroken = !file || !hasSupportedFormat
329323
return (
330324
<button
@@ -416,7 +410,8 @@ export function AudioAttachment({
416410
)
417411
const { file, fileMime } = message
418412
const src = runtime.transformBlobURL(file || '')
419-
const hasSupportedFormat = isAudio(fileMime)
413+
const hasSupportedFormat =
414+
message.viewType === 'Audio' || message.viewType === 'Voice'
420415
const isBroken = !file || !hasSupportedFormat
421416
return (
422417
<div

packages/frontend/src/components/attachment/messageAttachment.tsx

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ import { openAttachmentInShell } from '../message/messageFunctions'
66
import {
77
isDisplayableByFullscreenMedia,
88
isImage,
9-
isVideo,
10-
isAudio,
119
getExtension,
1210
dragAttachmentOut,
1311
MessageTypeAttachmentSubset,
@@ -50,7 +48,7 @@ export default function Attachment({
5048
const onClickAttachment = (ev: any) => {
5149
if (message.viewType === 'Sticker') return
5250
ev.stopPropagation()
53-
if (isDisplayableByFullscreenMedia(message.fileMime)) {
51+
if (isDisplayableByFullscreenMedia(message.viewType)) {
5452
openDialog(FullscreenMedia, {
5553
msg: message,
5654
neighboringMedia: NeighboringMediaMode.Chat,
@@ -126,7 +124,7 @@ export default function Attachment({
126124
const withCaption = Boolean(text)
127125
// For attachments which aren't full-frame
128126
const withContentBelow = withCaption
129-
if (isImage(message.fileMime) || message.viewType === 'Sticker') {
127+
if (isImage(message.viewType) || message.viewType === 'Sticker') {
130128
if (!message.file) {
131129
return (
132130
<div
@@ -158,7 +156,7 @@ export default function Attachment({
158156
/>
159157
</button>
160158
)
161-
} else if (isVideo(message.fileMime)) {
159+
} else if (message.viewType === 'Video') {
162160
if (!message.file) {
163161
return (
164162
<button
@@ -191,7 +189,7 @@ export default function Attachment({
191189
/>
192190
</div>
193191
)
194-
} else if (isAudio(message.fileMime)) {
192+
} else if (message.viewType === 'Audio' || message.viewType === 'Voice') {
195193
return (
196194
<div
197195
className={classNames(
@@ -299,7 +297,7 @@ export function DraftAttachment({
299297
if (!attachment) {
300298
return null
301299
}
302-
if (isImage(attachment.fileMime)) {
300+
if (isImage(attachment.viewType)) {
303301
return (
304302
<div className={classNames('message-attachment-media')}>
305303
<img
@@ -308,7 +306,7 @@ export function DraftAttachment({
308306
/>
309307
</div>
310308
)
311-
} else if (isVideo(attachment.fileMime)) {
309+
} else if (attachment.viewType === 'Video') {
312310
return (
313311
<div className={classNames('message-attachment-media')}>
314312
<video
@@ -318,7 +316,10 @@ export function DraftAttachment({
318316
/>
319317
</div>
320318
)
321-
} else if (isAudio(attachment.fileMime)) {
319+
} else if (
320+
attachment.viewType === 'Audio' ||
321+
attachment.viewType === 'Voice'
322+
) {
322323
return <AudioPlayer src={runtime.transformBlobURL(attachment.file || '')} />
323324
} else if (isViewTypeWebxdc) {
324325
const iconUrl = runtime.getWebxdcIconURL(selectedAccountId(), attachment.id)

packages/frontend/src/components/dialogs/FullscreenMedia.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import Dialog from '../Dialog'
66
import { IconButton } from '../Icon'
77
import { onDownload } from '../message/messageFunctions'
88
import { runtime } from '@deltachat-desktop/runtime-interface'
9-
import { isImage, isVideo, isAudio } from '../attachment/Attachment'
9+
1010
import { getLogger } from '../../../../shared/logger'
1111
import { gitHubIssuesUrl } from '../../../../shared/constants'
1212
import { useInitEffect } from '../helpers/hooks'
@@ -18,6 +18,7 @@ import useMessage from '../../hooks/chat/useMessage'
1818
import { useZoomKeyboardShortcuts } from '../../hooks/useZoomKeyboardShortcuts'
1919

2020
import type { DialogProps } from '../../contexts/DialogContext'
21+
import { isImage } from '../attachment/Attachment'
2122

2223
const log = getLogger('renderer/fullscreen_media')
2324

@@ -68,12 +69,11 @@ export default function FullscreenMedia(props: Props & DialogProps) {
6869
} else {
6970
const { viewType, chatId } = props.msg
7071
// workaround to get gifs and images into the same media list
71-
let additionalViewType: Type.Viewtype | null = null
72-
if (props.msg.viewType === 'Image') {
73-
additionalViewType = 'Gif'
74-
} else if (props.msg.viewType === 'Gif') {
75-
additionalViewType = 'Image'
76-
}
72+
const additionalViewType: Type.Viewtype | null = isImage(viewType)
73+
? viewType === 'Image'
74+
? 'Gif'
75+
: 'Image'
76+
: null
7777
const scope =
7878
props.neighboringMedia === NeighboringMediaMode.Global ? null : chatId
7979
BackendRemote.rpc
@@ -128,7 +128,7 @@ export default function FullscreenMedia(props: Props & DialogProps) {
128128

129129
let elm = null
130130

131-
if (isImage(fileMime)) {
131+
if (isImage(msg.viewType)) {
132132
const imageHeight =
133133
msg.dimensionsHeight < 300 ? 2 * msg.dimensionsHeight : ''
134134
elm = (
@@ -178,9 +178,9 @@ export default function FullscreenMedia(props: Props & DialogProps) {
178178
</TransformWrapper>
179179
</div>
180180
)
181-
} else if (isAudio(fileMime)) {
181+
} else if (msg.viewType === 'Audio' || msg.viewType === 'Voice') {
182182
elm = <audio src={runtime.transformBlobURL(file)} controls />
183-
} else if (isVideo(fileMime)) {
183+
} else if (msg.viewType === 'Video') {
184184
elm = <video src={runtime.transformBlobURL(file)} controls autoPlay />
185185
} else if (!fileMime) {
186186
// no file mime

packages/frontend/src/components/message/Message.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import {
2929
enterEditMessageMode,
3030
} from './messageFunctions'
3131
import Attachment from '../attachment/messageAttachment'
32-
import { isGenericAttachment, isImage, isVideo } from '../attachment/Attachment'
32+
import { isGenericAttachment, isImage } from '../attachment/Attachment'
3333
import { runtime } from '@deltachat-desktop/runtime-interface'
3434
import { ConversationType } from './MessageList'
3535
import { getDirection } from '../../utils/getDirection'
@@ -289,7 +289,7 @@ function buildContextMenu(
289289
}
290290

291291
const showAttachmentOptions = !!message.file
292-
const showCopyImage = !!message.file && message.viewType === 'Image'
292+
const showCopyImage = !!message.file && isImage(message.viewType)
293293
const showResend =
294294
message.sender.id === C.DC_CONTACT_ID_SELF && message.viewType !== 'Call'
295295

@@ -389,7 +389,7 @@ function buildContextMenu(
389389
// Open Attachment
390390
showAttachmentOptions &&
391391
message.viewType !== 'Webxdc' &&
392-
isGenericAttachment(message.fileMime) && {
392+
isGenericAttachment(message.viewType) && {
393393
label: tx('open_attachment'),
394394
action: openAttachmentInShell.bind(null, message),
395395
},
@@ -692,7 +692,8 @@ export default function Message(props: {
692692
// set message width which is used by reaction component
693693
// to adapt the number of visible reactions
694694
if (
695-
(message.fileMime && isImage(message.fileMime)) ||
695+
isImage(message.viewType) ||
696+
message.viewType === 'Sticker' ||
696697
window.innerWidth < 900
697698
) {
698699
// image messages have a defined width
@@ -712,7 +713,7 @@ export default function Message(props: {
712713
return () => {
713714
window.removeEventListener('resize', resizeHandler)
714715
}
715-
}, [message.fileMime])
716+
}, [message.viewType])
716717

717718
// Info Message
718719
if (message.isInfo) {
@@ -864,7 +865,7 @@ export default function Message(props: {
864865

865866
const hasText = text !== null && text !== ''
866867
const fileMime = message.fileMime || null
867-
const isWithoutText = isMediaWithoutText(fileMime, hasText, message.viewType)
868+
const isWithoutText = isMediaWithoutText(hasText, message.viewType)
868869
const showAttachment = (message: T.Message) =>
869870
message.file &&
870871
message.viewType !== 'Webxdc' &&
@@ -879,7 +880,7 @@ export default function Message(props: {
879880
direction,
880881
styles.message,
881882
rovingTabindex.className,
882-
isWithoutText && isVideo(fileMime) ? 'video-only' : '',
883+
isWithoutText && viewType === 'Video' ? 'video-only' : '',
883884
{
884885
[styles.withReactions]: message.reactions,
885886
'type-sticker': viewType === 'Sticker',

packages/frontend/src/components/message/MessageMetaData.tsx

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import classNames from 'classnames'
33
import { T } from '@deltachat/jsonrpc-client'
44

55
import Timestamp from '../conversations/Timestamp'
6-
import { isImage, isVideo } from '../attachment/Attachment'
6+
import { isImage } from '../attachment/Attachment'
77
import { msgStatus } from '../../types-app'
88
import useTranslationFunction from '../../hooks/useTranslationFunction'
99
import { useRpcFetch } from '../../hooks/useFetch'
@@ -37,7 +37,6 @@ export default function MessageMetaData(props: Props) {
3737
const {
3838
messageId,
3939
encrypted,
40-
fileMime,
4140
direction,
4241
status,
4342
error,
@@ -56,11 +55,7 @@ export default function MessageMetaData(props: Props) {
5655
return (
5756
<div
5857
className={classNames('metadata', {
59-
'with-image-no-caption': isMediaWithoutText(
60-
fileMime,
61-
hasText,
62-
viewType
63-
),
58+
'with-image-no-caption': isMediaWithoutText(hasText, viewType),
6459
})}
6560
>
6661
{/* FYI the email doesn't need `aria-live`
@@ -217,12 +212,11 @@ function ViewCount(props: { messageId: number }) {
217212
* without any further text.
218213
**/
219214
export function isMediaWithoutText(
220-
fileMime: string | null,
221215
hasText: boolean,
222216
viewType: T.Viewtype
223217
): boolean {
224218
const withImageNoCaption = Boolean(
225-
!hasText && (isImage(fileMime) || isVideo(fileMime))
219+
!hasText && (isImage(viewType) || viewType === 'Video')
226220
)
227221

228222
return withImageNoCaption || viewType === 'Sticker'

packages/frontend/src/system-integration/notifications.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { appName } from '../../../shared/constants'
22
import { getLogger } from '../../../shared/logger'
33
import { NOTIFICATION_TYPE } from '../../../shared/constants'
44
import { BackendRemote } from '../backend-com'
5-
import { isImage } from '../components/attachment/Attachment'
5+
66
import { runtime } from '@deltachat-desktop/runtime-interface'
77
import SettingsStoreInstance, {
88
mentionsEnabledDefaultVal,
@@ -468,7 +468,7 @@ export function clearAllNotifications() {
468468
function getNotificationIcon(
469469
notification: T.MessageNotificationInfo
470470
): [icon: string | null, iconIsAvatar: boolean] {
471-
if (notification.image && isImage(notification.imageMimeType)) {
471+
if (notification.image && notification.imageMimeType?.startsWith('image/')) {
472472
return [notification.image, false]
473473
} else if (notification.chatProfileImage) {
474474
return [notification.chatProfileImage, true]

0 commit comments

Comments
 (0)