diff --git a/src/components/Flex.tsx b/src/components/Flex.tsx index e2b9a71be..d86489f6c 100644 --- a/src/components/Flex.tsx +++ b/src/components/Flex.tsx @@ -21,16 +21,18 @@ import type { CSSProperties, HTMLAttributes } from "react"; export interface FlexProps extends HTMLAttributes { flexDirection?: CSSProperties["flexDirection"]; gap?: CSSProperties["gap"]; + alignContent?: CSSProperties["alignContent"]; justifyContent?: CSSProperties["justifyContent"]; alignItems?: CSSProperties["alignItems"]; flexWrap?: CSSProperties["flexWrap"]; } -export function Flex({ flexDirection, gap = "1em", justifyContent, alignItems, flexWrap, children, style, ...restProps }: FlexProps) { +export function Flex({ flexDirection, gap = "1em", alignContent, justifyContent, alignItems, flexWrap, children, style, ...restProps }: FlexProps) { style = { display: "flex", flexDirection, gap, + alignContent, justifyContent, alignItems, flexWrap, diff --git a/src/equicordplugins/whosWatching/index.tsx b/src/equicordplugins/whosWatching/index.tsx index c224a2da4..2412d1827 100644 --- a/src/equicordplugins/whosWatching/index.tsx +++ b/src/equicordplugins/whosWatching/index.tsx @@ -4,12 +4,14 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import "./styles.css"; + import { definePluginSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { Flex } from "@components/Flex"; import { Heading, HeadingSecondary } from "@components/Heading"; import { Paragraph } from "@components/Paragraph"; -import { EquicordDevs } from "@utils/constants"; +import { Devs, EquicordDevs } from "@utils/constants"; import { classNameFactory } from "@utils/css"; import { getIntlMessage, openUserProfile } from "@utils/discord"; import { Margins } from "@utils/margins"; @@ -25,12 +27,49 @@ interface WatchingProps { guildId?: string; } -const cl = classNameFactory("whosWatching-"); +const ApplicationStreamingStore = findStoreLazy("ApplicationStreamingStore"); +const UserSummaryItem = findComponentByCodeLazy("defaultRenderUser", "showDefaultAvatarsForNullUsers"); +const AvatarStyles = findCssClassesLazy("moreUsers", "clickableAvatar", "avatar"); +const cl = classNameFactory("vc-whos-watching-"); -function getUsername(user: any): string { +function getUsername(user: User): string { return RelationshipStore.getNickname(user.id) || user.globalName || user.username; } +function Watching({ userIds, guildId }: WatchingProps): JSX.Element { + let missingUsers = 0; + const users = userIds.map(id => UserStore.getUser(id)).filter(user => Boolean(user) ? true : (missingUsers += 1, false)); + return ( +
+ {userIds.length ? + ( +
+ {getIntlMessage("SPECTATORS", { numViewers: userIds.length })} + + {users.map(user => ( + + + {getUsername(user)} + + ))} + {missingUsers > 0 && + + {`+${getIntlMessage("NUM_USERS", { num: missingUsers })}`} + + } + +
+ ) + : ( + + No spectators + + ) + } +
+ ); +} + const settings = definePluginSettings({ showPanel: { description: "Show spectators under screenshare panel", @@ -40,53 +79,23 @@ const settings = definePluginSettings({ }, }); -function Watching({ userIds, guildId }: WatchingProps): JSX.Element { - // Missing Users happen when UserStore.getUser(id) returns null - // The client should automatically cache spectators, so this might not be possible but it's better to be sure just in case - let missingUsers = 0; - const users = userIds.map(id => UserStore.getUser(id)).filter(user => Boolean(user) ? true : (missingUsers += 1, false)); - return ( -
- {userIds.length ? - (<> - {getIntlMessage("SPECTATORS", { numViewers: userIds.length })} - - {users.map(user => ( - - - {getUsername(user)} - - ))} - {missingUsers > 0 && {`+${getIntlMessage("NUM_USERS", { num: missingUsers })}`}} - - ) - : (No spectators)} -
- ); -} - -const ApplicationStreamingStore = findStoreLazy("ApplicationStreamingStore"); - -const UserSummaryItem = findComponentByCodeLazy("defaultRenderUser", "showDefaultAvatarsForNullUsers"); -const AvatarStyles = findCssClassesLazy("moreUsers", "emptyUser", "avatarContainer", "clickableAvatar", "avatar"); - export default definePlugin({ name: "WhosWatching", description: "Hover over the screenshare icon to view what users are watching your stream", - authors: [EquicordDevs.Fres], + authors: [EquicordDevs.Fres, Devs.thororen], settings, patches: [ { find: ".Masks.STATUS_SCREENSHARE,width:32", replacement: { - match: /jsx\)\((\i\.\i),{mask:/, - replace: "jsx)($self.component({OriginalComponent:$1}),{mask:" + match: /\((\i\.\i)(?=,{mask:\i\.\i\.Masks\.STATUS_SCREENSHARE)/, + replace: "($self.component({OriginalComponent:$1})" } }, { find: "this.renderEmbeddedActivity()", replacement: { - match: /"div"(?=.{0,50}this.renderActions)/, + match: /"div"(?=.{0,40}?,this.renderActions\(\))/, replace: "$self.WrapperComponent" } } @@ -95,8 +104,8 @@ export default definePlugin({ const stream = useStateFromStores([ApplicationStreamingStore], () => ApplicationStreamingStore.getCurrentUserActiveStream()); if (!stream) return
{props.children}
; - const userIds: string[] = ApplicationStreamingStore.getViewerIds(stream); let missingUsers = 0; + const userIds: string[] = ApplicationStreamingStore.getViewerIds(stream); const users = userIds.map(id => UserStore.getUser(id)).filter(user => Boolean(user) ? true : (missingUsers += 1, false)); function renderMoreUsers(_label: string, count: number) { @@ -117,14 +126,14 @@ export default definePlugin({ } return ( - <> +
{props.children}
-
- +
+ {getIntlMessage("SPECTATORS", { numViewers: userIds.length })} {users.length ? - <> +
)} /> - - : No spectators +
+ : + No spectators + }
- +
); }), component: function ({ OriginalComponent }) { - return ErrorBoundary.wrap((props: any) => { - const stream = useStateFromStores( - [ApplicationStreamingStore], - () => ApplicationStreamingStore.getCurrentUserActiveStream() - ); + return ErrorBoundary.wrap(props => { + const stream = useStateFromStores([ApplicationStreamingStore], () => ApplicationStreamingStore.getCurrentUserActiveStream()); if (!stream) return null; + const viewers = ApplicationStreamingStore.getViewerIds(stream); return }> {({ onMouseEnter, onMouseLeave }) => ( diff --git a/src/equicordplugins/whosWatching/styles.css b/src/equicordplugins/whosWatching/styles.css new file mode 100644 index 000000000..66a965fb3 --- /dev/null +++ b/src/equicordplugins/whosWatching/styles.css @@ -0,0 +1,11 @@ +.vc-whos-watching-user-avatar { + border-radius: 8px; + width: 16px; + height: 16px; +} + +.vc-whos-watching-spectating-header { + margin-top: 8px; + margin-bottom: 0; + text-transform: uppercase; +} \ No newline at end of file