Files
RenewCMS/web/src/lib/mediaDuplicates.ts
T

55 lines
1.5 KiB
TypeScript

import { t } from '@/i18n'
import type { MediaItem } from '@/composables/useMedia'
import { formatDimensions, formatSize } from '@/lib/mediaFormat'
export interface DuplicateGroup {
hash: string
copies: MediaItem[]
suggested: MediaItem
header: string
}
function byAge(first: MediaItem, second: MediaItem) {
return Date.parse(first.created_at) - Date.parse(second.created_at) || first.id - second.id
}
function byPreference(first: MediaItem, second: MediaItem) {
return second.used_in - first.used_in || byAge(first, second)
}
export function groupHeader(copies: MediaItem[]) {
const [first] = copies
return t('{0} identical images · {1} each · {2}', [
copies.length,
formatSize(first!.size),
formatDimensions(first!.width, first!.height),
])
}
export function groupDuplicates(items: MediaItem[]): DuplicateGroup[] {
const byHash = new Map<string, MediaItem[]>()
for (const item of items) {
byHash.set(item.sha256, [...(byHash.get(item.sha256) ?? []), item])
}
return [...byHash.entries()]
.filter(([, copies]) => copies.length > 1)
.map(([hash, copies]) => {
const sorted = [...copies].sort(byPreference)
return {
hash,
copies: sorted,
suggested: sorted[0]!,
get header() {
return groupHeader(sorted)
},
}
})
.sort((first, second) => byAge(first.suggested, second.suggested))
}
export function mergeArticleCount(copies: MediaItem[], keepId: number) {
return copies
.filter((copy) => copy.id !== keepId)
.reduce((total, copy) => total + copy.used_in, 0)
}