Merge branch 'dev' into translation
This commit is contained in:
commit
f0cbdfd689
9 changed files with 226 additions and 61 deletions
16
.github/workflows/reportBrokenPlugins.yml
vendored
16
.github/workflows/reportBrokenPlugins.yml
vendored
|
|
@ -28,12 +28,8 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
if: ${{ github.event_name == 'schedule' }}
|
|
||||||
with:
|
with:
|
||||||
ref: dev
|
ref: ${{ github.event_name == 'schedule' && 'dev' || github.ref }}
|
||||||
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v3 # Install pnpm using packageManager key in package.json
|
- uses: pnpm/action-setup@v3 # Install pnpm using packageManager key in package.json
|
||||||
|
|
||||||
|
|
@ -45,13 +41,7 @@ jobs:
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
pnpm install --frozen-lockfile
|
pnpm install --frozen-lockfile --prefer-offline
|
||||||
|
|
||||||
- name: Install Google Chrome
|
|
||||||
id: setup-chrome
|
|
||||||
uses: browser-actions/setup-chrome@82b9ce628cc5595478a9ebadc480958a36457dc2
|
|
||||||
with:
|
|
||||||
chrome-version: stable
|
|
||||||
|
|
||||||
- name: Build Equicord Reporter Version
|
- name: Build Equicord Reporter Version
|
||||||
run: pnpm buildReporter
|
run: pnpm buildReporter
|
||||||
|
|
@ -60,7 +50,7 @@ jobs:
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
run: |
|
run: |
|
||||||
export PATH="$PWD/node_modules/.bin:$PATH"
|
export PATH="$PWD/node_modules/.bin:$PATH"
|
||||||
export CHROMIUM_BIN=${{ steps.setup-chrome.outputs.chrome-path }}
|
export CHROMIUM_BIN=/usr/bin/google-chrome
|
||||||
|
|
||||||
esbuild scripts/generateReport.ts > dist/report.mjs
|
esbuild scripts/generateReport.ts > dist/report.mjs
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,12 +37,6 @@ export const settings = definePluginSettings({
|
||||||
type: OptionType.COMPONENT,
|
type: OptionType.COMPONENT,
|
||||||
component: () => SectionSeparator(t("equicord.declutter.headers.userProfile")),
|
component: () => SectionSeparator(t("equicord.declutter.headers.userProfile")),
|
||||||
},
|
},
|
||||||
removeAvatarDecoration: {
|
|
||||||
type: OptionType.BOOLEAN,
|
|
||||||
description: t("equicord.declutter.settings.removeAvatarDecoration"),
|
|
||||||
default: true,
|
|
||||||
restartNeeded: true,
|
|
||||||
},
|
|
||||||
removeNameplate: {
|
removeNameplate: {
|
||||||
type: OptionType.BOOLEAN,
|
type: OptionType.BOOLEAN,
|
||||||
description: t("equicord.declutter.settings.removeNameplate"),
|
description: t("equicord.declutter.settings.removeNameplate"),
|
||||||
|
|
@ -152,15 +146,6 @@ export default definePlugin({
|
||||||
authors: [EquicordDevs.Leon135, Devs.prism, Devs.Kyuuhachi],
|
authors: [EquicordDevs.Leon135, Devs.prism, Devs.Kyuuhachi],
|
||||||
settings,
|
settings,
|
||||||
patches: [
|
patches: [
|
||||||
{
|
|
||||||
// Avatar decoration
|
|
||||||
find: "getAvatarDecorationURL:",
|
|
||||||
replacement: {
|
|
||||||
match: /(?<=function \i\((\i)\){)(?=.{0,150}let{avatarDecoration)/,
|
|
||||||
replace: "$&return null;"
|
|
||||||
},
|
|
||||||
predicate: () => settings.store.removeAvatarDecoration,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
// Nameplate
|
// Nameplate
|
||||||
find: "#{intl::AVATAR_MALLOW}",
|
find: "#{intl::AVATAR_MALLOW}",
|
||||||
|
|
|
||||||
|
|
@ -6,15 +6,14 @@
|
||||||
|
|
||||||
import "./style.css";
|
import "./style.css";
|
||||||
|
|
||||||
import { definePluginSettings } from "@api/Settings";
|
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { EquicordDevs } from "@utils/constants";
|
import { EquicordDevs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
|
|
||||||
import { useAuthorizationStore } from "./lib/stores/AuthorizationStore";
|
import { useAuthorizationStore } from "./lib/stores/AuthorizationStore";
|
||||||
import { useSongStore } from "./lib/stores/SongStore";
|
import { useSongStore } from "./lib/stores/SongStore";
|
||||||
import { Native } from "./service";
|
import { Native } from "./service";
|
||||||
import Settings from "./ui/settings";
|
import settings from "./settings";
|
||||||
import ProfileSongs from "./ui/songs/ProfileSongs";
|
import ProfileSongs from "./ui/songs/ProfileSongs";
|
||||||
import WidgetSongs from "./ui/songs/WidgetSongs";
|
import WidgetSongs from "./ui/songs/WidgetSongs";
|
||||||
|
|
||||||
|
|
@ -22,12 +21,7 @@ export default definePlugin({
|
||||||
name: "SongSpotlight",
|
name: "SongSpotlight",
|
||||||
description: "Show off songs on your profile",
|
description: "Show off songs on your profile",
|
||||||
authors: [EquicordDevs.nexpid],
|
authors: [EquicordDevs.nexpid],
|
||||||
settings: definePluginSettings({
|
settings,
|
||||||
manager: {
|
|
||||||
type: OptionType.COMPONENT,
|
|
||||||
component: () => <Settings />,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
patches: [
|
patches: [
|
||||||
// Personal profile popout
|
// Personal profile popout
|
||||||
{
|
{
|
||||||
|
|
@ -50,7 +44,7 @@ export default definePlugin({
|
||||||
find: ".SIDEBAR}),nicknameIcons:",
|
find: ".SIDEBAR}),nicknameIcons:",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /{userId:(\i)\.id}\)}\).{0,100}]}\)(?=\]\}\))/,
|
match: /{userId:(\i)\.id}\)}\).{0,100}]}\)(?=\]\}\))/,
|
||||||
replace: "$&,$self.renderProfileSongs({userId:$1.id})",
|
replace: "$&,$self.renderProfileSongs({userId:$1.id,isSidebar:true})",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// Full profile modal sections (lazy loaded)
|
// Full profile modal sections (lazy loaded)
|
||||||
|
|
@ -58,14 +52,14 @@ export default definePlugin({
|
||||||
find: ".MUTUAL_GUILDS})),",
|
find: ".MUTUAL_GUILDS})),",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /(\i).push\({text.{0,50}}\);/,
|
match: /(\i).push\({text.{0,50}}\);/,
|
||||||
replace: "$&$1.push({text:\"Song Spotlight\",section:\"SONG_SPOTLIGHT\"});",
|
replace: '$&$1.push({text:"Song Spotlight",section:"SONG_SPOTLIGHT"});',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
find: ".hasUnsavedChanges()&&",
|
find: ".hasUnsavedChanges()&&",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /({user:(\i),.{0,80}return (\i===))/,
|
match: /({user:(\i),.{0,80}return (\i===))/,
|
||||||
replace: "$1\"SONG_SPOTLIGHT\"?$self.renderWidgetSongs({user:$2}):$3",
|
replace: '$1"SONG_SPOTLIGHT"?$self.renderWidgetSongs({user:$2}):$3',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
||||||
34
src/equicordplugins/songSpotlight.desktop/settings.tsx
Normal file
34
src/equicordplugins/songSpotlight.desktop/settings.tsx
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2026 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { definePluginSettings } from "@api/Settings";
|
||||||
|
import { makeRange, OptionType } from "@utils/types";
|
||||||
|
|
||||||
|
import Settings from "./ui/settings";
|
||||||
|
|
||||||
|
export default definePluginSettings({
|
||||||
|
collapseSongList: {
|
||||||
|
type: OptionType.BOOLEAN,
|
||||||
|
description: "Collapses the song list on user profiles to a button which opens a separate menu",
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
profileSongsLimit: {
|
||||||
|
type: OptionType.SLIDER,
|
||||||
|
description: "How many songs are shown when initially clicking on a user",
|
||||||
|
default: 6,
|
||||||
|
markers: makeRange(1, 6),
|
||||||
|
},
|
||||||
|
manager: {
|
||||||
|
type: OptionType.COMPONENT,
|
||||||
|
component: () => <Settings />,
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
profileSongsLimit: {
|
||||||
|
disabled() {
|
||||||
|
return this.store.collapseSongList;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
@ -23,7 +23,10 @@
|
||||||
-webkit-line-clamp: 1;
|
-webkit-line-clamp: 1;
|
||||||
line-clamp: 1;
|
line-clamp: 1;
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
|
min-width: 0;
|
||||||
|
max-width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* components */
|
/* components */
|
||||||
|
|
@ -137,13 +140,13 @@
|
||||||
--list-height: calc(var(--base-height) + 80px);
|
--list-height: calc(var(--base-height) + 80px);
|
||||||
--number-size: 32px;
|
--number-size: 32px;
|
||||||
|
|
||||||
padding: 8px;
|
display: flex;
|
||||||
gap: 12px;
|
flex-direction: column;
|
||||||
overflow: visible;
|
gap: 6px;
|
||||||
}
|
|
||||||
|
|
||||||
.user-profile-sidebar .vc-songspotlight-songs-container {
|
&.vc-songspotlight-songs-container-sidebar {
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.vc-songspotlight-songs-more {
|
.vc-songspotlight-songs-more {
|
||||||
|
|
@ -194,6 +197,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.user-profile-sidebar .vc-songspotlight-song-container {
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.user-profile-popout:not(.custom-user-profile-theme) .vc-songspotlight-song-container {
|
.user-profile-popout:not(.custom-user-profile-theme) .vc-songspotlight-song-container {
|
||||||
background: var(--opacity-16);
|
background: var(--opacity-16);
|
||||||
}
|
}
|
||||||
|
|
@ -211,7 +218,6 @@
|
||||||
grid-template-columns: 1fr auto;
|
grid-template-columns: 1fr auto;
|
||||||
grid-template-rows: 1fr auto;
|
grid-template-rows: 1fr auto;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
overflow: visible;
|
|
||||||
border-radius: inherit;
|
border-radius: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -220,7 +226,7 @@
|
||||||
grid-column: 1;
|
grid-column: 1;
|
||||||
grid-row: 1 / 3;
|
grid-row: 1 / 3;
|
||||||
border-radius: inherit;
|
border-radius: inherit;
|
||||||
overflow: visible;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vc-songspotlight-song-cover {
|
.vc-songspotlight-song-cover {
|
||||||
|
|
@ -232,7 +238,6 @@
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
box-shadow: 0 3px 12px 0 rgb(0 0 0 / 16%);
|
box-shadow: 0 3px 12px 0 rgb(0 0 0 / 16%);
|
||||||
transition: 0.18s transform;
|
transition: 0.18s transform;
|
||||||
overflow: visible;
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
transform: scale(1.03);
|
transform: scale(1.03);
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,14 @@ import { Tooltip } from "@webpack/common";
|
||||||
import { ComponentType, HTMLAttributes, JSX } from "react";
|
import { ComponentType, HTMLAttributes, JSX } from "react";
|
||||||
|
|
||||||
export const OverlayClasses = findCssClassesLazy("overlay", "inner", "outer");
|
export const OverlayClasses = findCssClassesLazy("overlay", "inner", "outer");
|
||||||
|
export const ContainerClasses = findCssClassesLazy(
|
||||||
|
"breadcrumb",
|
||||||
|
"innerContainer",
|
||||||
|
"icons",
|
||||||
|
"icon",
|
||||||
|
"displayCount",
|
||||||
|
"displayCountText",
|
||||||
|
);
|
||||||
export const CardClasses = findCssClassesLazy("card", "headerText", "headerContextMenu");
|
export const CardClasses = findCssClassesLazy("card", "headerText", "headerContextMenu");
|
||||||
export const WidgetClasses = findCssClassesLazy("tabPanelScroller", "tabListScroller");
|
export const WidgetClasses = findCssClassesLazy("tabPanelScroller", "tabListScroller");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2026 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { BaseText } from "@components/index";
|
||||||
|
import { Native } from "@equicordplugins/songSpotlight.desktop/service";
|
||||||
|
import { CardClasses, ContainerClasses, OverlayClasses, Spinner } from "@equicordplugins/songSpotlight.desktop/ui/common";
|
||||||
|
import { RenderSongInfo } from "@song-spotlight/api/handlers";
|
||||||
|
import { UserData } from "@song-spotlight/api/structs";
|
||||||
|
import { sid } from "@song-spotlight/api/util";
|
||||||
|
import { classes } from "@utils/index";
|
||||||
|
import {
|
||||||
|
SelectedChannelStore,
|
||||||
|
SelectedGuildStore,
|
||||||
|
useEffect,
|
||||||
|
useMemo,
|
||||||
|
UserProfileActions,
|
||||||
|
UserStore,
|
||||||
|
useState,
|
||||||
|
} from "@webpack/common";
|
||||||
|
|
||||||
|
import { ProfileSongsProps } from "./ProfileSongs";
|
||||||
|
|
||||||
|
const shownSongs = 4;
|
||||||
|
|
||||||
|
interface CollapsedProfileSongsProps extends ProfileSongsProps {
|
||||||
|
data?: UserData;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function CollapsedProfileSongs({ data, userId, isSidebar }: CollapsedProfileSongsProps) {
|
||||||
|
const [renders, setRenders] = useState(new Map<string, RenderSongInfo>());
|
||||||
|
const previews = useMemo(() => data?.slice(0, shownSongs), [data]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setRenders(new Map());
|
||||||
|
if (!previews) return;
|
||||||
|
|
||||||
|
for (const song of previews) {
|
||||||
|
Native.renderSong(song)
|
||||||
|
.catch(() => null)
|
||||||
|
.then(info => {
|
||||||
|
if (!info) return;
|
||||||
|
setRenders(renders => new Map(renders).set(sid(song), info));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [previews]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={ContainerClasses.breadcrumb}
|
||||||
|
aria-label="Song Spotlight"
|
||||||
|
role="button"
|
||||||
|
tabIndex={0}
|
||||||
|
onClick={() => {
|
||||||
|
const user = UserStore.getUser(userId);
|
||||||
|
if (!user) return;
|
||||||
|
|
||||||
|
const guildId = SelectedGuildStore.getGuildId();
|
||||||
|
UserProfileActions.openUserProfileModal({
|
||||||
|
userId,
|
||||||
|
guildId,
|
||||||
|
channelId: SelectedChannelStore.getChannelId(),
|
||||||
|
analyticsLocation: {
|
||||||
|
page: guildId ? "Guild Channel" : "DM Channel",
|
||||||
|
section: "Profile Popout",
|
||||||
|
},
|
||||||
|
tabSection: "SONG_SPOTLIGHT",
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className={classes(OverlayClasses.overlay, ContainerClasses.innerContainer, CardClasses.card)}>
|
||||||
|
<BaseText size={isSidebar ? "sm" : "xs"} weight="medium">Song Spotlight</BaseText>
|
||||||
|
<div className={ContainerClasses.icons}>
|
||||||
|
{previews && data
|
||||||
|
? previews.map((song, i) => {
|
||||||
|
const render = renders.get(sid(song));
|
||||||
|
const extra = i === shownSongs - 1 && data.length > shownSongs;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={ContainerClasses.icon} key={i}>
|
||||||
|
{render?.thumbnailUrl && (
|
||||||
|
<img
|
||||||
|
src={render.thumbnailUrl}
|
||||||
|
alt={render.label}
|
||||||
|
className={classes(extra && ContainerClasses.displayCount)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{extra && (
|
||||||
|
<div className={ContainerClasses.displayCountText}>
|
||||||
|
<BaseText size="xs" weight="medium">+{data.length - shownSongs}</BaseText>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
: <Spinner type={Spinner.Type.SPINNING_CIRCLE} />}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -7,10 +7,12 @@
|
||||||
import { BaseText } from "@components/BaseText";
|
import { BaseText } from "@components/BaseText";
|
||||||
import { Flex } from "@components/Flex";
|
import { Flex } from "@components/Flex";
|
||||||
import { LinkIcon, PencilIcon } from "@components/Icons";
|
import { LinkIcon, PencilIcon } from "@components/Icons";
|
||||||
|
import { Link } from "@components/Link";
|
||||||
import { listData } from "@equicordplugins/songSpotlight.desktop/lib/api";
|
import { listData } from "@equicordplugins/songSpotlight.desktop/lib/api";
|
||||||
import { useAuthorizationStore } from "@equicordplugins/songSpotlight.desktop/lib/stores/AuthorizationStore";
|
import { useAuthorizationStore } from "@equicordplugins/songSpotlight.desktop/lib/stores/AuthorizationStore";
|
||||||
import { useSongStore } from "@equicordplugins/songSpotlight.desktop/lib/stores/SongStore";
|
import { useSongStore } from "@equicordplugins/songSpotlight.desktop/lib/stores/SongStore";
|
||||||
import { cl } from "@equicordplugins/songSpotlight.desktop/lib/utils";
|
import { cl } from "@equicordplugins/songSpotlight.desktop/lib/utils";
|
||||||
|
import settings from "@equicordplugins/songSpotlight.desktop/settings";
|
||||||
import {
|
import {
|
||||||
CardClasses,
|
CardClasses,
|
||||||
MoreHorizontalIcon,
|
MoreHorizontalIcon,
|
||||||
|
|
@ -20,40 +22,75 @@ import {
|
||||||
import { openSettingsModal } from "@equicordplugins/songSpotlight.desktop/ui/settings";
|
import { openSettingsModal } from "@equicordplugins/songSpotlight.desktop/ui/settings";
|
||||||
import { sid } from "@song-spotlight/api/util";
|
import { sid } from "@song-spotlight/api/util";
|
||||||
import { copyWithToast } from "@utils/discord";
|
import { copyWithToast } from "@utils/discord";
|
||||||
import { classes } from "@utils/misc";
|
import { classes } from "@utils/index";
|
||||||
import { ContextMenuApi, FluxDispatcher, Menu, React, Tooltip, useEffect, UserStore, useState } from "@webpack/common";
|
import {
|
||||||
|
ContextMenuApi,
|
||||||
|
FluxDispatcher,
|
||||||
|
Menu,
|
||||||
|
React,
|
||||||
|
Tooltip,
|
||||||
|
useEffect,
|
||||||
|
useMemo,
|
||||||
|
UserStore,
|
||||||
|
useState,
|
||||||
|
} from "@webpack/common";
|
||||||
|
|
||||||
import Song from ".";
|
import Song from ".";
|
||||||
|
import CollapsedProfileSongs from "./CollapsedProfileSongs";
|
||||||
|
|
||||||
interface ProfileSongsProps {
|
export interface ProfileSongsProps {
|
||||||
userId: string;
|
userId: string;
|
||||||
|
isSidebar: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ProfileSongs({ userId }: ProfileSongsProps) {
|
export default function ProfileSongs({ userId, isSidebar }: ProfileSongsProps) {
|
||||||
const [failed, setFailed] = useState(false);
|
const [failed, setFailed] = useState(false);
|
||||||
const { isAuthorized } = useAuthorizationStore();
|
const { isAuthorized } = useAuthorizationStore();
|
||||||
const { users } = useSongStore();
|
const { users } = useSongStore();
|
||||||
|
const { profileSongsLimit, collapseSongList } = settings.use();
|
||||||
|
|
||||||
const data = users[userId]?.data, at = users[userId]?.at;
|
const data = users[userId]?.data;
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isAuthorized() && !data) listData(userId).catch(() => setFailed(true));
|
if (isAuthorized() && !data) listData(userId).catch(() => setFailed(true));
|
||||||
}, [isAuthorized()]);
|
}, [isAuthorized()]);
|
||||||
|
|
||||||
|
const [clamped, setClamped] = useState(true);
|
||||||
|
const clampedData = useMemo(() => data && (clamped ? data.slice(0, profileSongsLimit) : data), [
|
||||||
|
data,
|
||||||
|
clamped,
|
||||||
|
profileSongsLimit,
|
||||||
|
]);
|
||||||
|
|
||||||
const owned = UserStore.getCurrentUser().id === userId;
|
const owned = UserStore.getCurrentUser().id === userId;
|
||||||
|
|
||||||
if (isAuthorized() && !data && !failed) {
|
const pending = isAuthorized() && !clampedData && !data && !failed;
|
||||||
|
if (!pending && !clampedData?.[0]) return null;
|
||||||
|
|
||||||
|
if (collapseSongList) {
|
||||||
|
return (
|
||||||
|
<CollapsedProfileSongs
|
||||||
|
data={data}
|
||||||
|
userId={userId}
|
||||||
|
isSidebar={isSidebar}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
} else if (pending) {
|
||||||
return <Spinner type={Spinner.Type.WANDERING_CUBES} />;
|
return <Spinner type={Spinner.Type.WANDERING_CUBES} />;
|
||||||
} else if (!data?.[0]) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={classes(OverlayClasses.overlay, CardClasses.card, cl("songs-container"))}
|
className={classes(
|
||||||
|
isSidebar && OverlayClasses.overlay,
|
||||||
|
isSidebar && CardClasses.card,
|
||||||
|
cl("songs-container", isSidebar && "songs-container-sidebar"),
|
||||||
|
)}
|
||||||
key="song-spotlight-profile-songs"
|
key="song-spotlight-profile-songs"
|
||||||
>
|
>
|
||||||
<Flex justifyContent="space-between">
|
<Flex justifyContent="space-between">
|
||||||
<BaseText size="xs" weight="semibold" className={cl("header")}>Song Spotlight</BaseText>
|
<BaseText size="xs" weight={isSidebar ? "semibold" : "medium"} className={cl("header")}>
|
||||||
|
Song Spotlight
|
||||||
|
</BaseText>
|
||||||
<Tooltip text="More">
|
<Tooltip text="More">
|
||||||
{props => (
|
{props => (
|
||||||
<MoreHorizontalIcon
|
<MoreHorizontalIcon
|
||||||
|
|
@ -89,8 +126,17 @@ export default function ProfileSongs({ userId }: ProfileSongsProps) {
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex flexDirection="column" gap="6px">
|
<Flex flexDirection="column" gap="6px">
|
||||||
{data.map((song, i) => <Song owned={owned} song={song} index={i} key={sid(song)} />)}
|
{clampedData.map((song, i) => <Song owned={owned} song={song} index={i} key={sid(song)} />)}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
{clamped && data.length > profileSongsLimit && (
|
||||||
|
<Link
|
||||||
|
onClick={() => setClamped(false)}
|
||||||
|
>
|
||||||
|
<BaseText size="sm" weight="medium" className={cl("sub")} style={{ textAlign: "center" }}>
|
||||||
|
Show {data.length - profileSongsLimit} more
|
||||||
|
</BaseText>
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -187,7 +187,7 @@ function SongInfo({ owned, song, render, big }: SongInfoProps) {
|
||||||
icon={LinkIcon}
|
icon={LinkIcon}
|
||||||
action={() => copyWithToast(render.link)}
|
action={() => copyWithToast(render.link)}
|
||||||
/>
|
/>
|
||||||
{owned
|
{!owned
|
||||||
? (
|
? (
|
||||||
<Menu.MenuItem
|
<Menu.MenuItem
|
||||||
id="steal-song"
|
id="steal-song"
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue