From 6802678d51b5ee18ebf8e161268b1ad114f8798b Mon Sep 17 00:00:00 2001 From: Daniel Mizerski Date: Sun, 27 Feb 2022 18:13:57 +0100 Subject: [PATCH] (feature) ScoreSaber integration --- docs/content-security-policy.md | 43 +-- docs/verification.md | 351 ++++++++++-------- src/App.tsx | 3 + .../config/appConfigurationFromString.ts | 1 + .../broadcasterConfigFromString.ts | 1 + .../extractScoreSaberConfig.ts | 2 + .../useTwitchExtConfigurationOnChanged.ts | 4 +- src/common/utils/defaults.ts | 2 +- .../ScoreSaberBar/ScoreSaberBar.tsx | 15 +- .../BroadcasterConfigPage.tsx | 88 ++++- 10 files changed, 310 insertions(+), 200 deletions(-) diff --git a/docs/content-security-policy.md b/docs/content-security-policy.md index 465df63..bb0080a 100644 --- a/docs/content-security-policy.md +++ b/docs/content-security-policy.md @@ -4,39 +4,40 @@ Configuration targets: Redirection targets: -* https://beatsaver.com -* https://beatfollower.com -* https://github.com -* https://flaticon.com -* https://icon-icons.com -* https://iconfinder.com -* https://loading.io -* https://kindpng.com -* https://pngarea.com -* https://i.giphy.com +- https://beatsaver.com +- https://beatfollower.com +- https://github.com +- https://flaticon.com +- https://icon-icons.com +- https://iconfinder.com +- https://loading.io +- https://kindpng.com +- https://pngarea.com +- https://i.giphy.com https://beatsaver.com,https://beatfollower.com,https://github.com,https://flaticon.com,https://icon-icons.com,https://iconfinder.com,https://loading.io,https://kindpng.com,https://pngarea.com,https://i.giphy.com Image targets: -* https://cdn.beatmaps.io/ -* https://cdn.beatsaver.com/ -* https://*.cdn.beatsaver.com/ -* https://i.giphy.com +- https://cdn.beatmaps.io/ +- https://cdn.beatsaver.com/ +- https://\*.cdn.beatsaver.com/ +- https://i.giphy.com +- https://new.scoresaber.com -https://cdn.beatmaps.io/,https://cdn.beatsaver.com/,https://*.cdn.beatsaver.com/,https://i.giphy.com +https://cdn.beatmaps.io/,https://cdn.beatsaver.com/,https://*.cdn.beatsaver.com/,https://i.giphy.com,https://new.scoresaber.com Media targets: -* https://i.giphy.com +- https://i.giphy.com https://i.giphy.com API targets: -* https://api.twitch.tv -* https://api.beatsaver.com -* https://api.beatfollower.com - -https://api.twitch.tv,https://api.beatsaver.com,https://api.beatfollower.com +- https://api.twitch.tv +- https://api.beatsaver.com +- https://api.beatfollower.com +- https://new.scoresaber.com +https://api.twitch.tv,https://api.beatsaver.com,https://api.beatfollower.com,https://new.scoresaber.com diff --git a/docs/verification.md b/docs/verification.md index 1387394..6285a1b 100644 --- a/docs/verification.md +++ b/docs/verification.md @@ -4,16 +4,18 @@ URL of the channel: https://www.twitch.tv/danielduel URL of repository: + > https://github.com/Duelsik/beatsaber-request-ui -I am tagging versions, so if you want to review version x.y.z go to +> I am tagging versions, so if you want to review version x.y.z go to > https://github.com/Duelsik/beatsaber-request-ui/tree/x.y.z -like, when you are reviewing version 0.0.4 you can use +> like, when you are reviewing version 0.0.4 you can use > https://github.com/Duelsik/beatsaber-request-ui/tree/0.0.4 After fetching code from the repo you can just `npm install && npm run build` in order to get built extension :) Also! You can get latest formatted version of this file on + > https://github.com/Duelsik/beatsaber-request-ui/blob/master/docs/verification.md Table of contents: @@ -28,168 +30,189 @@ Table of contents: 0. Changelog 0.0.10: -* 4 September 2021 - * (tech) Clean info page boilerplate - * (tech) Exclude UnexpandedApp as separate component and generalize wrapWith -* 5 September 2021 - * (tech) Refine typings -* 7 September 2021 - * (tech) Rewrite app start and replace rxjs with mostjs -* 13 October 2021 - * (feature) Add footer and ScoreSaber bar - * (feature) Add ColorPicker to config page [@cutler7] -* 26 February 2022 - * (fix) Change CSP and BeatSaver endpoints to use api subdomain [@zaourzag] - * (fix) Layout issue without footer - * (fix) Remove delay from color picker input - -0.0.9 (hotfix in the middle of 0.0.10 timeline): -* 6 February 2022 - * (docs) Add CSP policy document - -0.0.8: -* 13 August 2021 - * (docs) Bump up version - * (feature) Ask user if they want to visit beatsaver page of map -* 21 August 2021 - * (feature) Redesign and refactor config page - * (docs) Update documentation -* 1 September 2021 - * (fix) Redact config page - * (feature) Tell the streamer that config is alright - * (docs) Update docs - * (feature) Reposition inactive bubble and fix rotations - * (fix) Reposition close button and fix bubble ratios - * (fix) Direct external links to _blank - * (tech) Clean build warns - * (docs) Update twitch extension page -Special thanks: -Thanks to ttv/acerolavr for helping me with my bad english. - -0.0.7 (not published, failed to verify because TVT): -* 10 August 2021 - * (feature) Redesign result rows - * (fix) Remove blue overlay onClick on webkits - * (docs) Change version and remove rusher release notice - * (tech) Cleanup code - * (fix) Fix config-related bug and modify bubble behavior -* 11 August 2021 - * (feature) Upgrade image loading - * (fix) Animate song list backgrounds and improve codestyle -* 12 August 2021 - * (fix) Fix pointer events on background image - * (tech) Exclude close button as a component - * (feature) Improve feeling of copy-pasting - * (docs) Add translations - * (docs) Update docs -Special thanks: -Thanks to ttv/acerolavr for spotting some bugs in this version. - -0.0.6: (already verified) -* 6 July 2021 - * (tech) Bump up version - * (tech) Push tools directory to repo -* 7 July 2021 - * (tech) Reduce css and include @types/twitch-ext -* 8 July 2021 - * (tech) Rewrite LayoutRow - * (tech) Move pages to pages folder and create BodyWithNavigation layout - * (tech) Refactor app wrappers/containers -* 9 July 2021 - * (feature) Update infopage -* 10 July 2021 - * (feature) Improve and redesign search input - * (fix) Style post-copy button on search item - * (fix) Fix copy button dimensions with longer translations - * (docs) Redesign base templates on figma - * (feature) Redesign and improve code quality on search list item - * (tech) Export SearchListItemDetails as a component - * (feature) Show available difficulties per map - * (fix) Fix overflow issue with difficulties - * (fix) Fix wrapping issue on search item details - * (tech) Exclude SearchListItem-related code as components - * (fix) Redesign after reviewing viewports -* 11 July 2021 - * (tech) Refactor of SongItem and SongList to make app ready for more datasources - * (feature) Add initial beatfollower integration - * (feature) Improve beatfollower integration UI - * (fix) Update ranked map list -* 23 July 2021 - * (feature) Redesign navigation bar -* 24 July 2021 - * (fix) Add pressed state on navigation items - * (fix) Add config datasource and comment out 3rd party streamers -* 26 July 2021 - * (feature) Use pagination on resources - * (docs) Update changelog -* 9 August 2021 - * (feature) Use new beatsaver api - * (docs) Add information about rushed release - * (fix) Fix pagination styling - * (fix) Fix overflow issue on mobile - -0.0.5: (already verified) -* 24 May 2021 - * (feature) Add a language selector - * (docs) Clean this (`verification.md`) file -* 31 May 2021 - * (docs) gitignore tools and add note about tagged versions - * (feature) Add an option to use extension as a panel - * (fix) Redesign clear button cross -* 2 June 2021 - * (docs) Add scripts and form cache to reduce work with sending code -* 3 June 2021 - * (feature) Don't render anything if stream category isn't BeatSaber (fullvideo-only) -* 4 June 2021 - * (feature) Make inactive bubble position configurable by the streamer - * (dev) Configure proxies - * (docs) Reformat verification doc to be nicely formatted (at least changelog section) - * (fix) Fix api.twitch.tv calls - * (fix) Fix bottom positioning to be left - * (feature) Fetch ranked maps (local json) and mark ranked maps - * (fix) Tweaks to the UI - -0.0.4: -* 14 May 2021 - * (fix) Hide autogenerated maps from search results -* 22 May 2021 - * Initialize internationalization - * (fix) Change button style when hovering over search and copy button - * Minor refactor of button feel - * (tech) Stabilize return types - * Add autofocus on searchbar input - * Add clear button to searchbar input -* 23 May 2021 - * Update page meta - -0.0.3: (already verified) -* 26 March 2021: - * Switch app to typescript - * Use prettier - * Use eslint - * Don't offer automatically generated maps in the results (for now, will add optional checkbox in future) - * Typed common response data from beatsaver - * Don't render big panel at start, just a bubble with animation and a little tooltip -* 08 May 2021: - * Finish codesplit to config, mobile and fullvideo extension (config and mobile are only for test) - * Reformat project - * Fix prettier config - * Update docs about functions - -0.0.2: (already verified) -* 22 March 2021: - * Replace "command" (cta) tooltip with the copy button - * Fix partial-pixel component position glitches - * Change extension name to "Beatsaber Request UI" (the extension page, not code) - * Add sections in the header - * Add Search section leading to the search - * Add Info section leading to the information page (internal - with version and link to the repository) - * Make search section to be open by default - * Add information page with links to the extension page, this repo issue tracker, link leading to the repo and the actual version of this extension - -0.0.1: (already verified) -* 18 March 2021 - * Add expand/unexpand and searching functionality + +- 4 September 2021 + - (tech) Clean info page boilerplate + - (tech) Exclude UnexpandedApp as separate component and generalize wrapWith +- 5 September 2021 + - (tech) Refine typings +- 7 September 2021 + - (tech) Rewrite app start and replace rxjs with mostjs +- 13 October 2021 + - (feature) Add footer and ScoreSaber bar + - (feature) Add ColorPicker to config page [@cutler7] +- 26 February 2022 + - (fix) Change CSP and BeatSaver endpoints to use api subdomain [@zaourzag] + - (fix) Layout issue without footer + - (fix) Remove delay from color picker input +- 27 February 2022 + + - (feature) ScoreSaber integration + + 0.0.9 (hotfix in the middle of 0.0.10 timeline): + +- 6 February 2022 + + - (docs) Add CSP policy document + + 0.0.8: + +- 13 August 2021 + - (docs) Bump up version + - (feature) Ask user if they want to visit beatsaver page of map +- 21 August 2021 + - (feature) Redesign and refactor config page + - (docs) Update documentation +- 1 September 2021 + + - (fix) Redact config page + - (feature) Tell the streamer that config is alright + - (docs) Update docs + - (feature) Reposition inactive bubble and fix rotations + - (fix) Reposition close button and fix bubble ratios + - (fix) Direct external links to \_blank + - (tech) Clean build warns + - (docs) Update twitch extension page + Special thanks: + Thanks to ttv/acerolavr for helping me with my bad english. + + 0.0.7 (not published, failed to verify because TVT): + +- 10 August 2021 + - (feature) Redesign result rows + - (fix) Remove blue overlay onClick on webkits + - (docs) Change version and remove rusher release notice + - (tech) Cleanup code + - (fix) Fix config-related bug and modify bubble behavior +- 11 August 2021 + - (feature) Upgrade image loading + - (fix) Animate song list backgrounds and improve codestyle +- 12 August 2021 + + - (fix) Fix pointer events on background image + - (tech) Exclude close button as a component + - (feature) Improve feeling of copy-pasting + - (docs) Add translations + - (docs) Update docs + Special thanks: + Thanks to ttv/acerolavr for spotting some bugs in this version. + + 0.0.6: (already verified) + +- 6 July 2021 + - (tech) Bump up version + - (tech) Push tools directory to repo +- 7 July 2021 + - (tech) Reduce css and include @types/twitch-ext +- 8 July 2021 + - (tech) Rewrite LayoutRow + - (tech) Move pages to pages folder and create BodyWithNavigation layout + - (tech) Refactor app wrappers/containers +- 9 July 2021 + - (feature) Update infopage +- 10 July 2021 + - (feature) Improve and redesign search input + - (fix) Style post-copy button on search item + - (fix) Fix copy button dimensions with longer translations + - (docs) Redesign base templates on figma + - (feature) Redesign and improve code quality on search list item + - (tech) Export SearchListItemDetails as a component + - (feature) Show available difficulties per map + - (fix) Fix overflow issue with difficulties + - (fix) Fix wrapping issue on search item details + - (tech) Exclude SearchListItem-related code as components + - (fix) Redesign after reviewing viewports +- 11 July 2021 + - (tech) Refactor of SongItem and SongList to make app ready for more datasources + - (feature) Add initial beatfollower integration + - (feature) Improve beatfollower integration UI + - (fix) Update ranked map list +- 23 July 2021 + - (feature) Redesign navigation bar +- 24 July 2021 + - (fix) Add pressed state on navigation items + - (fix) Add config datasource and comment out 3rd party streamers +- 26 July 2021 + - (feature) Use pagination on resources + - (docs) Update changelog +- 9 August 2021 + + - (feature) Use new beatsaver api + - (docs) Add information about rushed release + - (fix) Fix pagination styling + - (fix) Fix overflow issue on mobile + + 0.0.5: (already verified) + +- 24 May 2021 + - (feature) Add a language selector + - (docs) Clean this (`verification.md`) file +- 31 May 2021 + - (docs) gitignore tools and add note about tagged versions + - (feature) Add an option to use extension as a panel + - (fix) Redesign clear button cross +- 2 June 2021 + - (docs) Add scripts and form cache to reduce work with sending code +- 3 June 2021 + - (feature) Don't render anything if stream category isn't BeatSaber (fullvideo-only) +- 4 June 2021 + + - (feature) Make inactive bubble position configurable by the streamer + - (dev) Configure proxies + - (docs) Reformat verification doc to be nicely formatted (at least changelog section) + - (fix) Fix api.twitch.tv calls + - (fix) Fix bottom positioning to be left + - (feature) Fetch ranked maps (local json) and mark ranked maps + - (fix) Tweaks to the UI + + 0.0.4: + +- 14 May 2021 + - (fix) Hide autogenerated maps from search results +- 22 May 2021 + - Initialize internationalization + - (fix) Change button style when hovering over search and copy button + - Minor refactor of button feel + - (tech) Stabilize return types + - Add autofocus on searchbar input + - Add clear button to searchbar input +- 23 May 2021 + + - Update page meta + + 0.0.3: (already verified) + +- 26 March 2021: + - Switch app to typescript + - Use prettier + - Use eslint + - Don't offer automatically generated maps in the results (for now, will add optional checkbox in future) + - Typed common response data from beatsaver + - Don't render big panel at start, just a bubble with animation and a little tooltip +- 08 May 2021: + + - Finish codesplit to config, mobile and fullvideo extension (config and mobile are only for test) + - Reformat project + - Fix prettier config + - Update docs about functions + + 0.0.2: (already verified) + +- 22 March 2021: + + - Replace "command" (cta) tooltip with the copy button + - Fix partial-pixel component position glitches + - Change extension name to "Beatsaber Request UI" (the extension page, not code) + - Add sections in the header + - Add Search section leading to the search + - Add Info section leading to the information page (internal - with version and link to the repository) + - Make search section to be open by default + - Add information page with links to the extension page, this repo issue tracker, link leading to the repo and the actual version of this extension + + 0.0.1: (already verified) + +- 18 March 2021 + - Add expand/unexpand and searching functionality 1. Motivation diff --git a/src/App.tsx b/src/App.tsx index 8816495..f2b8572 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -53,6 +53,9 @@ const MainApp = ({ togglePanel }: MainAppProps): JSX.Element => { const scoreSaberConfig = configuration?.broadcaster.scoreSaber || null; const shouldRenderFooter = !!scoreSaberConfig; + console.log(configuration?.broadcaster); + console.log("Should render footer: " + shouldRenderFooter); + return ( diff --git a/src/common/config/appConfigurationFromString.ts b/src/common/config/appConfigurationFromString.ts index 28b13f9..557d87f 100644 --- a/src/common/config/appConfigurationFromString.ts +++ b/src/common/config/appConfigurationFromString.ts @@ -6,6 +6,7 @@ function appConfigurationFromStrings( developerString: string, globalString: string ): AppConfiguration { + console.log("AppConfiguration: " + broadcasterString); return { broadcaster: broadcasterConfigFromString(broadcasterString), developer: null, diff --git a/src/common/config/broadcasterConfig/broadcasterConfigFromString.ts b/src/common/config/broadcasterConfig/broadcasterConfigFromString.ts index 62603ac..2273520 100644 --- a/src/common/config/broadcasterConfig/broadcasterConfigFromString.ts +++ b/src/common/config/broadcasterConfig/broadcasterConfigFromString.ts @@ -3,6 +3,7 @@ import { extractPanelConfig } from "./extractPanelConfig"; import { extractScoreSaberConfig } from "./extractScoreSaberConfig"; function broadcasterConfigFromString(broadcasterString: string): BroadcasterConfiguration { + console.log("Broadcaster string: " + broadcasterString); return { panelPosition: extractPanelConfig(broadcasterString), scoreSaber: extractScoreSaberConfig(broadcasterString) diff --git a/src/common/config/broadcasterConfig/extractScoreSaberConfig.ts b/src/common/config/broadcasterConfig/extractScoreSaberConfig.ts index 7d9de7f..4527213 100644 --- a/src/common/config/broadcasterConfig/extractScoreSaberConfig.ts +++ b/src/common/config/broadcasterConfig/extractScoreSaberConfig.ts @@ -2,6 +2,8 @@ import { BroadcasterConfiguration } from "./BroadcasterConfiguration"; function extractScoreSaberConfig(broadcasterConfigString: string): BroadcasterConfiguration.ScoreSaber | null { const scoreSaberConfig = broadcasterConfigString.split(";").find((part) => part.startsWith("ss://")); + console.log("Extract SS config: " + broadcasterConfigString); + console.log("Extract SS config: " + scoreSaberConfig); if (!scoreSaberConfig) { return null; diff --git a/src/common/hooks/useTwitchExtConfigurationOnChanged.ts b/src/common/hooks/useTwitchExtConfigurationOnChanged.ts index 5003163..c43d530 100644 --- a/src/common/hooks/useTwitchExtConfigurationOnChanged.ts +++ b/src/common/hooks/useTwitchExtConfigurationOnChanged.ts @@ -17,12 +17,14 @@ function useTwitchExtConfigurationOnChanged() { if (isLocalhost) { // this has to be delayed setTimeout(() => { - handler(appConfigurationFromStrings("overlay|topLeft;ss://76561198023909718", "", "")); + // handler(appConfigurationFromStrings("overlay|topLeft;ss://76561198023909718", "", "")); // handler(appConfigurationFromStrings("overlay|topLeft;", "", "")); + handler(appConfigurationFromStrings("panel;ss://76561198023909718", "", "")); }, 0); } Twitch.ext.configuration.onChanged(() => { + console.log("Broadcaster content: " + Twitch.ext.configuration.broadcaster?.content); handler( appConfigurationFromStrings( stringOrDefault(Twitch.ext.configuration.broadcaster?.content, ""), diff --git a/src/common/utils/defaults.ts b/src/common/utils/defaults.ts index ad84236..7a23c6c 100644 --- a/src/common/utils/defaults.ts +++ b/src/common/utils/defaults.ts @@ -1,6 +1,6 @@ const numberOrDefault = (something: unknown, def: number): number => isNaN(Number(something)) ? def : Number(something); const stringOrDefault = (something: unknown, def: string): string => - typeof something === "string" ? def : String(something); + typeof something === "string" ? String(something) : def; export { numberOrDefault, stringOrDefault }; diff --git a/src/components/ScoreSaberBar/ScoreSaberBar.tsx b/src/components/ScoreSaberBar/ScoreSaberBar.tsx index 2733147..4e2ae03 100644 --- a/src/components/ScoreSaberBar/ScoreSaberBar.tsx +++ b/src/components/ScoreSaberBar/ScoreSaberBar.tsx @@ -10,6 +10,7 @@ import { Button } from "../Buttons/Button"; type ScoreSaberBarProps = { scoreSaberId: string; + withoutReload?: boolean; }; const ScoreSaberBarWrapper = styled.div` @@ -54,7 +55,7 @@ const ScoreSaberBarPlayerActionContainer = styled.div` const ScoreSaberBarPlayerReload = styled(Button)``; // https://scoresaber.com/imports/images/usr-avatars/76561198023909718.jpg -const ScoreSaberBar = ({ scoreSaberId }: ScoreSaberBarProps) => { +const ScoreSaberBar = ({ scoreSaberId, withoutReload }: ScoreSaberBarProps) => { const [scoreSaberBasicPlayerData, setScoreSaberBasicPlayerData] = React.useState(null); const [scoreSaberBasicPlayerData$, refetchScoreSaberBasicPlayerData] = useRefetchingData( @@ -78,13 +79,13 @@ const ScoreSaberBar = ({ scoreSaberId }: ScoreSaberBarProps) => { 🌎 {rank} ({emojiFlag} {countryRank}) - - {pp}pp - + {pp}pp - - Reload - + {!withoutReload && ( + + Reload + + )} ); }; diff --git a/src/pages/BroadcasterConfigPage/BroadcasterConfigPage.tsx b/src/pages/BroadcasterConfigPage/BroadcasterConfigPage.tsx index 7e5b0ae..06c4f81 100644 --- a/src/pages/BroadcasterConfigPage/BroadcasterConfigPage.tsx +++ b/src/pages/BroadcasterConfigPage/BroadcasterConfigPage.tsx @@ -1,14 +1,15 @@ // TODO - Rewrite this mess using some tool for such work // This file is one big "xD" - don't do forms like this kids -import React from "react"; +import React, { ChangeEvent } from "react"; import "../../App.css"; import styled from "styled-components"; import { LayoutRowBase } from "../../components/LayoutRow/LayoutRow"; import { GroupButton } from "../../components/Buttons/GroupButton"; -import { ButtonAsItem } from "../../components/Buttons/Button"; +import { ButtonAsItem, ButtonLink } from "../../components/Buttons/Button"; import { ColorSchemeAutoCreator } from "./ColorSchemeAutoCreator"; import { ColorSchemeManualCreator } from "./ColorSchemeManualCreator"; +import { ScoreSaberBar } from "../../components/ScoreSaberBar/ScoreSaberBar"; type TwitchConfigInputRowProps = { name: string; @@ -36,6 +37,10 @@ const FormRow = styled.div` } `; +const LinkLogo = styled.img` + height: 1rem; +`; + const SuccessRow = styled.div` width: 100%; display: flex; @@ -81,6 +86,7 @@ const TwitchConfigInputRow = ({ name, type, value, setValue }: TwitchConfigInput // console.log(Twitch.ext.configuration.set("broadcaster", "1", "somethingelse")); type SerializationData = { + scoreSaberId: string; colorScheme: null | "auto" | "manual"; panelOrOverlay: null | "panel" | "overlay"; overlayPlacement: null | "topLeft" | "bottomLeft" | "topRight" | "bottomRight" | "custom"; @@ -89,13 +95,19 @@ type SerializationData = { }; function serializeData({ + scoreSaberId, panelOrOverlay, overlayPlacement, customOverlayPlacementX, customOverlayPlacementY }: SerializationData) { + const separator = ";"; + const scoreSaberData = scoreSaberId ? `${separator}ss://${scoreSaberId}` : ""; + + const optionalFields = scoreSaberData; + if (panelOrOverlay === "panel") { - return "panel"; + return "panel" + optionalFields; } if (panelOrOverlay === "overlay" && overlayPlacement !== null) { @@ -106,11 +118,11 @@ function serializeData({ !isNaN(customOverlayPlacementX) && !isNaN(customOverlayPlacementY) ) { - return `overlay|custom|${customOverlayPlacementX}|${customOverlayPlacementY}`; + return `overlay|custom|${customOverlayPlacementX}|${customOverlayPlacementY}` + optionalFields; } return; } - return `overlay|${overlayPlacement}`; + return `overlay|${overlayPlacement}` + optionalFields; } return; @@ -118,6 +130,7 @@ function serializeData({ const _BroadcasterConfigPage = (): JSX.Element => { const [wasSubmitted, setWasSubmitted] = React.useState(false); + const [scoreSaberId, setScoreSaberId] = React.useState(""); const [panelOrOverlay, setPanelOrOverlay] = React.useState(null); const [overlayPlacement, setOverlayPlacement] = React.useState(null); const [colorScheme, setColorScheme] = React.useState(null); @@ -130,6 +143,7 @@ const _BroadcasterConfigPage = (): JSX.Element => { e.preventDefault(); const data = serializeData({ colorScheme, + scoreSaberId, panelOrOverlay, overlayPlacement, customOverlayPlacementX, @@ -143,7 +157,21 @@ const _BroadcasterConfigPage = (): JSX.Element => { setWasSubmitted(false); } }, - [panelOrOverlay, overlayPlacement, customOverlayPlacementX, customOverlayPlacementY] + [panelOrOverlay, overlayPlacement, customOverlayPlacementX, customOverlayPlacementY, scoreSaberId] + ); + + const scoreSaberLinkOnChange = React.useCallback( + (e: ChangeEvent) => { + const link = e.target.value; + const splitLink = link.split("/"); + const id = splitLink.find((part) => Number(part)); + if (!id) { + e.target.value = ""; + } else { + setScoreSaberId(id); + } + }, + [setScoreSaberId] ); return ( @@ -294,6 +322,54 @@ const _BroadcasterConfigPage = (): JSX.Element => { )} + + + Connect your ScoreSaber profile (optional) + + You can connect your ScoreSaber profile to display your stats in extensions footer. +
+ Find yourself on ScoreSaber and paste link to your profile, for example mine is +
+ +
+ Most likely your link will be pretty much the same, but the number at the end will differ. +
+ Handy link: +
+ + +   Go to ScoreSaber ranking search + +
+ Paste your link here: +
+ + {scoreSaberId && ( + <> + +
+ setScoreSaberId(""), + text: "Reset" + } + ]} + /> + + )} +
+
+
+ Define your own color scheme