From 4fa26cff04a3245f4ae3c1b82d5222e7c2aff0b9 Mon Sep 17 00:00:00 2001 From: Yuzuki Aida Date: Thu, 16 May 2024 23:47:34 +0900 Subject: [PATCH] Add popover, fix mastodon domain processing, tweak styling --- apps/server/src/streaming/mastodon.ts | 7 +- apps/web/locales/en.json | 14 +- apps/web/locales/ja.json | 14 +- .../comment-post/fediverse-sync-popover.tsx | 53 ++++++++ .../web/organisms/live/comment-post/index.tsx | 120 +++++++++++------- .../live/comment-post/public-post-switch.tsx | 30 +++-- 6 files changed, 169 insertions(+), 69 deletions(-) create mode 100644 apps/web/organisms/live/comment-post/fediverse-sync-popover.tsx diff --git a/apps/server/src/streaming/mastodon.ts b/apps/server/src/streaming/mastodon.ts index 370bcdb8..d9b06387 100644 --- a/apps/server/src/streaming/mastodon.ts +++ b/apps/server/src/streaming/mastodon.ts @@ -4,7 +4,8 @@ import { comments, lives, users } from '../models'; import { pubsub } from '../services/redis/pubsub/client'; const token = process.env.MASTODON_ACCESS_TOKEN || ''; -const domain = process.env.MASTODON_DOMAIN || ''; +const mastodonDomain = process.env.MASTODON_DOMAIN || ''; +const streamingDomain = process.env.MASTODON_STREAMING_DOMAIN || mastodonDomain; type Hashtag = { hashtag: string; @@ -26,7 +27,7 @@ export class MastodonStreaming { try { const ws = new WebSocket( - `wss://${domain}/api/v1/streaming/?access_token=${token}` + `wss://${streamingDomain}/api/v1/streaming/?access_token=${token}` ); this.ws = ws; @@ -200,7 +201,7 @@ export class MastodonStreaming { if (liveIds.length > 0) { const acct = payload.account.acct === payload.account.username - ? `${payload.account.acct}@${domain}` + ? `${payload.account.acct}@${mastodonDomain}` : payload.account.acct; const user = await users.getOrCreateForRemote( diff --git a/apps/web/locales/en.json b/apps/web/locales/en.json index 82ac2e04..b54a4f84 100644 --- a/apps/web/locales/en.json +++ b/apps/web/locales/en.json @@ -72,11 +72,15 @@ "live.comment-post.require-login.with-hashtag": "To post a comment, please sign in or post as publicly with #{hashtag}", "live.comment-post.placeholder": "Enter to comment", "live.comment-post.placeholder.with-hashtag": "Enter to post a comment (or post as publicly with #{hashtag})", - "live.comment-post.publish.tooltip.enabled": "Publish to ActivityPub: Enabled", - "live.comment-post.publish.tooltip.disabled": "Publish to ActivityPub: Disabled", - "live.comment-post.publish.tooltip.disabled-in-live": "Publish to ActivityPub: Disabled (by streamer)", - "live.comment-post.publish.popover.title": "Publish to ActivityPub", - "live.comment-post.publish.popover.description": "If enabled, your comment will be posted as unlisted/home on your account {acct} with the hashtag #{hashtag}. Your comment will only be posted on KnzkLive if the streamer disables it or with this switch.", + "live.comment-post.fediverse-sync.title": "Comment via Fediverse with #{hashtag} 💬", + "live.comment-post.fediverse-sync.description": "If you have a Mastodon or Misskey account, you can comment directly on the live feed by posting a post with #{hashtag}!", + "live.comment-post.fediverse-sync.notice": "* There are certain conditions for syncing comments from Fediverse, you can also log in to KnzkLive and comment directly.", + "live.comment-post.publish.tooltip.enabled": "Sync comments with ActivityPub: Enabled", + "live.comment-post.publish.tooltip.disabled": "Sync comments with ActivityPub: Disabled", + "live.comment-post.publish.tooltip.disabled-in-live": "Sync comments with ActivityPub: Disabled (by streamer)", + "live.comment-post.publish.popover.title": "Sync comments with ActivityPub", + "live.comment-post.publish.popover.description": "If enabled, your comment will be posted as unlisted/home on your account {acct} with the hashtag #{hashtag}.", + "live.comment-post.publish.popover.description2": "Your comment will only be posted on KnzkLive if the streamer disables it or with this switch.", "live.comment-post.permission-denied": "Please re-login to KnzkLive with the same account because you do not have the required permission.", "live.not-started": "Not started", "live.viewers-count": "{sum} viewed in live", diff --git a/apps/web/locales/ja.json b/apps/web/locales/ja.json index 4efbe580..c1d010eb 100644 --- a/apps/web/locales/ja.json +++ b/apps/web/locales/ja.json @@ -68,15 +68,19 @@ "live.comment.title.with-hashtag": "コメント #{hashtag}", "video.comment.title": "コメント (リプレイ)", "video.comment.title.with-hashtag": "コメント (リプレイ) #{hashtag}", + "live.comment-post.fediverse-sync.title": "Fediverse から #{hashtag} でコメントできます 💬", + "live.comment-post.fediverse-sync.description": "Mastodon や Misskey などの Fediverse アカウントをお持ちの場合、 #{hashtag} を付けてポストを投稿することでライブ配信上にそのままコメントできます!", + "live.comment-post.fediverse-sync.notice": "* Fediverse からのコメントの同期には一定の条件があります。KnzkLive にログインして直接ここからコメントすることもできます。", "live.comment-post.require-login": "コメントを投稿するにはログインが必要です", "live.comment-post.require-login.with-hashtag": "コメントを投稿するにはログインするか、#{hashtag} で公開投稿してください", "live.comment-post.placeholder": "Enter でコメントを投稿", "live.comment-post.placeholder.with-hashtag": "Enter でコメントを投稿 (もしくは #{hashtag} で公開投稿)", - "live.comment-post.publish.tooltip.enabled": "コメントの公開投稿: 有効", - "live.comment-post.publish.tooltip.disabled": "コメントの公開投稿: 無効", - "live.comment-post.publish.tooltip.disabled-in-live": "コメントの公開投稿: 無効(配信者が無効化)", - "live.comment-post.publish.popover.title": "コメントの公開投稿", - "live.comment-post.publish.popover.description": "有効にすると、ハッシュタグ #{hashtag} を付けてあなたのアカウント {acct} でコメントを未収載/ホームで投稿します。配信者が配信設定で無効にするか、このスイッチで無効にするとあなたのコメントは KnzkLive 上にのみ投稿されます。", + "live.comment-post.publish.tooltip.enabled": "コメントの同期: 有効", + "live.comment-post.publish.tooltip.disabled": "コメントの同期: 無効", + "live.comment-post.publish.tooltip.disabled-in-live": "コメントの同期: 無効(配信者が無効化)", + "live.comment-post.publish.popover.title": "コメントの同期", + "live.comment-post.publish.popover.description": "有効にすると、ハッシュタグ #{hashtag} を付けてあなたのアカウント {acct} でコメントを未収載/ホームで投稿します。", + "live.comment-post.publish.popover.description2": "配信者が配信設定で無効にするか、このスイッチで無効にするとあなたのコメントは KnzkLive 上にのみ投稿されます。", "live.comment-post.permission-denied": "お手数ですが必要な権限が取得できていないため、同じアカウントで KnzkLive へ再ログインしてください。", "live.not-started": "未開始", "live.viewers-count": "{sum} 人が生配信で視聴", diff --git a/apps/web/organisms/live/comment-post/fediverse-sync-popover.tsx b/apps/web/organisms/live/comment-post/fediverse-sync-popover.tsx new file mode 100644 index 00000000..6a5cc710 --- /dev/null +++ b/apps/web/organisms/live/comment-post/fediverse-sync-popover.tsx @@ -0,0 +1,53 @@ +import { + PopoverArrow, + PopoverBody, + PopoverCloseButton, + PopoverContent, + PopoverHeader, + Portal, + Text, + VStack +} from '@chakra-ui/react'; +import { FC } from 'react'; +import { FormattedMessage } from 'react-intl'; + +type Props = { + hashtag: string; +}; + +export const FediverseSyncPopover: FC = ({ hashtag }) => { + return ( + + + + + + + + + + + + + + + + + + + + + + + + ); +}; diff --git a/apps/web/organisms/live/comment-post/index.tsx b/apps/web/organisms/live/comment-post/index.tsx index e75af9e1..539fdeec 100644 --- a/apps/web/organisms/live/comment-post/index.tsx +++ b/apps/web/organisms/live/comment-post/index.tsx @@ -4,9 +4,12 @@ import { Icon, Input, InputGroup, - InputRightElement + InputRightElement, + Popover, + PopoverAnchor, + useDisclosure } from '@chakra-ui/react'; -import { FC, FormEvent, useCallback, useState } from 'react'; +import { FC, FormEvent, useCallback, useEffect, useState } from 'react'; import { useIntl } from 'react-intl'; import { FiSend } from 'react-icons/fi'; import { useAPIError } from '~/utils/hooks/api/use-api-error'; @@ -15,6 +18,7 @@ import { useUsersMe } from '~/utils/hooks/api/use-users-me'; import { useLocalStorage } from 'react-use'; import { useCommentPublish } from '~/utils/hooks/api/use-comment-publish'; import { PublicPostSwitch } from './public-post-switch'; +import { FediverseSyncPopover } from './fediverse-sync-popover'; type Props = { liveId: number; @@ -31,6 +35,7 @@ export const CommentPost: FC = ({ liveId, hashtag }) => { ); const [comment, setComment] = useState(''); const [isLoading, setIsLoading] = useState(false); + const fediverseSyncPopoverDisclosure = useDisclosure(); const { handlePublish } = useCommentPublish(liveId, hashtag); const [error, setError] = useState(); useAPIError(error); @@ -67,53 +72,78 @@ export const CommentPost: FC = ({ liveId, hashtag }) => { [comment, token, enablePublish, handlePublish, hashtag] ); + const onOpen = fediverseSyncPopoverDisclosure.onOpen; + useEffect(() => { + if (!isSignedIn && hashtag) { + const timeoutId = setTimeout(() => { + onOpen(); + }, 1000 * 3); + + return () => { + clearTimeout(timeoutId); + }; + } + }, [isSignedIn, onOpen, hashtag]); + return (
- - setComment(e.target.value)} - placeholder={intl.formatMessage( - { - id: !isSignedIn - ? hashtag - ? 'live.comment-post.require-login.with-hashtag' - : 'live.comment-post.require-login' - : hashtag - ? 'live.comment-post.placeholder.with-hashtag' - : 'live.comment-post.placeholder' - }, - { hashtag } - )} - isDisabled={!isSignedIn} - maxLength={100} - /> - - - - + + + setComment(e.target.value)} + placeholder={intl.formatMessage( + { + id: !isSignedIn + ? hashtag + ? 'live.comment-post.require-login.with-hashtag' + : 'live.comment-post.require-login' + : hashtag + ? 'live.comment-post.placeholder.with-hashtag' + : 'live.comment-post.placeholder' + }, + { hashtag } + )} + isDisabled={!isSignedIn} + maxLength={100} /> - - - - + + + + + + + + + + + {!isSignedIn && !!hashtag && } + ); }; diff --git a/apps/web/organisms/live/comment-post/public-post-switch.tsx b/apps/web/organisms/live/comment-post/public-post-switch.tsx index 89c16759..4d826d5e 100644 --- a/apps/web/organisms/live/comment-post/public-post-switch.tsx +++ b/apps/web/organisms/live/comment-post/public-post-switch.tsx @@ -13,14 +13,14 @@ import { useDisclosure, VStack } from '@chakra-ui/react'; -import { FC, Fragment, useCallback, useRef } from 'react'; +import { FC, Fragment, useEffect, useRef } from 'react'; import { FormattedMessage, useIntl } from 'react-intl'; type Props = { acct?: string; hashtag?: string; isSignedIn: boolean; - enablePublish?: boolean; + enablePublish: boolean; toggleEnablePublish: () => void; }; @@ -41,14 +41,18 @@ export const PublicPostSwitch: FC = ({ : 'live.comment-post.publish.tooltip.disabled' : 'live.comment-post.publish.tooltip.disabled-in-live'; - const handleSwitch = useCallback(() => { - toggleEnablePublish(); + useEffect(() => { + if (!isFirstOpenedRef.current && hashtag && enablePublish && isSignedIn) { + const timeoutId = setTimeout(() => { + isFirstOpenedRef.current = true; + onOpen(); + }, 1000); - if (!isFirstOpenedRef.current) { - isFirstOpenedRef.current = true; - onOpen(); + return () => { + clearTimeout(timeoutId); + }; } - }, [toggleEnablePublish, onOpen]); + }, [onOpen, hashtag, enablePublish, isSignedIn]); return ( @@ -71,8 +75,8 @@ export const PublicPostSwitch: FC = ({ @@ -89,7 +93,7 @@ export const PublicPostSwitch: FC = ({ - + @@ -100,6 +104,10 @@ export const PublicPostSwitch: FC = ({ values={{ acct: acct || '', hashtag }} /> + + + +