Compare commits

..

8 Commits

Author SHA1 Message Date
TrainDoctor 59038f65ac Fix log spam from injection related errors 2022-08-17 12:57:58 -07:00
AAGaming 5960c11d60 add class names to PluginCard for theming 2022-08-17 15:27:22 -04:00
Sefa Eyeoglu 8d065eab1f Add Plugin Reload Button to Settings (#128)
* feat: add reload button to plugin list

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>

* refactor: move plugin actions into context menu

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-08-16 16:51:39 -07:00
AAGaming 3b1b6d28d6 add some classes for nicer scrolling, update lib 2022-08-15 13:22:38 -04:00
AAGaming 0a735886c9 fix toasts breaking sometimes 2022-08-14 21:59:55 -04:00
AAGaming c9430f5be4 less stupid method 2022-08-14 13:17:39 -04:00
AAGaming a4e2237fc0 fix loader not re-injecting on restart 2022-08-14 12:51:07 -04:00
AAGaming 85d0398e62 shut typescript up 2022-08-14 00:02:01 -04:00
10 changed files with 77 additions and 43 deletions
+5 -2
View File
@@ -5,6 +5,7 @@ from logging import debug, getLogger
from traceback import format_exc
from aiohttp import ClientSession
from aiohttp.client_exceptions import ClientConnectorError
BASE_ADDRESS = "http://localhost:8080"
@@ -65,11 +66,13 @@ async def get_tabs():
while True:
try:
res = await web.get(f"{BASE_ADDRESS}/json")
break
except:
except ClientConnectorError:
logger.debug("ClientConnectorError excepted.")
logger.debug("Steam isn't available yet. Wait for a moment...")
logger.debug(format_exc())
await sleep(5)
else:
break
if res.status == 200:
r = await res.json()
+2 -1
View File
@@ -97,7 +97,8 @@ class PluginManager:
#await inject_to_tab("SP", "window.syncDeckyPlugins();")
async def loader_reinjector(self):
await sleep(5)
await sleep(2)
await self.inject_javascript()
while True:
await sleep(5)
if not await tab_has_global_var("SP", "deckyHasLoaded"):
+1 -1
View File
@@ -37,7 +37,7 @@
}
},
"dependencies": {
"decky-frontend-lib": "^1.5.1",
"decky-frontend-lib": "^1.6.2",
"react-icons": "^4.4.0"
}
}
+4 -4
View File
@@ -9,7 +9,7 @@ specifiers:
'@types/react': 16.14.0
'@types/react-router': 5.1.18
'@types/webpack': ^5.28.0
decky-frontend-lib: ^1.5.1
decky-frontend-lib: ^1.6.2
husky: ^8.0.1
import-sort-style-module: ^6.0.0
inquirer: ^8.2.4
@@ -23,7 +23,7 @@ specifiers:
typescript: ^4.7.4
dependencies:
decky-frontend-lib: 1.5.1
decky-frontend-lib: 1.6.2
react-icons: 4.4.0_react@16.14.0
devDependencies:
@@ -806,8 +806,8 @@ packages:
ms: 2.1.2
dev: true
/decky-frontend-lib/1.5.1:
resolution: {integrity: sha512-XrcMNxqdXJFyuJYJX4Wmo7DvFVkwBsl8aWU5wfLdPQmcPz3drafyEgqIdO4AxpFuTsHTf1qaHBiYYw349vYpgw==}
/decky-frontend-lib/1.6.2:
resolution: {integrity: sha512-O34rHg6BWYP99jxlosAl0hUfo+SmOyjN+TtcyutdIjvPkg/FgHwahTd+SMujTpZemV31c4JX8hdGnN/Z7tjL9g==}
dependencies:
minimist: 1.2.6
dev: false
+32 -16
View File
@@ -1,4 +1,11 @@
import { ButtonItem, PanelSection, PanelSectionRow } from 'decky-frontend-lib';
import {
ButtonItem,
PanelSection,
PanelSectionRow,
joinClassNames,
scrollClasses,
staticClasses,
} from 'decky-frontend-lib';
import { VFC } from 'react';
import { useDeckyState } from './DeckyState';
@@ -7,24 +14,33 @@ const PluginView: VFC = () => {
const { plugins, activePlugin, setActivePlugin } = useDeckyState();
if (activePlugin) {
return <div style={{ height: '100%' }}>{activePlugin.content}</div>;
return (
<div
className={joinClassNames(staticClasses.TabGroupPanel, scrollClasses.ScrollPanel, scrollClasses.ScrollY)}
style={{ height: '100%' }}
>
{activePlugin.content}
</div>
);
}
return (
<PanelSection>
{plugins
.filter((p) => p.content)
.map(({ name, icon }) => (
<PanelSectionRow key={name}>
<ButtonItem layout="below" onClick={() => setActivePlugin(name)}>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<div>{icon}</div>
<div>{name}</div>
</div>
</ButtonItem>
</PanelSectionRow>
))}
</PanelSection>
<div className={joinClassNames(staticClasses.TabGroupPanel, scrollClasses.ScrollPanel, scrollClasses.ScrollY)}>
<PanelSection>
{plugins
.filter((p) => p.content)
.map(({ name, icon }) => (
<PanelSectionRow key={name}>
<ButtonItem layout="below" onClick={() => setActivePlugin(name)}>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<div>{icon}</div>
<div>{name}</div>
</div>
</ButtonItem>
</PanelSectionRow>
))}
</PanelSection>
</div>
);
};
-1
View File
@@ -7,7 +7,6 @@ import { useDeckyState } from './DeckyState';
const titleStyles: CSSProperties = {
display: 'flex',
paddingTop: '3px',
paddingBottom: '14px',
paddingRight: '16px',
boxShadow: 'unset',
};
@@ -1,5 +1,5 @@
import { DialogButton, staticClasses } from 'decky-frontend-lib';
import { FaTrash } from 'react-icons/fa';
import { DialogButton, Menu, MenuItem, showContextMenu, staticClasses } from 'decky-frontend-lib';
import { FaEllipsisH } from 'react-icons/fa';
import { useDeckyState } from '../../../DeckyState';
@@ -22,9 +22,17 @@ export default function PluginList() {
<div className={staticClasses.Title} style={{ marginLeft: 'auto', boxShadow: 'none' }}>
<DialogButton
style={{ height: '40px', width: '40px', padding: '10px 12px' }}
onClick={() => window.DeckyPluginLoader.uninstallPlugin(name)}
onClick={(e: MouseEvent) =>
showContextMenu(
<Menu label="Plugin Actions">
<MenuItem onSelected={() => window.DeckyPluginLoader.importPlugin(name)}>Reload</MenuItem>
<MenuItem onSelected={() => window.DeckyPluginLoader.uninstallPlugin(name)}>Uninstall</MenuItem>
</Menu>,
e.currentTarget ?? window,
)
}
>
<FaTrash />
<FaEllipsisH />
</DialogButton>
</div>
</li>
+20 -11
View File
@@ -6,6 +6,7 @@ import {
Router,
SingleDropdownOption,
SuspensefulImage,
joinClassNames,
staticClasses,
} from 'decky-frontend-lib';
import { FC, useRef, useState } from 'react';
@@ -22,10 +23,6 @@ interface PluginCardProps {
plugin: StorePlugin | LegacyStorePlugin;
}
const classNames = (...classes: string[]) => {
return classes.join(' ');
};
function isLegacyPlugin(plugin: LegacyStorePlugin | StorePlugin): plugin is LegacyStorePlugin {
return 'artifact' in plugin;
}
@@ -44,7 +41,7 @@ const PluginCard: FC<PluginCardProps> = ({ plugin }) => {
>
{/* TODO: abstract this messy focus hackiness into a custom component in lib */}
<Focusable
// className="Panel Focusable"
className="deckyStoreCard"
ref={containerRef}
onActivate={(_: CustomEvent) => {
buttonRef.current!.focus();
@@ -68,15 +65,17 @@ const PluginCard: FC<PluginCardProps> = ({ plugin }) => {
boxSizing: 'border-box',
}}
>
<div style={{ display: 'flex', alignItems: 'center' }}>
<div className="deckyStoreCardHeader" style={{ display: 'flex', alignItems: 'center' }}>
<a
style={{ fontSize: '18pt', padding: '10px' }}
className={classNames(staticClasses.Text)}
className={joinClassNames(staticClasses.Text)}
// onClick={() => Router.NavigateToExternalWeb('https://github.com/' + plugin.artifact)}
>
{isLegacyPlugin(plugin) ? (
<div>
<span style={{ color: 'grey' }}>{plugin.artifact.split('/')[0]}/</span>
<div className="deckyStoreCardNameContainer">
<span className="deckyStoreCardLegacyRepoOwner" style={{ color: 'grey' }}>
{plugin.artifact.split('/')[0]}/
</span>
{plugin.artifact.split('/')[1]}
</div>
) : (
@@ -89,8 +88,10 @@ const PluginCard: FC<PluginCardProps> = ({ plugin }) => {
display: 'flex',
flexDirection: 'row',
}}
className="deckyStoreCardBody"
>
<SuspensefulImage
className="deckyStoreCardImage"
suspenseWidth="256px"
style={{
width: 'auto',
@@ -113,14 +114,16 @@ const PluginCard: FC<PluginCardProps> = ({ plugin }) => {
display: 'flex',
flexDirection: 'column',
}}
className="deckyStoreCardInfo"
>
<p className={classNames(staticClasses.PanelSectionRow)}>
<p className={joinClassNames(staticClasses.PanelSectionRow)}>
<span>Author: {plugin.author}</span>
</p>
<p className={classNames(staticClasses.PanelSectionRow)}>
<p className={joinClassNames('deckyStoreCardTagsContainer', staticClasses.PanelSectionRow)}>
<span>Tags:</span>
{plugin.tags.map((tag: string) => (
<span
className="deckyStoreCardTag"
style={{
padding: '5px',
marginRight: '10px',
@@ -133,6 +136,7 @@ const PluginCard: FC<PluginCardProps> = ({ plugin }) => {
))}
{isLegacyPlugin(plugin) && (
<span
className="deckyStoreCardTag deckyStoreCardLegacyTag"
style={{
color: '#232120',
padding: '5px',
@@ -148,6 +152,7 @@ const PluginCard: FC<PluginCardProps> = ({ plugin }) => {
</div>
</div>
<div
className="deckyStoreCardActionsContainer"
style={{
width: '100%',
alignSelf: 'flex-end',
@@ -156,6 +161,7 @@ const PluginCard: FC<PluginCardProps> = ({ plugin }) => {
}}
>
<Focusable
className="deckyStoreCardActions"
style={{
display: 'flex',
flexDirection: 'row',
@@ -163,11 +169,13 @@ const PluginCard: FC<PluginCardProps> = ({ plugin }) => {
}}
>
<div
className="deckyStoreCardInstallButtonContainer"
style={{
flex: '1',
}}
>
<DialogButton
className="deckyStoreCardInstallButton"
ref={buttonRef}
onClick={() =>
isLegacyPlugin(plugin)
@@ -179,6 +187,7 @@ const PluginCard: FC<PluginCardProps> = ({ plugin }) => {
</DialogButton>
</div>
<div
className="deckyStoreCardVersionDropdownContainer"
style={{
flex: '0.2',
}}
-2
View File
@@ -1,5 +1,3 @@
import { sleep } from 'decky-frontend-lib';
import PluginLoader from './plugin-loader';
import { DeckyUpdater } from './updater';
+1 -1
View File
@@ -35,7 +35,7 @@ class Toaster extends Logger {
while (true) {
instance = findInReactTree(
(document.getElementById('root') as any)._reactRootContainer._internalRoot.current,
(x) => x?.memoizedProps?.className?.startsWith('toastmanager_ToastPlaceholder'),
(x) => x?.memoizedProps?.className?.startsWith?.('toastmanager_ToastPlaceholder'),
);
if (instance) break;
this.debug('finding instance');