tsk-371 Create avatar providers in models (#2339)

Signed-off-by: Denis Bunakalya <denis.bunakalya@xored.com>
This commit is contained in:
Denis Bunakalya 2022-10-31 14:59:01 +03:00 committed by GitHub
parent b600d736b8
commit 8287b4f465
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 70 additions and 25 deletions

View File

@ -16,6 +16,7 @@
import {
AvatarProvider,
AvatarType,
GetAvatarUrl,
Channel,
ChannelProvider,
Contact,
@ -49,9 +50,8 @@ import core, { TAccount, TAttachedDoc, TDoc, TSpace } from '@hcengineering/model
import presentation from '@hcengineering/model-presentation'
import view, { actionTemplates, createAction, ViewAction } from '@hcengineering/model-view'
import workbench from '@hcengineering/model-workbench'
import type { Asset, IntlString } from '@hcengineering/platform'
import type { Asset, IntlString, Resource } from '@hcengineering/platform'
import setting from '@hcengineering/setting'
import { IconSize } from '@hcengineering/ui'
import contact from './plugin'
export const DOMAIN_CONTACT = 'contact' as Domain
@ -60,7 +60,7 @@ export const DOMAIN_CHANNEL = 'channel' as Domain
@Model(contact.class.AvatarProvider, core.class.Doc, DOMAIN_MODEL)
export class TAvatarProvider extends TDoc implements AvatarProvider {
type!: AvatarType
getUrl!: (uri: string, size: IconSize) => string
getUrl!: Resource<GetAvatarUrl>
}
@Model(contact.class.ChannelProvider, core.class.Doc, DOMAIN_MODEL)
@ -370,6 +370,36 @@ export function createModel (builder: Builder): void {
contact.channelProvider.Homepage
)
builder.createDoc(
contact.class.AvatarProvider,
core.space.Model,
{
type: AvatarType.COLOR,
getUrl: contact.function.GetColorUrl
},
contact.avatarProvider.Color
)
builder.createDoc(
contact.class.AvatarProvider,
core.space.Model,
{
type: AvatarType.IMAGE,
getUrl: contact.function.GetFileUrl
},
contact.avatarProvider.Image
)
builder.createDoc(
contact.class.AvatarProvider,
core.space.Model,
{
type: AvatarType.GRAVATAR,
getUrl: contact.function.GetGravatarUrl
},
contact.avatarProvider.Gravatar
)
builder.mixin(contact.class.Person, core.class.Class, view.mixin.AttributePresenter, {
presenter: contact.component.PersonPresenter
})

View File

@ -13,10 +13,10 @@
// limitations under the License.
-->
<script lang="ts">
import { AvatarType, AvatarProvider } from '@hcengineering/contact'
import contact, { AvatarType, AvatarProvider } from '@hcengineering/contact'
import { Asset, getResource } from '@hcengineering/platform'
import { AnySvelteComponent, Icon, IconSize } from '@hcengineering/ui'
import { getBlobURL, getAvatarProviderId } from '../utils'
import { getBlobURL, getAvatarProviderId, getClient } from '../utils'
import AvatarIcon from './icons/Avatar.svelte'
export let avatar: string | null | undefined = undefined
@ -35,15 +35,16 @@
})
} else if (avatar) {
const avatarProviderId = getAvatarProviderId(avatar)
avatarProvider = avatarProviderId && (await getResource(avatarProviderId))
avatarProvider =
avatarProviderId && (await getClient().findOne(contact.class.AvatarProvider, { _id: avatarProviderId }))
if (!avatarProvider || avatarProvider.type === AvatarType.COLOR) {
url = undefined
} else if (avatarProvider.type === AvatarType.IMAGE) {
url = avatarProvider.getUrl(avatar, size)
url = (await getResource(avatarProvider.getUrl))(avatar, size)
} else {
const uri = avatar.split('://')[1]
url = avatarProvider.getUrl(uri, size)
url = (await getResource(avatarProvider.getUrl))(uri, size)
}
} else {
url = undefined
@ -53,14 +54,18 @@
$: update(size, avatar, direct)
let style = ''
$: if (!avatar || avatarProvider?.type !== AvatarType.COLOR) {
style = ''
} else {
const uri = avatar.split('://')[1]
const color = avatarProvider.getUrl(uri, size)
style = `background-color: ${color}`
async function updateStyle (avatar?: string | null, avatarProvider?: AvatarProvider) {
if (!avatar || avatarProvider?.type !== AvatarType.COLOR) {
style = ''
} else {
const uri = avatar.split('://')[1]
const color = (await getResource(avatarProvider.getUrl))(uri, size)
style = `background-color: ${color}`
}
}
$: updateStyle(avatar, avatarProvider)
</script>
<div class="ava-{size} flex-center avatar-container" class:no-img={!url} {style}>

View File

@ -34,7 +34,7 @@ import core, {
TxResult
} from '@hcengineering/core'
import login from '@hcengineering/login'
import { getMetadata, Resource } from '@hcengineering/platform'
import { getMetadata } from '@hcengineering/platform'
import { LiveQuery as LQ } from '@hcengineering/query'
import { onDestroy } from 'svelte'
import { deepEqual } from 'fast-equals'
@ -281,7 +281,7 @@ export function getAvatarColorForId (id: string): string {
return AVATAR_COLORS[hash % AVATAR_COLORS.length]
}
export function getAvatarProviderId (avatar?: string | null): Resource<AvatarProvider> | undefined {
export function getAvatarProviderId (avatar?: string | null): Ref<AvatarProvider> | undefined {
if (avatar === null || avatar === undefined || avatar === '') {
return
}

View File

@ -14,7 +14,7 @@
// limitations under the License.
//
import { AvatarType, Channel, Contact, Employee, formatName } from '@hcengineering/contact'
import { Channel, Contact, Employee, formatName } from '@hcengineering/contact'
import { Class, Client, DocumentQuery, Ref, RelatedDocument, WithLookup } from '@hcengineering/core'
import { leaveWorkspace } from '@hcengineering/login-resources'
import { Resources } from '@hcengineering/platform'
@ -168,9 +168,9 @@ export default async (): Promise<Resources> => ({
filter?: { in?: RelatedDocument[], nin?: RelatedDocument[] }
) => await queryContact(contact.class.Organization, client, query, filter)
},
avatarProvider: {
Image: { type: AvatarType.IMAGE, getUrl: getFileUrl },
Gravatar: { type: AvatarType.GRAVATAR, getUrl: getGravatarUrl },
Color: { type: AvatarType.COLOR, getUrl: (uri: string) => uri }
function: {
GetFileUrl: getFileUrl,
GetGravatarUrl: getGravatarUrl,
GetColorUrl: (uri: string) => uri
}
})

View File

@ -78,12 +78,17 @@ export enum AvatarType {
GRAVATAR = 'gravatar'
}
/**
* @public
*/
export type GetAvatarUrl = (uri: string, size: IconSize) => string
/**
* @public
*/
export interface AvatarProvider extends Doc {
type: AvatarType
getUrl: (uri: string, size: IconSize) => string
getUrl: Resource<GetAvatarUrl>
}
/**
@ -214,9 +219,14 @@ const contactPlugin = plugin(contactId, {
Homepage: '' as Ref<ChannelProvider>
},
avatarProvider: {
Color: '' as Resource<AvatarProvider>,
Image: '' as Resource<AvatarProvider>,
Gravatar: '' as Resource<AvatarProvider>
Color: '' as Ref<AvatarProvider>,
Image: '' as Ref<AvatarProvider>,
Gravatar: '' as Ref<AvatarProvider>
},
function: {
GetColorUrl: '' as Resource<GetAvatarUrl>,
GetFileUrl: '' as Resource<GetAvatarUrl>,
GetGravatarUrl: '' as Resource<GetAvatarUrl>
},
icon: {
ContactApplication: '' as Asset,