Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
ruibaby committed Apr 26, 2024
2 parents 5ce274d + 824c05d commit 3ae42f1
Show file tree
Hide file tree
Showing 15 changed files with 294 additions and 11 deletions.
2 changes: 1 addition & 1 deletion packages/comment-widget/package.json
Original file line number Diff line number Diff line change
@@ -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"
Expand Down
85 changes: 85 additions & 0 deletions packages/comment-widget/src/avatar/avatar-policy.ts
Original file line number Diff line number Diff line change
@@ -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,
};
23 changes: 23 additions & 0 deletions packages/comment-widget/src/avatar/providers/avatar-provider.ts
Original file line number Diff line number Diff line change
@@ -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;
}
9 changes: 9 additions & 0 deletions packages/comment-widget/src/avatar/providers/gravatar.ts
Original file line number Diff line number Diff line change
@@ -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');
24 changes: 24 additions & 0 deletions packages/comment-widget/src/avatar/providers/index.ts
Original file line number Diff line number Diff line change
@@ -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;
}
11 changes: 10 additions & 1 deletion packages/comment-widget/src/comment-item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 })
Expand Down Expand Up @@ -103,7 +104,7 @@ export class CommentItem extends LitElement {

override render() {
return html`<base-comment-item
.userAvatar="${this.comment?.owner.avatar}"
.userAvatar="${handleCommentAvatar(this.comment)}"
.userDisplayName="${this.comment?.owner.displayName}"
.content="${this.comment?.spec.content || ''}"
.creationTime="${this.comment?.spec.creationTime}"
Expand Down Expand Up @@ -233,6 +234,14 @@ export class CommentItem extends LitElement {

customElements.get('comment-item') || customElements.define('comment-item', CommentItem);

function handleCommentAvatar(comment: CommentVo | undefined): string | undefined {
const avatarPolicy = getPolicyInstance();
if (avatarPolicy === undefined) {
return comment?.owner.avatar;
}
return avatarPolicy.applyCommentPolicy(comment);
}

declare global {
interface HTMLElementTagNameMap {
'comment-item': CommentItem;
Expand Down
60 changes: 59 additions & 1 deletion packages/comment-widget/src/comment-widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { repeat } from 'lit/directives/repeat.js';
import baseStyles from './styles/base';
import { provide } from '@lit/context';
import {
allowAnonymousCommentsContext,
baseUrlContext,
currentUserContext,
emojiDataUrlContext,
Expand All @@ -16,12 +15,25 @@ import {
toastContext,
versionContext,
withRepliesContext,
allowAnonymousCommentsContext,
useAvatarProviderContext,
avatarPolicyContext,
avatarProviderContext,
avatarProviderMirrorContext,
} from './context';
import './comment-form';
import './comment-item';
import './comment-pagination';
import varStyles from './styles/var';
import { ToastManager } from './lit-toast';
import {
AnonymousUserPolicy,
AllUserPolicy,
NoAvatarUserPolicy,
AvatarPolicyEnum,
setPolicyInstance,
} from './avatar/avatar-policy';
import { setAvatarProvider } from './avatar/providers';

export class CommentWidget extends LitElement {
@provide({ context: baseUrlContext })
Expand Down Expand Up @@ -58,6 +70,22 @@ export class CommentWidget extends LitElement {
@property({ type: Number, attribute: 'with-reply-size' })
withReplySize = 10;

@provide({ context: useAvatarProviderContext })
@property({ type: Boolean, attribute: 'use-avatar-provider' })
useAvatarProvider = false;

@provide({ context: avatarProviderContext })
@property({ type: String, attribute: 'avatar-provider' })
avatarProvider = '';

@provide({ context: avatarProviderMirrorContext })
@property({ type: String, attribute: 'avatar-provider-mirror' })
avatarProviderMirror = '';

@provide({ context: avatarPolicyContext })
@property({ type: String, attribute: 'avatar-policy' })
avatarPolicy = '';

@provide({ context: emojiDataUrlContext })
@property({ type: String, attribute: 'emoji-data-url' })
emojiDataUrl = 'https://unpkg.com/@emoji-mart/data';
Expand Down Expand Up @@ -203,12 +231,42 @@ export class CommentWidget extends LitElement {
await this.fetchComments({ scrollIntoView: true });
}

initAvatarProvider() {
if (!this.useAvatarProvider) {
return;
}
setAvatarProvider(this.avatarProvider, this.avatarProviderMirror);
}

initAvatarPolicy() {
if (!this.useAvatarProvider) {
console.log(this.useAvatarProvider);
setPolicyInstance(undefined);
return;
}
switch (this.avatarPolicy) {
case AvatarPolicyEnum.ALL_USER_POLICY: {
setPolicyInstance(new AllUserPolicy());
break;
}
case AvatarPolicyEnum.NO_AVATAR_USER_POLICY: {
setPolicyInstance(new NoAvatarUserPolicy());
break;
}
case AvatarPolicyEnum.ANONYMOUS_USER_POLICY:
default:
setPolicyInstance(new AnonymousUserPolicy());
}
}

override connectedCallback(): void {
super.connectedCallback();
this.toastManager = new ToastManager();
this.fetchCurrentUser();
this.fetchComments();
this.fetchGlobalInfo();
this.initAvatarProvider();
this.initAvatarPolicy();
}

static override styles = [
Expand Down
4 changes: 4 additions & 0 deletions packages/comment-widget/src/context/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ export const nameContext = createContext<string>(Symbol('name'));
export const versionContext = createContext<string>(Symbol('version'));
export const replySizeContext = createContext<number>(Symbol('replySize'));
export const withRepliesContext = createContext<boolean>(Symbol('withReplies'));
export const useAvatarProviderContext = createContext<boolean>(Symbol('useAvatarProvider'));
export const avatarProviderContext = createContext<string>(Symbol('avatarProvider'));
export const avatarProviderMirrorContext = createContext<string>(Symbol('avatarProviderMirror'));
export const avatarPolicyContext = createContext<string>(Symbol('avatarPolicy'));

export const allowAnonymousCommentsContext = createContext<boolean>(
Symbol('allowAnonymousComments')
Expand Down
2 changes: 1 addition & 1 deletion packages/comment-widget/src/emoji-button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export class EmojiButton extends LitElement {
}

override render() {
return html`<button class="emoji-button" type="button">
return html`<button class="emoji-button" type="button" aria-label="选择表情">
${this.emojiLoading
? html`<icon-loading></icon-loading>`
: html`<icon-emoji @click=${this.handleOpenEmojiPicker}></icon-emoji>`}
Expand Down
11 changes: 10 additions & 1 deletion packages/comment-widget/src/reply-item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { LS_UPVOTED_REPLIES_KEY } from './constant';
import { consume } from '@lit/context';
import { baseUrlContext } from './context';
import varStyles from './styles/var';
import { getPolicyInstance } from './avatar/avatar-policy';

export class ReplyItem extends LitElement {
@consume({ context: baseUrlContext })
Expand Down Expand Up @@ -106,7 +107,7 @@ export class ReplyItem extends LitElement {
override render() {
return html`
<base-comment-item
.userAvatar="${this.reply?.owner.avatar}"
.userAvatar="${handleReplyAvatar(this.reply)}"
.userDisplayName="${this.reply?.owner.displayName}"
.content="${this.reply?.spec.content || ''}"
.creationTime="${this.reply?.metadata.creationTimestamp ?? undefined}"
Expand Down Expand Up @@ -248,6 +249,14 @@ export class ReplyItem extends LitElement {

customElements.get('reply-item') || customElements.define('reply-item', ReplyItem);

function handleReplyAvatar(reply: ReplyVo | undefined): string | undefined {
const avatarPolicy = getPolicyInstance();
if (avatarPolicy === undefined) {
return reply?.owner.avatar;
}
return avatarPolicy.applyReplyPolicy(reply);
}

declare global {
interface HTMLElementTagNameMap {
'reply-item': ReplyItem;
Expand Down
8 changes: 8 additions & 0 deletions packages/widget/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ interface Props {
replySize?: number;
withReplies?: boolean;
withReplySize?: number;
useAvatarProvider: boolean;
avatarProvider?: string;
avatarProviderMirror?: string;
avatarPolicy?: string;
}

export function init(el: string, props: Props) {
Expand All @@ -34,6 +38,10 @@ export function init(el: string, props: Props) {
commentWidget.withReplySize = props.withReplySize || 10;
commentWidget.emojiDataUrl =
'/plugins/PluginCommentWidget/assets/static/emoji/native.json';
commentWidget.useAvatarProvider = props.useAvatarProvider || false;
commentWidget.avatarProvider = props.avatarProvider || '';
commentWidget.avatarProviderMirror = props.avatarProviderMirror || '';
commentWidget.avatarPolicy = props.avatarPolicy || '';

const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import org.pf4j.PluginWrapper;
import org.springframework.stereotype.Component;
import run.halo.app.extension.SchemeManager;
import run.halo.app.plugin.BasePlugin;

/**
Expand All @@ -11,10 +10,10 @@
*/
@Component
public class CommentWidgetPlugin extends BasePlugin {

public CommentWidgetPlugin(PluginWrapper wrapper) {
super(wrapper);
}

@Override
public void start() {
}
Expand Down
Loading

0 comments on commit 3ae42f1

Please sign in to comment.