pleroma-fe/src/components/gallery/gallery.js

140 lines
3.8 KiB
JavaScript
Raw Normal View History

2026-01-06 16:23:17 +02:00
import { set, sumBy } from 'lodash'
2026-01-08 17:26:52 +02:00
2025-02-03 13:02:14 +02:00
import { useMediaViewerStore } from 'src/stores/media_viewer'
2019-01-26 17:45:03 +02:00
import Attachment from '../attachment/attachment.vue'
const Gallery = {
props: [
'attachments',
'compact',
2021-06-18 02:04:01 +03:00
'limitRows',
'descriptions',
'limit',
2019-01-26 17:45:03 +02:00
'nsfw',
'setMedia',
2021-06-18 02:04:01 +03:00
'size',
'editable',
'removeAttachment',
'shiftUpAttachment',
'shiftDnAttachment',
2021-06-18 02:04:01 +03:00
'editAttachment',
2026-01-06 16:22:52 +02:00
'grid',
2019-01-26 17:45:03 +02:00
],
2026-01-06 16:22:52 +02:00
data() {
return {
sizes: {},
2026-01-06 16:22:52 +02:00
hidingLong: true,
}
2019-01-26 17:45:03 +02:00
},
components: { Attachment },
computed: {
2026-01-06 16:22:52 +02:00
rows() {
2019-01-26 17:45:03 +02:00
if (!this.attachments) {
return []
}
2026-01-06 16:22:52 +02:00
const attachments =
this.limit > 0
? this.attachments.slice(0, this.limit)
: this.attachments
if (this.size === 'hide') {
2026-01-06 16:22:52 +02:00
return attachments.map((item) => ({ minimal: true, items: [item] }))
2019-01-26 17:45:03 +02:00
}
const rows = this.grid
? [{ grid: true, items: attachments }]
2026-01-06 16:22:52 +02:00
: attachments
.reduce(
(acc, attachment, i) => {
if (attachment.mimetype.includes('audio')) {
return [
...acc,
{ audio: true, items: [attachment] },
{ items: [] },
]
}
if (
!(
attachment.mimetype.includes('image') ||
attachment.mimetype.includes('video') ||
attachment.mimetype.includes('flash')
)
) {
return [
...acc,
{ minimal: true, items: [attachment] },
{ items: [] },
]
}
const maxPerRow = 3
const attachmentsRemaining = this.attachments.length - i + 1
const currentRow = acc[acc.length - 1].items
currentRow.push(attachment)
if (
currentRow.length >= maxPerRow &&
attachmentsRemaining > maxPerRow
) {
return [...acc, { items: [] }]
} else {
return acc
}
},
[{ items: [] }],
)
.filter((_) => _.items.length > 0)
2019-01-26 17:45:03 +02:00
return rows
},
2026-01-06 16:22:52 +02:00
attachmentsDimensionalScore() {
return this.rows.reduce((acc, row) => {
let size = 0
if (row.minimal) {
size += 1 / 8
} else if (row.audio) {
size += 1 / 4
} else {
size += 1 / (row.items.length + 0.6)
}
return acc + size
}, 0)
},
2026-01-06 16:22:52 +02:00
tooManyAttachments() {
2021-06-18 02:04:01 +03:00
if (this.editable || this.size === 'small') {
return false
} else if (this.size === 'hide') {
return this.attachments.length > 8
} else {
return this.attachmentsDimensionalScore > 1
}
2026-01-06 16:22:52 +02:00
},
2019-01-26 17:45:03 +02:00
},
methods: {
2026-01-06 16:22:52 +02:00
onNaturalSizeLoad({ id, width, height }) {
2022-03-18 13:32:36 +02:00
set(this.sizes, id, { width, height })
},
2026-01-06 16:22:52 +02:00
rowStyle(row) {
if (row.audio) {
return { 'padding-bottom': '25%' } // fixed reduced height for audio
} else if (!row.minimal && !row.grid) {
2026-01-06 16:22:52 +02:00
return { 'padding-bottom': `${100 / (row.items.length + 0.6)}%` }
}
},
2026-01-06 16:22:52 +02:00
itemStyle(id, row) {
const total = sumBy(row, (item) => this.getAspectRatio(item.id))
return { flex: `${this.getAspectRatio(id) / total} 1 0%` }
2019-10-21 15:13:11 -04:00
},
2026-01-06 16:22:52 +02:00
getAspectRatio(id) {
const size = this.sizes[id]
2019-10-21 15:13:11 -04:00
return size ? size.width / size.height : 1
},
2026-01-06 16:22:52 +02:00
toggleHidingLong(event) {
this.hidingLong = event
},
2026-01-06 16:22:52 +02:00
openGallery() {
2023-04-05 13:55:38 -06:00
useMediaViewerStore().setMedia(this.attachments)
useMediaViewerStore().setCurrentMedia(this.attachments[0])
2021-06-18 02:04:01 +03:00
},
2026-01-06 16:22:52 +02:00
onMedia() {
2023-04-05 13:55:38 -06:00
useMediaViewerStore().setMedia(this.attachments)
2026-01-06 16:22:52 +02:00
},
},
2019-01-26 17:45:03 +02:00
}
export default Gallery