diff --git a/i18n/en-US.json b/i18n/en-US.json index 520ea94ce..a576bb889 100644 --- a/i18n/en-US.json +++ b/i18n/en-US.json @@ -62,6 +62,9 @@ "REPLUGGED_PLUGIN": "Plugin", "REPLUGGED_PLUGINS": "Plugins", "REPLUGGED_QUICKCSS": "Quick CSS", + "REPLUGGED_QUICKCSS_CHANGES_APPLY": "Apply Changes", + "REPLUGGED_QUICKCSS_FOLDER_OPEN": "Open Quick CSS Folder", + "REPLUGGED_QUICKCSS_POPPED_OUT": "Quick CSS Editor has been popped out", "REPLUGGED_SETTINGS_ADVANCED_DESC": "Don't touch stuff in here if you don't know what you're doing. Unexpected things can happen to your cat.", "REPLUGGED_SETTINGS_BACKEND": "Backend URL", "REPLUGGED_SETTINGS_BACKEND_DESC": "URL used to fetch some assets and to query Replugged's REST API.", @@ -167,7 +170,6 @@ "REPLUGGED_LIST_RESULTS": "{count, plural, =1 {# match} other {# matches}}", "REPLUGGED_NO_ADDON_RESULTS": "No {type} matched your search.", "REPLUGGED_NO_ADDONS_INSTALLED": "No {type} installed.", - "REPLUGGED_QUICKCSS_CHANGES_APPLY": "Apply Changes", "REPLUGGED_SEARCH_FOR_ADDON": "Search for a {type}", "REPLUGGED_TOAST_ADDON_DISABLE_SUCCESS": "Disabled {name}", "REPLUGGED_TOAST_ADDON_ENABLE_SUCCESS": "Enabled {name}", @@ -189,7 +191,6 @@ "REPLUGGED_TOAST_INSTALLER_ADDON_INSTALL_SUCCESS": "{name} installed successfully.", "REPLUGGED_TOAST_INSTALLER_ADDON_FETCH_INFO_FAILED": "Failed to get info for addon.", "REPLUGGED_TOAST_INSTALLER_ADDON_CANCELED_INSTALL": "Install canceled.", - "REPLUGGED_QUICKCSS_FOLDER_OPEN": "Open Quick CSS Folder", "REPLUGGED_ADDON_AUTHORS_ONE": "by {author1}", "REPLUGGED_ADDON_AUTHORS_TWO": "by {author1} and {author2}", "REPLUGGED_ADDON_AUTHORS_THREE": "by {author1}, {author2}, and {author3}", diff --git a/src/renderer/coremods/settings/index.tsx b/src/renderer/coremods/settings/index.tsx index 080b9786b..306ef5b06 100644 --- a/src/renderer/coremods/settings/index.tsx +++ b/src/renderer/coremods/settings/index.tsx @@ -4,7 +4,7 @@ import { Injector } from "@replugged"; import { filters, waitForModule } from "src/renderer/modules/webpack"; import type { Section as SectionType } from "src/types/coremods/settings"; import { Divider, Header, Section, insertSections, settingsTools } from "./lib"; -import { General, Plugins, QuickCSS, Themes, Updater } from "./pages"; +import { General, Plugins, ConnectedQuickCSS, Themes, Updater } from "./pages"; const injector = new Injector(); @@ -47,7 +47,7 @@ export function start(): void { Section({ name: "rp-quickcss", label: () => Messages.REPLUGGED_QUICKCSS, - elem: QuickCSS, + elem: ConnectedQuickCSS as unknown as (args: unknown) => React.ReactElement, }), Section({ name: "rp-plugins", diff --git a/src/renderer/coremods/settings/pages/QuickCSS.css b/src/renderer/coremods/settings/pages/QuickCSS.css index 44cdc41c7..cd121cef7 100644 --- a/src/renderer/coremods/settings/pages/QuickCSS.css +++ b/src/renderer/coremods/settings/pages/QuickCSS.css @@ -1,3 +1,11 @@ +#replugged-quickcss-wrapper { + color: var(--text-normal); +} + +#replugged-quickcss-wrapper[data-popout=true] { + width: 100% !important; +} + #replugged-quickcss-wrapper .cm-editor { border: 1px solid transparent; border-radius: 4px; @@ -28,6 +36,11 @@ max-height: 75vh; } +/* TODO: Fix the height not working in popout */ +#replugged-quickcss-wrapper[data-popout=true] .cm-scroller { + max-height: 95vh; +} + #replugged-quickcss-wrapper .cm-scroller::-webkit-scrollbar { width: 10px; height: 0px; @@ -38,3 +51,24 @@ background-color: var(--scrollbar-thin-thumb); border-radius: 10px; } + +.replugged-quickcss-header { + height: 30px; + color: var(--text-normal); + display: flex; + align-items: center; + justify-content: space-between; + font-size: 14px; + padding: 7px 15px; + background-color: var(--background-secondary); +} +/* Why do these have to be different in different windows.. */ +#replugged-quickcss-wrapper[data-popout=true] .replugged-quickcss-header { + height: 16px; +} + +.replugged-quickcss-header span, +.replugged-quickcss-header svg { + width: 100%; + height: 100%; +} diff --git a/src/renderer/coremods/settings/pages/QuickCSS.tsx b/src/renderer/coremods/settings/pages/QuickCSS.tsx index 59d96e0ce..a06f0c7b8 100644 --- a/src/renderer/coremods/settings/pages/QuickCSS.tsx +++ b/src/renderer/coremods/settings/pages/QuickCSS.tsx @@ -1,13 +1,17 @@ -import { React, toast } from "@common"; +import { React, flux, toast } from "@common"; import { Messages } from "@common/i18n"; import { EditorView, basicSetup } from "codemirror"; import { EditorState } from "@codemirror/state"; import { css } from "@codemirror/lang-css"; import { githubDark, githubLight } from "./codemirror-github"; import { webpack } from "@replugged"; -import { Button, Divider, Flex, Text } from "@components"; +import { Button, ButtonItem, Divider, Flex, Text, Tooltip } from "@components"; import "./QuickCSS.css"; import { generalSettings } from "./General"; +import { ReactComponent } from "src/types"; +import { Store } from "@common/flux"; + +const { connectStores } = flux; interface UseCodeMirrorOptions { value?: string; @@ -22,6 +26,30 @@ type ThemeModule = { removeChangeListener: (listener: () => unknown) => unknown; }; +const PopoutModule = await webpack.waitForModule( + webpack.filters.bySource('type:"POPOUT_WINDOW_OPEN"'), +); +// eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style +const openPopout = webpack.getFunctionBySource(PopoutModule, "POPOUT_WINDOW_OPEN") as ( + key: string, + render: ReactComponent, + features: Record, +) => void; +// eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style +const closePopout = webpack.getFunctionBySource(PopoutModule, "POPOUT_WINDOW_CLOSE") as ( + key: string, +) => void; +// eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style +const PopoutWindowStore = webpack.getByStoreName("PopoutWindowStore") as Store & { + getWindow: (key: string) => Window; + getWindowOpen: (key: string) => boolean; +}; + +// eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style +const DnDProvider = webpack.getBySource( + ".EMBEDDED_ACTIVITIES_ARE_YOU_SURE_WANT_TO_LEAVE", +) as ReactComponent; + function useTheme(): "light" | "dark" { const [theme, setTheme] = React.useState<"light" | "dark">("dark"); @@ -110,7 +138,7 @@ function useCodeMirror({ value: initialValueParam, onChange, container }: UseCod return { value, setValue: customSetValue }; } -export const QuickCSS = (): React.ReactElement => { +const QuickCSS = (props: { popout: boolean } & Record): React.ReactElement => { const ref = React.useRef(null); const { value, setValue } = useCodeMirror({ container: ref.current, @@ -170,24 +198,108 @@ export const QuickCSS = (): React.ReactElement => { if (autoApply) setReloadTimer(setTimeout(reload, 500)); }, [value]); + if (props.popout) { + React.useEffect(() => { + const window = PopoutWindowStore?.getWindow("DISCORD_REPLUGGED_QUICKCSS"); + + let el = window.document.createElement("link"); + el.rel = "stylesheet"; + el.href = `replugged://renderer.css?t=${Date.now()}`; + window.document.head.appendChild(el); + }, []); + } + return ( <> - - {Messages.REPLUGGED_QUICKCSS} -
- {autoApply ? null : ( - - )} - + {!props.popout ? ( + <> + + {Messages.REPLUGGED_QUICKCSS} +
+ {autoApply ? null : ( + + )} + +
+
+ + + ) : null} + + {!props.popout && props.isPopoutOpen ? ( + { + closePopout("DISCORD_REPLUGGED_QUICKCSS"); + }}> + {Messages.REPLUGGED_QUICKCSS_POPPED_OUT} + + ) : ( +
+
+ + {}}> + + + + + + {!props.popout ? ( + { + openPopout( + "DISCORD_REPLUGGED_QUICKCSS", + () => ( + + + + ), + {}, + ); + }}> + + + ) : ( + { + closePopout("DISCORD_REPLUGGED_QUICKCSS"); + }}> + + + + + )} + +
+
- - -
+ )} ); }; + +export const ConnectedQuickCSS = connectStores<{ popout: boolean }, { popout: boolean; isPopoutOpen: boolean }>([PopoutWindowStore], (props) => { + return { + isPopoutOpen: PopoutWindowStore.getWindowOpen("DISCORD_REPLUGGED_QUICKCSS"), + ...props + } +})(QuickCSS);