mirror of
https://github.com/BrenBroZAYT/gameyfin.git
synced 2026-06-15 16:20:03 +00:00
Implement plugin enabling & disabling
This commit is contained in:
@@ -14,6 +14,10 @@ export default function PluginManagement() {
|
||||
});
|
||||
}, []);
|
||||
|
||||
function updatePlugin(plugin: PluginDto) {
|
||||
setPlugins(plugins.map(p => p.id === plugin.id ? plugin : p));
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
<div className="flex flex-row flex-grow justify-between mb-8">
|
||||
@@ -26,7 +30,10 @@ export default function PluginManagement() {
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-300px gap-4">
|
||||
{plugins.map((plugin) => <PluginManagementCard plugin={plugin} key={plugin.name}/>)}
|
||||
{plugins.map((plugin) => <PluginManagementCard plugin={plugin}
|
||||
updatePlugin={updatePlugin}
|
||||
key={plugin.name}/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-row flex-grow justify-between my-8">
|
||||
|
||||
@@ -6,7 +6,7 @@ import {PluginConfigEndpoint} from "Frontend/generated/endpoints";
|
||||
import PluginDto from "Frontend/generated/de/grimsi/gameyfin/core/plugins/management/PluginDto";
|
||||
import PluginConfigElement from "Frontend/generated/de/grimsi/gameyfin/pluginapi/core/PluginConfigElement";
|
||||
import Input from "Frontend/components/general/Input";
|
||||
import {PuzzlePiece} from "@phosphor-icons/react";
|
||||
import {Plug} from "@phosphor-icons/react";
|
||||
|
||||
interface PluginDetailsModalProps {
|
||||
plugin: PluginDto;
|
||||
@@ -52,7 +52,7 @@ export default function PluginDetailsModal({plugin, isOpen, onOpenChange}: Plugi
|
||||
<ModalBody>
|
||||
<h4 className="text-l font-bold">Details</h4>
|
||||
<div className="flex flex-row gap-8">
|
||||
<PuzzlePiece size={64} weight="fill"/>
|
||||
<Plug size={64} weight="fill"/>
|
||||
<div className="grid grid-cols-2">
|
||||
<p>Author: {plugin.author}</p>
|
||||
<p>Version: {plugin.version}</p>
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import {Card, Chip, Skeleton, useDisclosure} from "@nextui-org/react";
|
||||
import {PuzzlePiece} from "@phosphor-icons/react";
|
||||
import {Button, Card, Chip, Skeleton, Tooltip, useDisclosure} from "@nextui-org/react";
|
||||
import {Plug, Power, SlidersHorizontal} from "@phosphor-icons/react";
|
||||
import {PluginManagementEndpoint} from "Frontend/generated/endpoints";
|
||||
import PluginDto from "Frontend/generated/de/grimsi/gameyfin/core/plugins/management/PluginDto";
|
||||
import PluginState from "Frontend/generated/org/pf4j/PluginState";
|
||||
import React, {useEffect, useState} from "react";
|
||||
import PluginDetailsModal from "Frontend/components/general/PluginDetailsModal";
|
||||
|
||||
export function PluginManagementCard({plugin}: { plugin: PluginDto }) {
|
||||
export function PluginManagementCard({plugin, updatePlugin}: {
|
||||
plugin: PluginDto,
|
||||
updatePlugin: (plugin: PluginDto) => void
|
||||
}) {
|
||||
const pluginDetailsModal = useDisclosure();
|
||||
const [configValid, setConfigValid] = useState<boolean | undefined>(undefined);
|
||||
|
||||
@@ -17,7 +20,12 @@ export function PluginManagementCard({plugin}: { plugin: PluginDto }) {
|
||||
});
|
||||
}, []);
|
||||
|
||||
function iconColor(state: PluginState | undefined): "white" | "default" {
|
||||
return "default";
|
||||
}
|
||||
|
||||
function borderColor(state: PluginState | undefined): "success" | "warning" | "danger" | "default" {
|
||||
if (isDisabled(state)) return "warning";
|
||||
if (configValid === undefined) return "default";
|
||||
if (!configValid) return "danger";
|
||||
return stateToColor(state);
|
||||
@@ -36,12 +44,46 @@ export function PluginManagementCard({plugin}: { plugin: PluginDto }) {
|
||||
}
|
||||
}
|
||||
|
||||
function isDisabled(state: PluginState | undefined): boolean {
|
||||
return state === PluginState.DISABLED;
|
||||
}
|
||||
|
||||
function togglePluginEnabled() {
|
||||
if (isDisabled(plugin.state)) {
|
||||
PluginManagementEndpoint.enablePlugin(plugin.id).then(() => {
|
||||
PluginManagementEndpoint.getPlugin(plugin.id).then((response) => {
|
||||
if (response === undefined) return;
|
||||
updatePlugin(response);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
PluginManagementEndpoint.disablePlugin(plugin.id).then(() => {
|
||||
PluginManagementEndpoint.getPlugin(plugin.id).then((response) => {
|
||||
if (response === undefined) return;
|
||||
updatePlugin(response);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Card className={`flex flex-row justify-between p-2 border-2 border-${borderColor(plugin.state)}`}
|
||||
isPressable={true} onPress={pluginDetailsModal.onOpen}>
|
||||
<Card className={`flex flex-row justify-between p-2 border-2 border-${borderColor(plugin.state)}`}>
|
||||
<div className="absolute right-0 top-0 flex flex-row">
|
||||
<Tooltip content={`${isDisabled(plugin.state) ? "Enable" : "Disable"} plugin`} placement="bottom"
|
||||
color="foreground">
|
||||
<Button isIconOnly variant="ghost" onPress={() => togglePluginEnabled()}>
|
||||
<Power/>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip content="Configuration" placement="bottom" color="foreground">
|
||||
<Button isIconOnly variant="ghost" onPress={pluginDetailsModal.onOpen}>
|
||||
<SlidersHorizontal/>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className="flex flex-1 flex-col items-center gap-1">
|
||||
<PuzzlePiece size={64} weight="fill"/>
|
||||
<Plug size={64} weight="fill"/>
|
||||
<p className="font-semibold">{plugin.name}</p>
|
||||
<div className="flex flex-row gap-2">
|
||||
<Chip size="sm" radius="sm" className="text-xs">{plugin.version}</Chip>
|
||||
|
||||
+2
-2
@@ -17,7 +17,7 @@ class DatabasePluginStatusProvider(
|
||||
override fun disablePlugin(pluginId: String) {
|
||||
val pluginManagement = pluginManagementRepository.findByIdOrNull(pluginId)
|
||||
if (pluginManagement != null) {
|
||||
pluginManagement.enabled = true
|
||||
pluginManagement.enabled = false
|
||||
pluginManagementRepository.save(pluginManagement)
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ class DatabasePluginStatusProvider(
|
||||
override fun enablePlugin(pluginId: String) {
|
||||
val pluginManagement = pluginManagementRepository.findByIdOrNull(pluginId)
|
||||
if (pluginManagement != null) {
|
||||
pluginManagement.enabled = false
|
||||
pluginManagement.enabled = true
|
||||
pluginManagementRepository.save(pluginManagement)
|
||||
}
|
||||
}
|
||||
|
||||
+12
-1
@@ -22,7 +22,18 @@ class GameyfinPluginManager(
|
||||
// This took me way too long to figure out...
|
||||
// But I learned a lot about Kotlin and Java interoperability in the process
|
||||
init {
|
||||
this.pluginStatusProvider = dbPluginStatusProvider
|
||||
pluginStatusProvider = dbPluginStatusProvider
|
||||
|
||||
pluginStateListeners.add { event ->
|
||||
if (event is PluginStateEvent) {
|
||||
log.info { "Plugin ${event.plugin.pluginId} changed state to ${event.pluginState}" }
|
||||
if (event.oldState == PluginState.DISABLED) {
|
||||
startPlugin(event.plugin.pluginId)
|
||||
} else if (event.pluginState == PluginState.DISABLED) {
|
||||
stopPlugin(event.plugin.pluginId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun createPluginLoader(): PluginLoader {
|
||||
|
||||
+2
@@ -11,6 +11,8 @@ class PluginManagementEndpoint(
|
||||
) {
|
||||
fun getPlugins() = pluginManagementService.getPlugins()
|
||||
|
||||
fun getPlugin(pluginId: String) = pluginManagementService.getPlugin(pluginId)
|
||||
|
||||
fun startPlugin(pluginId: String) = pluginManagementService.startPlugin(pluginId)
|
||||
|
||||
fun stopPlugin(pluginId: String) = pluginManagementService.stopPlugin(pluginId)
|
||||
|
||||
+11
@@ -18,6 +18,17 @@ class PluginManagementService(
|
||||
}
|
||||
}
|
||||
|
||||
fun getPlugin(pluginId: String): PluginDto {
|
||||
val plugin = pluginManager.getPlugin(pluginId)
|
||||
return PluginDto(
|
||||
plugin.pluginId,
|
||||
plugin.descriptor.pluginDescription,
|
||||
plugin.descriptor.version,
|
||||
plugin.descriptor.provider,
|
||||
plugin.pluginState
|
||||
)
|
||||
}
|
||||
|
||||
fun startPlugin(pluginId: String) {
|
||||
pluginManager.startPlugin(pluginId)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user