diff --git a/packages/comment-widget/package.json b/packages/comment-widget/package.json index 70fa85d..30befc9 100644 --- a/packages/comment-widget/package.json +++ b/packages/comment-widget/package.json @@ -1,6 +1,6 @@ { "name": "@halo-dev/comment-widget", - "version": "1.3.0", + "version": "2.1.0", "author": { "name": "Halo", "url": "https://github.com/halo-dev" diff --git a/packages/comment-widget/src/avatar/avatar-policy.ts b/packages/comment-widget/src/avatar/avatar-policy.ts new file mode 100644 index 0000000..1cc4b56 --- /dev/null +++ b/packages/comment-widget/src/avatar/avatar-policy.ts @@ -0,0 +1,85 @@ +import { CommentVo, ReplyVo } from '@halo-dev/api-client'; +import { getAvatarProvider } from './providers'; + +abstract class AvatarPolicy { + abstract applyCommentPolicy(comment: CommentVo | undefined): string | undefined; + abstract applyReplyPolicy(reply: ReplyVo | undefined): string | undefined; +} + +let policyInstance: AvatarPolicy | undefined; +const emailKind = 'Email'; +const emailHash = 'email-hash'; + +class AnonymousUserPolicy extends AvatarPolicy { + applyCommentPolicy(comment: CommentVo | undefined): string | undefined { + const avatarProvider = getAvatarProvider(); + const isAnonymous = comment?.owner.kind === emailKind; + if (isAnonymous) { + return avatarProvider?.getAvatarSrc(comment?.spec.owner.annotations?.[emailHash]); + } + return comment?.owner.avatar; + } + applyReplyPolicy(reply: ReplyVo | undefined): string | undefined { + const avatarProvider = getAvatarProvider(); + const isAnonymous = reply?.owner.kind === emailKind; + if (isAnonymous) { + return avatarProvider?.getAvatarSrc(reply?.spec.owner.annotations?.[emailHash]); + } + return reply?.owner.avatar; + } +} + +class AllUserPolicy extends AvatarPolicy { + applyCommentPolicy(comment: CommentVo | undefined): string | undefined { + const avatarProvider = getAvatarProvider(); + return avatarProvider?.getAvatarSrc(comment?.spec.owner.annotations?.[emailHash]); + } + applyReplyPolicy(reply: ReplyVo | undefined): string | undefined { + const avatarProvider = getAvatarProvider(); + return avatarProvider?.getAvatarSrc(reply?.spec.owner.annotations?.[emailHash]); + } +} + +class NoAvatarUserPolicy extends AvatarPolicy { + applyCommentPolicy(comment: CommentVo | undefined): string | undefined { + const avatarProvider = getAvatarProvider(); + const isAnonymous = comment?.owner.kind === emailKind; + const avatar = comment?.owner.avatar; + if (isAnonymous || !avatar) { + return avatarProvider?.getAvatarSrc(comment?.spec.owner.annotations?.[emailHash]); + } + return avatar; + } + applyReplyPolicy(reply: ReplyVo | undefined): string | undefined { + const avatarProvider = getAvatarProvider(); + const isAnonymous = reply?.owner.kind === emailKind; + const avatar = reply?.owner.avatar; + if (isAnonymous || !avatar) { + return avatarProvider?.getAvatarSrc(reply?.spec.owner.annotations?.[emailHash]); + } + return avatar; + } +} + +enum AvatarPolicyEnum { + ANONYMOUS_USER_POLICY = 'anonymousUser', + ALL_USER_POLICY = 'allUser', + NO_AVATAR_USER_POLICY = 'noAvatarUser', +} + +function setPolicyInstance(nPolicyInstance: AvatarPolicy | undefined) { + policyInstance = nPolicyInstance; +} + +function getPolicyInstance(): AvatarPolicy | undefined { + return policyInstance; +} + +export { + AnonymousUserPolicy, + AllUserPolicy, + NoAvatarUserPolicy, + AvatarPolicyEnum, + setPolicyInstance, + getPolicyInstance, +}; diff --git a/packages/comment-widget/src/avatar/providers/avatar-provider.ts b/packages/comment-widget/src/avatar/providers/avatar-provider.ts new file mode 100644 index 0000000..6b38042 --- /dev/null +++ b/packages/comment-widget/src/avatar/providers/avatar-provider.ts @@ -0,0 +1,23 @@ +export default abstract class AvatarProvider { + private readonly _name: string; + private _url: string; + + constructor(name: string, url: string) { + this._name = name; + this._url = url; + } + + get url(): string { + return this._url; + } + + set url(value: string) { + this._url = value; + } + + get name(): string { + return this._name; + } + + abstract getAvatarSrc(emailHash: string | undefined): string; +} diff --git a/packages/comment-widget/src/avatar/providers/gravatar.ts b/packages/comment-widget/src/avatar/providers/gravatar.ts new file mode 100644 index 0000000..08da722 --- /dev/null +++ b/packages/comment-widget/src/avatar/providers/gravatar.ts @@ -0,0 +1,9 @@ +import AvatarProvider from './avatar-provider'; + +class Gravatar extends AvatarProvider { + override getAvatarSrc(emailHash: string | undefined): string { + return `${this.url}/avatar/${emailHash}`; + } +} + +export default new Gravatar('Gravatar', 'https://gravatar.com'); diff --git a/packages/comment-widget/src/avatar/providers/index.ts b/packages/comment-widget/src/avatar/providers/index.ts new file mode 100644 index 0000000..7723a1c --- /dev/null +++ b/packages/comment-widget/src/avatar/providers/index.ts @@ -0,0 +1,24 @@ +import Gravatar from './gravatar'; +import AvatarProvider from './avatar-provider'; + +let avatarProvider: AvatarProvider | undefined; + +enum AvatarProviderEnum { + GRAVATAR = 'gravatar', +} + +export function setAvatarProvider(provider: string, mirrorUrl?: string) { + switch (provider) { + case AvatarProviderEnum.GRAVATAR: + if (mirrorUrl) { + Gravatar.url = mirrorUrl; + } + avatarProvider = Gravatar; + break; + default: + } +} + +export function getAvatarProvider() { + return avatarProvider; +} diff --git a/packages/comment-widget/src/comment-item.ts b/packages/comment-widget/src/comment-item.ts index 5404505..25edca7 100644 --- a/packages/comment-widget/src/comment-item.ts +++ b/packages/comment-widget/src/comment-item.ts @@ -12,6 +12,7 @@ import { LS_UPVOTED_COMMENTS_KEY } from './constant'; import varStyles from './styles/var'; import { Ref, createRef, ref } from 'lit/directives/ref.js'; import { CommentReplies } from './comment-replies'; +import { getPolicyInstance } from './avatar/avatar-policy'; export class CommentItem extends LitElement { @consume({ context: baseUrlContext }) @@ -103,7 +104,7 @@ export class CommentItem extends LitElement { override render() { return html`(Symbol('name')); export const versionContext = createContext(Symbol('version')); export const replySizeContext = createContext(Symbol('replySize')); export const withRepliesContext = createContext(Symbol('withReplies')); +export const useAvatarProviderContext = createContext(Symbol('useAvatarProvider')); +export const avatarProviderContext = createContext(Symbol('avatarProvider')); +export const avatarProviderMirrorContext = createContext(Symbol('avatarProviderMirror')); +export const avatarPolicyContext = createContext(Symbol('avatarPolicy')); export const allowAnonymousCommentsContext = createContext( Symbol('allowAnonymousComments') diff --git a/packages/comment-widget/src/emoji-button.ts b/packages/comment-widget/src/emoji-button.ts index 104ea0e..19303cd 100644 --- a/packages/comment-widget/src/emoji-button.ts +++ b/packages/comment-widget/src/emoji-button.ts @@ -83,7 +83,7 @@ export class EmojiButton extends LitElement { } override render() { - return html`