Support multiple avatars/banners
This commit is contained in:
parent
1e0538bab0
commit
4129b2f3dc
2
PeerTube
2
PeerTube
|
@ -1 +1 @@
|
||||||
Subproject commit 3e8c3fcdb063e2d8f4b3ba04fdcdeda588538751
|
Subproject commit 28216aa41a392ae3b3f87871fefa22dadc471cf6
|
|
@ -7,8 +7,8 @@
|
||||||
:title="linkTitle"
|
:title="linkTitle"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
v-if="actor.avatar && !avatarError"
|
v-if="avatarUrl && !avatarError"
|
||||||
:src="actor.avatar.url"
|
:src="avatarUrl"
|
||||||
alt=""
|
alt=""
|
||||||
:class="{ account: isAccount }"
|
:class="{ account: isAccount }"
|
||||||
@error="setAvatarError()"
|
@error="setAvatarError()"
|
||||||
|
@ -39,6 +39,20 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
|
avatarUrl (): string {
|
||||||
|
const avatars = this.actor.avatars
|
||||||
|
if (avatars.length === 0) return ''
|
||||||
|
|
||||||
|
avatars.sort((a1, a2) => {
|
||||||
|
if (a1.width < a2.width) return -1
|
||||||
|
if (a1.width > a2.width) return 1
|
||||||
|
|
||||||
|
return 0
|
||||||
|
})
|
||||||
|
|
||||||
|
return avatars[0].url
|
||||||
|
},
|
||||||
|
|
||||||
linkTitle (): string {
|
linkTitle (): string {
|
||||||
if (this.type === 'channel') return this.$gettext('Go on this channel page')
|
if (this.type === 'channel') return this.$gettext('Go on this channel page')
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,12 @@ import { DBChannel, EnhancedVideoChannel, IndexableChannel } from '../../types/c
|
||||||
import { ChannelsSearchQuery } from '../../types/search-query/channel-search.model'
|
import { ChannelsSearchQuery } from '../../types/search-query/channel-search.model'
|
||||||
import { buildSort, extractQueryResult } from './elastic-search-queries'
|
import { buildSort, extractQueryResult } from './elastic-search-queries'
|
||||||
import { buildChannelOrAccountCommonMapping, buildMultiMatchBool } from './shared'
|
import { buildChannelOrAccountCommonMapping, buildMultiMatchBool } from './shared'
|
||||||
import { formatAvatarForAPI, formatAvatarForDB } from './shared/elastic-search-avatar'
|
import {
|
||||||
|
formatActorImageForAPI,
|
||||||
|
formatActorImageForDB,
|
||||||
|
formatActorImagesForAPI,
|
||||||
|
formatActorImagesForDB
|
||||||
|
} from './shared/elastic-search-avatar'
|
||||||
|
|
||||||
async function queryChannels (search: ChannelsSearchQuery) {
|
async function queryChannels (search: ChannelsSearchQuery) {
|
||||||
const bool: any = {}
|
const bool: any = {}
|
||||||
|
@ -86,7 +91,12 @@ function formatChannelForAPI (c: DBChannel, fromHost?: string): EnhancedVideoCha
|
||||||
followersCount: c.followersCount,
|
followersCount: c.followersCount,
|
||||||
createdAt: c.createdAt,
|
createdAt: c.createdAt,
|
||||||
updatedAt: c.updatedAt,
|
updatedAt: c.updatedAt,
|
||||||
avatar: formatAvatarForAPI(c),
|
|
||||||
|
avatar: formatActorImageForAPI(c.avatar),
|
||||||
|
avatars: formatActorImagesForAPI(c.avatars, c.avatar),
|
||||||
|
|
||||||
|
banner: formatActorImageForAPI(c.banner),
|
||||||
|
banners: formatActorImagesForAPI(c.banners, c.banner),
|
||||||
|
|
||||||
displayName: c.displayName,
|
displayName: c.displayName,
|
||||||
description: c.description,
|
description: c.description,
|
||||||
|
@ -106,7 +116,8 @@ function formatChannelForAPI (c: DBChannel, fromHost?: string): EnhancedVideoCha
|
||||||
createdAt: c.ownerAccount.createdAt,
|
createdAt: c.ownerAccount.createdAt,
|
||||||
updatedAt: c.ownerAccount.updatedAt,
|
updatedAt: c.ownerAccount.updatedAt,
|
||||||
|
|
||||||
avatar: formatAvatarForAPI(c.ownerAccount)
|
avatar: formatActorImageForAPI(c.ownerAccount.avatar),
|
||||||
|
avatars: formatActorImagesForAPI(c.ownerAccount.avatars, c.ownerAccount.avatar)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,7 +130,11 @@ function formatChannelForDB (c: IndexableChannel): DBChannel {
|
||||||
host: c.host,
|
host: c.host,
|
||||||
url: c.url,
|
url: c.url,
|
||||||
|
|
||||||
avatar: formatAvatarForDB(c),
|
avatar: formatActorImageForDB(c.avatar, c.host),
|
||||||
|
avatars: formatActorImagesForDB(c.avatars, c.host),
|
||||||
|
|
||||||
|
banner: formatActorImageForDB(c.banner, c.host),
|
||||||
|
banners: formatActorImagesForDB(c.banners, c.host),
|
||||||
|
|
||||||
displayName: c.displayName,
|
displayName: c.displayName,
|
||||||
|
|
||||||
|
@ -151,7 +166,8 @@ function formatChannelForDB (c: IndexableChannel): DBChannel {
|
||||||
|
|
||||||
handle: `${c.ownerAccount.name}@${c.ownerAccount.host}`,
|
handle: `${c.ownerAccount.name}@${c.ownerAccount.host}`,
|
||||||
|
|
||||||
avatar: formatAvatarForDB(c.ownerAccount)
|
avatar: formatActorImageForDB(c.ownerAccount.avatar, c.ownerAccount.host),
|
||||||
|
avatars: formatActorImagesForDB(c.ownerAccount.avatars, c.ownerAccount.host)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { AccountSummary, VideoChannelSummary } from '../../../../PeerTube/shared/models'
|
import { AccountSummary, VideoChannelSummary } from '../../../../PeerTube/shared/models'
|
||||||
import { AdditionalActorAttributes } from '../../../types/actor.model'
|
import { AdditionalActorAttributes } from '../../../types/actor.model'
|
||||||
import { buildAvatarMapping, formatAvatarForAPI, formatAvatarForDB } from './elastic-search-avatar'
|
import { formatActorImageForDB } from './'
|
||||||
|
import { buildActorImageMapping, formatActorImageForAPI, formatActorImagesForAPI, formatActorImagesForDB } from './elastic-search-avatar'
|
||||||
|
|
||||||
function buildChannelOrAccountSummaryMapping () {
|
function buildChannelOrAccountSummaryMapping () {
|
||||||
return {
|
return {
|
||||||
|
@ -30,7 +31,12 @@ function buildChannelOrAccountSummaryMapping () {
|
||||||
},
|
},
|
||||||
|
|
||||||
avatar: {
|
avatar: {
|
||||||
properties: buildAvatarMapping()
|
properties: buildActorImageMapping()
|
||||||
|
},
|
||||||
|
|
||||||
|
// Introduced in 4.2
|
||||||
|
avatars: {
|
||||||
|
properties: buildActorImageMapping()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,7 +75,8 @@ function formatActorSummaryForAPI (actor: (AccountSummary | VideoChannelSummary)
|
||||||
url: actor.url,
|
url: actor.url,
|
||||||
host: actor.host,
|
host: actor.host,
|
||||||
|
|
||||||
avatar: formatAvatarForAPI(actor)
|
avatar: formatActorImageForAPI(actor.avatar),
|
||||||
|
avatars: formatActorImagesForAPI(actor.avatars, actor.avatar)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +90,8 @@ function formatActorForDB (actor: AccountSummary | VideoChannelSummary) {
|
||||||
|
|
||||||
handle: `${actor.name}@${actor.host}`,
|
handle: `${actor.name}@${actor.host}`,
|
||||||
|
|
||||||
avatar: formatAvatarForDB(actor)
|
avatar: formatActorImageForDB(actor.avatar, actor.host),
|
||||||
|
avatars: formatActorImagesForDB(actor.avatars, actor.host)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,34 +1,59 @@
|
||||||
|
|
||||||
import { ActorImage } from '../../../../PeerTube/shared/models'
|
import { ActorImage } from '../../../../PeerTube/shared/models'
|
||||||
import { buildUrl } from '../../../helpers/utils'
|
import { buildUrl } from '../../../helpers/utils'
|
||||||
|
|
||||||
function formatAvatarForAPI (obj: { avatar?: ActorImage & { url: string } }) {
|
function formatActorImageForAPI (image?: ActorImage) {
|
||||||
if (!obj.avatar) return null
|
if (!image) return null
|
||||||
|
|
||||||
return {
|
return {
|
||||||
url: obj.avatar.url,
|
url: image.url,
|
||||||
path: obj.avatar.path,
|
path: image.path,
|
||||||
createdAt: obj.avatar.createdAt,
|
width: image.width,
|
||||||
updatedAt: obj.avatar.updatedAt
|
createdAt: image.createdAt,
|
||||||
|
updatedAt: image.updatedAt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatAvatarForDB (obj: { avatar?: ActorImage, host: string }) {
|
function formatActorImagesForAPI (images?: ActorImage[], image?: ActorImage) {
|
||||||
if (!obj.avatar) return null
|
// Does not exist in PeerTube < 4.2
|
||||||
|
if (!images) {
|
||||||
|
if (!image) return []
|
||||||
|
|
||||||
|
return [ image ]
|
||||||
|
}
|
||||||
|
|
||||||
|
return images.map(a => formatActorImageForAPI(a))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function formatActorImageForDB (image: ActorImage, host: string) {
|
||||||
|
if (!image) return null
|
||||||
|
|
||||||
return {
|
return {
|
||||||
url: buildUrl(obj.host, obj.avatar.path),
|
url: buildUrl(host, image.path),
|
||||||
path: obj.avatar.path,
|
path: image.path,
|
||||||
createdAt: obj.avatar.createdAt,
|
width: image.width,
|
||||||
updatedAt: obj.avatar.updatedAt
|
createdAt: image.createdAt,
|
||||||
|
updatedAt: image.updatedAt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildAvatarMapping () {
|
function formatActorImagesForDB (images: ActorImage[], host: string) {
|
||||||
|
if (!images) return null
|
||||||
|
|
||||||
|
return images.map(image => formatActorImageForDB(image, host))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function buildActorImageMapping () {
|
||||||
return {
|
return {
|
||||||
path: {
|
path: {
|
||||||
type: 'keyword'
|
type: 'keyword'
|
||||||
},
|
},
|
||||||
|
width: {
|
||||||
|
type: 'long'
|
||||||
|
},
|
||||||
createdAt: {
|
createdAt: {
|
||||||
type: 'date',
|
type: 'date',
|
||||||
format: 'date_optional_time'
|
format: 'date_optional_time'
|
||||||
|
@ -41,7 +66,11 @@ function buildAvatarMapping () {
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
formatAvatarForAPI,
|
formatActorImageForAPI,
|
||||||
formatAvatarForDB,
|
formatActorImagesForAPI,
|
||||||
buildAvatarMapping
|
|
||||||
|
formatActorImageForDB,
|
||||||
|
formatActorImagesForDB,
|
||||||
|
|
||||||
|
buildActorImageMapping
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,10 @@ import { ActorImage } from '../../PeerTube/shared/models'
|
||||||
|
|
||||||
export type AdditionalActorAttributes = {
|
export type AdditionalActorAttributes = {
|
||||||
handle: string
|
handle: string
|
||||||
avatar: ActorImageExtended
|
|
||||||
url: string
|
url: string
|
||||||
|
|
||||||
|
avatar: ActorImageExtended
|
||||||
|
avatars: ActorImageExtended[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ActorImageExtended = ActorImage & { url: string }
|
export type ActorImageExtended = ActorImage & { url: string }
|
||||||
|
|
|
@ -13,7 +13,11 @@ export interface DBChannel extends Omit<VideoChannel, 'isLocal'> {
|
||||||
|
|
||||||
ownerAccount?: Account & AdditionalActorAttributes
|
ownerAccount?: Account & AdditionalActorAttributes
|
||||||
|
|
||||||
avatar?: ActorImageExtended
|
avatar: ActorImageExtended
|
||||||
|
avatars: ActorImageExtended[]
|
||||||
|
|
||||||
|
banner: ActorImageExtended
|
||||||
|
banners: ActorImageExtended[]
|
||||||
|
|
||||||
score?: number
|
score?: number
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue