From 6b5f7c8642062906ecb36d905e52d0fcc6172783 Mon Sep 17 00:00:00 2001 From: marios8543 Date: Thu, 22 Feb 2024 14:07:59 +0200 Subject: Added log viewer as side-tab in settings --- frontend/src/components/logviewer/LogList.tsx | 48 +++++++++ frontend/src/components/logviewer/LogViewModal.tsx | 45 +++++++++ frontend/src/components/logviewer/LoggedPlugin.tsx | 35 +++++++ .../src/components/logviewer/ScrollableWindow.tsx | 107 +++++++++++++++++++++ frontend/src/components/logviewer/index.tsx | 20 ++++ 5 files changed, 255 insertions(+) create mode 100644 frontend/src/components/logviewer/LogList.tsx create mode 100644 frontend/src/components/logviewer/LogViewModal.tsx create mode 100644 frontend/src/components/logviewer/LoggedPlugin.tsx create mode 100644 frontend/src/components/logviewer/ScrollableWindow.tsx create mode 100644 frontend/src/components/logviewer/index.tsx (limited to 'frontend/src/components/logviewer') diff --git a/frontend/src/components/logviewer/LogList.tsx b/frontend/src/components/logviewer/LogList.tsx new file mode 100644 index 00000000..b536fd02 --- /dev/null +++ b/frontend/src/components/logviewer/LogList.tsx @@ -0,0 +1,48 @@ +import { + DialogButton, + Focusable, + showModal, +} from "decky-frontend-lib"; +import { FC, useEffect, useState } from "react"; +import { useTranslation } from "react-i18next"; +import LogViewModal from "./LogViewModal"; + +const LogList: FC<{ plugin: string }> = ({ plugin }) => { + const [logList, setLogList] = useState([]); + const { t } = useTranslation(); + + useEffect(() => { + window.DeckyPluginLoader.callServerMethod("get_plugin_logs", { + plugin_name: plugin, + }).then((log_list) => { + setLogList(log_list.result || []); + }); + }, []); + + return ( + + {logList.map((log_file) => ( + + showModal( + , + ) + } + onClick={() => + showModal( + , + ) + } + > +
+
{log_file}
+
+
+ ))} +
+ ); +}; + +export default LogList; diff --git a/frontend/src/components/logviewer/LogViewModal.tsx b/frontend/src/components/logviewer/LogViewModal.tsx new file mode 100644 index 00000000..beda50a3 --- /dev/null +++ b/frontend/src/components/logviewer/LogViewModal.tsx @@ -0,0 +1,45 @@ +import { Focusable } from "decky-frontend-lib"; +import { VFC, useEffect, useState } from "react"; +import { ScrollableWindowRelative } from "./ScrollableWindow"; + +interface LogFileProps { + plugin: string; + name: string; + closeModal?: () => void; +} + +const LogViewModal: VFC = ({ name, plugin, closeModal }) => { + const [logText, setLogText] = useState("Loading text...."); + useEffect(() => { + window.DeckyPluginLoader.callServerMethod("get_plugin_log_text", { + plugin_name: plugin, + log_name: name, + }).then((text) => { + setLogText(text.result || "Error loading text"); + }); + }, []); + + return ( + console.log("Uploading...")} + > + +
+ {logText} +
+
+
+ ); +}; + +export default LogViewModal; diff --git a/frontend/src/components/logviewer/LoggedPlugin.tsx b/frontend/src/components/logviewer/LoggedPlugin.tsx new file mode 100644 index 00000000..af7564e2 --- /dev/null +++ b/frontend/src/components/logviewer/LoggedPlugin.tsx @@ -0,0 +1,35 @@ +import { Focusable } from "decky-frontend-lib"; +import { VFC, useState } from "react"; +import { FaArrowDown, FaArrowUp } from "react-icons/fa"; +import LogList from "./LogList"; + +interface LoggedPluginProps { + plugin: string; +} + +const focusableStyle = { + background: "rgba(255,255,255,.15)", + borderRadius: "var(--round-radius-size)", + padding: "10px 24px", + marginBottom: "0.5rem", +}; + +const LoggedPlugin: VFC = ({ plugin }) => { + const [isOpen, setOpen] = useState(false); + + return ( +
+ setOpen(!isOpen)}> +
+
{plugin}
+
+ {isOpen ? : } +
+
+
+ {isOpen && } +
+ ); +}; + +export default LoggedPlugin; \ No newline at end of file diff --git a/frontend/src/components/logviewer/ScrollableWindow.tsx b/frontend/src/components/logviewer/ScrollableWindow.tsx new file mode 100644 index 00000000..c1d5e5b4 --- /dev/null +++ b/frontend/src/components/logviewer/ScrollableWindow.tsx @@ -0,0 +1,107 @@ +/* +Big thanks to @jessebofil for this +https://discord.com/channels/960281551428522045/960284327445418044/1209253688363716648 +*/ + +import { Focusable, ModalPosition, GamepadButton, ScrollPanelGroup, gamepadDialogClasses, scrollPanelClasses, FooterLegendProps } from "decky-frontend-lib"; +import { FC, useLayoutEffect, useRef, useState } from "react"; + +export interface ScrollableWindowProps extends FooterLegendProps { + height: string; + fadeAmount?: string; + scrollBarWidth?: string; + alwaysFocus?: boolean; + noScrollDescription?: boolean; + + onActivate?: (e: CustomEvent) => void; + onCancel?: (e: CustomEvent) => void; +} + +const ScrollableWindow: FC = ({ height, fadeAmount, scrollBarWidth, alwaysFocus, noScrollDescription, children, actionDescriptionMap, ...focusableProps }) => { + const fade = fadeAmount === undefined || fadeAmount === '' ? '10px' : fadeAmount; + const barWidth = scrollBarWidth === undefined || scrollBarWidth === '' ? '4px' : scrollBarWidth; + const [isOverflowing, setIsOverflowing] = useState(false); + const scrollPanelRef = useRef(); + + useLayoutEffect(() => { + const { current } = scrollPanelRef; + const trigger = () => { + if (current) { + const hasOverflow = current.scrollHeight > current.clientHeight; + setIsOverflowing(hasOverflow); + } + }; + if (current) trigger(); + }, [children, height]); + + const panel = ( + + + {children} + + + ); + + return ( + <> + +
+ {isOverflowing ? ( + + {panel} + + ) : ( +
+ {panel} +
+ )} +
+ + ); +}; + +interface ScrollableWindowAutoProps extends Omit { + heightPercent?: number; +} + +export const ScrollableWindowRelative: FC = ({ heightPercent, ...props }) => { + return ( +
+ +
+ ); +}; \ No newline at end of file diff --git a/frontend/src/components/logviewer/index.tsx b/frontend/src/components/logviewer/index.tsx new file mode 100644 index 00000000..6e9baae0 --- /dev/null +++ b/frontend/src/components/logviewer/index.tsx @@ -0,0 +1,20 @@ +import { DialogBody } from 'decky-frontend-lib'; +import { FC, useEffect, useState } from 'react'; + +import LoggedPlugin from './LoggedPlugin'; + +const LogViewerPage: FC<{}> = () => { + const [plugins, setPlugins] = useState([]); + useEffect(() => { + window.DeckyPluginLoader.callServerMethod('get_plugins_with_logs').then((plugins) => { + setPlugins(plugins.result || []); + }); + }, []); + return ( + + {plugins.map((plugin) => )} + + ) +}; + +export default LogViewerPage; \ No newline at end of file -- cgit v1.2.3