mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-05 21:15:38 -05:00
Allow removing force-padding on monitor widgets + plugin load fixes
This commit is contained in:
@@ -204,7 +204,8 @@ Singleton {
|
||||
"size": 20,
|
||||
"selectedGpuIndex": 0,
|
||||
"pciId": "",
|
||||
"mountPath": "/"
|
||||
"mountPath": "/",
|
||||
"minimumWidth": true
|
||||
}
|
||||
leftWidgetsModel.append(dummyItem)
|
||||
centerWidgetsModel.append(dummyItem)
|
||||
@@ -811,6 +812,7 @@ Singleton {
|
||||
var selectedGpuIndex = typeof order[i] === "string" ? undefined : order[i].selectedGpuIndex
|
||||
var pciId = typeof order[i] === "string" ? undefined : order[i].pciId
|
||||
var mountPath = typeof order[i] === "string" ? undefined : order[i].mountPath
|
||||
var minimumWidth = typeof order[i] === "string" ? undefined : order[i].minimumWidth
|
||||
var item = {
|
||||
"widgetId": widgetId,
|
||||
"enabled": enabled
|
||||
@@ -823,6 +825,8 @@ Singleton {
|
||||
item.pciId = pciId
|
||||
if (mountPath !== undefined)
|
||||
item.mountPath = mountPath
|
||||
if (minimumWidth !== undefined)
|
||||
item.minimumWidth = minimumWidth
|
||||
|
||||
listModel.append(item)
|
||||
}
|
||||
|
||||
@@ -827,6 +827,7 @@ Item {
|
||||
return processListPopoutLoader.item
|
||||
}
|
||||
parentScreen: barWindow.screen
|
||||
widgetData: parent.widgetData
|
||||
toggleProcessList: () => {
|
||||
processListPopoutLoader.active = true
|
||||
return processListPopoutLoader.item?.toggle()
|
||||
@@ -846,6 +847,7 @@ Item {
|
||||
return processListPopoutLoader.item
|
||||
}
|
||||
parentScreen: barWindow.screen
|
||||
widgetData: parent.widgetData
|
||||
toggleProcessList: () => {
|
||||
processListPopoutLoader.active = true
|
||||
return processListPopoutLoader.item?.toggle()
|
||||
@@ -875,6 +877,7 @@ Item {
|
||||
return processListPopoutLoader.item
|
||||
}
|
||||
parentScreen: barWindow.screen
|
||||
widgetData: parent.widgetData
|
||||
toggleProcessList: () => {
|
||||
processListPopoutLoader.active = true
|
||||
return processListPopoutLoader.item?.toggle()
|
||||
|
||||
@@ -65,6 +65,14 @@ Loader {
|
||||
restoreMode: Binding.RestoreNone
|
||||
}
|
||||
|
||||
Binding {
|
||||
target: root.item
|
||||
when: root.item && "widgetData" in root.item
|
||||
property: "widgetData"
|
||||
value: root.widgetData
|
||||
restoreMode: Binding.RestoreNone
|
||||
}
|
||||
|
||||
onLoaded: {
|
||||
if (item) {
|
||||
contentItemReady(item)
|
||||
|
||||
@@ -17,6 +17,8 @@ Rectangle {
|
||||
property var parentScreen: null
|
||||
property real barThickness: 48
|
||||
property real widgetThickness: 30
|
||||
property var widgetData: null
|
||||
property bool minimumWidth: (widgetData && widgetData.minimumWidth !== undefined) ? widgetData.minimumWidth : true
|
||||
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetThickness / 30))
|
||||
|
||||
width: isVertical ? widgetThickness : (cpuContent.implicitWidth + horizontalPadding * 2)
|
||||
@@ -141,7 +143,7 @@ Rectangle {
|
||||
text: "100%"
|
||||
}
|
||||
|
||||
width: Math.max(cpuBaseline.width, paintedWidth)
|
||||
width: root.minimumWidth ? Math.max(cpuBaseline.width, paintedWidth) : paintedWidth
|
||||
|
||||
Behavior on width {
|
||||
NumberAnimation {
|
||||
|
||||
@@ -17,6 +17,8 @@ Rectangle {
|
||||
property var parentScreen: null
|
||||
property real barThickness: 48
|
||||
property real widgetThickness: 30
|
||||
property var widgetData: null
|
||||
property bool minimumWidth: (widgetData && widgetData.minimumWidth !== undefined) ? widgetData.minimumWidth : true
|
||||
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetThickness / 30))
|
||||
|
||||
width: isVertical ? widgetThickness : (cpuTempContent.implicitWidth + horizontalPadding * 2)
|
||||
@@ -141,7 +143,7 @@ Rectangle {
|
||||
text: "100°"
|
||||
}
|
||||
|
||||
width: Math.max(tempBaseline.width, paintedWidth)
|
||||
width: root.minimumWidth ? Math.max(tempBaseline.width, paintedWidth) : paintedWidth
|
||||
|
||||
Behavior on width {
|
||||
NumberAnimation {
|
||||
|
||||
@@ -19,6 +19,7 @@ Rectangle {
|
||||
property real barThickness: 48
|
||||
property real widgetThickness: 30
|
||||
property int selectedGpuIndex: (widgetData && widgetData.selectedGpuIndex !== undefined) ? widgetData.selectedGpuIndex : 0
|
||||
property bool minimumWidth: (widgetData && widgetData.minimumWidth !== undefined) ? widgetData.minimumWidth : true
|
||||
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetThickness / 30))
|
||||
property real displayTemp: {
|
||||
if (!DgopService.availableGpus || DgopService.availableGpus.length === 0) {
|
||||
@@ -209,7 +210,7 @@ Rectangle {
|
||||
text: "100°"
|
||||
}
|
||||
|
||||
width: Math.max(gpuTempBaseline.width, paintedWidth)
|
||||
width: root.minimumWidth ? Math.max(gpuTempBaseline.width, paintedWidth) : paintedWidth
|
||||
|
||||
Behavior on width {
|
||||
NumberAnimation {
|
||||
|
||||
@@ -17,6 +17,8 @@ Rectangle {
|
||||
property var parentScreen: null
|
||||
property real barThickness: 48
|
||||
property real widgetThickness: 30
|
||||
property var widgetData: null
|
||||
property bool minimumWidth: (widgetData && widgetData.minimumWidth !== undefined) ? widgetData.minimumWidth : true
|
||||
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetThickness / 30))
|
||||
|
||||
width: isVertical ? widgetThickness : (ramContent.implicitWidth + horizontalPadding * 2)
|
||||
@@ -30,6 +32,7 @@ Rectangle {
|
||||
const baseColor = ramArea.containsMouse ? Theme.widgetBaseHoverColor : Theme.widgetBaseBackgroundColor;
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
DgopService.addRef(["memory"]);
|
||||
}
|
||||
@@ -141,7 +144,7 @@ Rectangle {
|
||||
text: "100%"
|
||||
}
|
||||
|
||||
width: Math.max(ramBaseline.width, paintedWidth)
|
||||
width: root.minimumWidth ? Math.max(ramBaseline.width, paintedWidth) : paintedWidth
|
||||
|
||||
Behavior on width {
|
||||
NumberAnimation {
|
||||
|
||||
@@ -263,6 +263,9 @@ Item {
|
||||
if (widgetId === "diskUsage") {
|
||||
widgetObj.mountPath = "/"
|
||||
}
|
||||
if (widgetId === "cpuUsage" || widgetId === "memUsage" || widgetId === "cpuTemp" || widgetId === "gpuTemp") {
|
||||
widgetObj.minimumWidth = true
|
||||
}
|
||||
|
||||
var widgets = []
|
||||
if (targetSection === "left") {
|
||||
@@ -509,6 +512,54 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
function handleMinimumWidthChanged(sectionId, widgetIndex, enabled) {
|
||||
var widgets = []
|
||||
if (sectionId === "left")
|
||||
widgets = SettingsData.dankBarLeftWidgets.slice()
|
||||
else if (sectionId === "center")
|
||||
widgets = SettingsData.dankBarCenterWidgets.slice()
|
||||
else if (sectionId === "right")
|
||||
widgets = SettingsData.dankBarRightWidgets.slice()
|
||||
|
||||
if (widgetIndex >= 0 && widgetIndex < widgets.length) {
|
||||
var widget = widgets[widgetIndex]
|
||||
if (typeof widget === "string") {
|
||||
widgets[widgetIndex] = {
|
||||
"id": widget,
|
||||
"enabled": true,
|
||||
"minimumWidth": enabled
|
||||
}
|
||||
} else {
|
||||
var newWidget = {
|
||||
"id": widget.id,
|
||||
"enabled": widget.enabled,
|
||||
"minimumWidth": enabled
|
||||
}
|
||||
if (widget.size !== undefined)
|
||||
newWidget.size = widget.size
|
||||
if (widget.selectedGpuIndex !== undefined)
|
||||
newWidget.selectedGpuIndex = widget.selectedGpuIndex
|
||||
if (widget.pciId !== undefined)
|
||||
newWidget.pciId = widget.pciId
|
||||
if (widget.mountPath !== undefined)
|
||||
newWidget.mountPath = widget.mountPath
|
||||
if (widget.id === "controlCenterButton") {
|
||||
newWidget.showNetworkIcon = widget.showNetworkIcon !== undefined ? widget.showNetworkIcon : true
|
||||
newWidget.showBluetoothIcon = widget.showBluetoothIcon !== undefined ? widget.showBluetoothIcon : true
|
||||
newWidget.showAudioIcon = widget.showAudioIcon !== undefined ? widget.showAudioIcon : true
|
||||
}
|
||||
widgets[widgetIndex] = newWidget
|
||||
}
|
||||
}
|
||||
|
||||
if (sectionId === "left")
|
||||
SettingsData.setDankBarLeftWidgets(widgets)
|
||||
else if (sectionId === "center")
|
||||
SettingsData.setDankBarCenterWidgets(widgets)
|
||||
else if (sectionId === "right")
|
||||
SettingsData.setDankBarRightWidgets(widgets)
|
||||
}
|
||||
|
||||
function getItemsForSection(sectionId) {
|
||||
var widgets = []
|
||||
var widgetData = []
|
||||
@@ -532,6 +583,7 @@ Item {
|
||||
var widgetShowNetworkIcon = typeof widget === "string" ? undefined : widget.showNetworkIcon
|
||||
var widgetShowBluetoothIcon = typeof widget === "string" ? undefined : widget.showBluetoothIcon
|
||||
var widgetShowAudioIcon = typeof widget === "string" ? undefined : widget.showAudioIcon
|
||||
var widgetMinimumWidth = typeof widget === "string" ? undefined : widget.minimumWidth
|
||||
var widgetDef = baseWidgetDefinitions.find(w => {
|
||||
return w.id === widgetId
|
||||
})
|
||||
@@ -552,6 +604,8 @@ Item {
|
||||
item.showBluetoothIcon = widgetShowBluetoothIcon
|
||||
if (widgetShowAudioIcon !== undefined)
|
||||
item.showAudioIcon = widgetShowAudioIcon
|
||||
if (widgetMinimumWidth !== undefined)
|
||||
item.minimumWidth = widgetMinimumWidth
|
||||
|
||||
widgets.push(item)
|
||||
}
|
||||
@@ -1208,6 +1262,10 @@ Item {
|
||||
dankBarTab.handleDiskMountSelectionChanged(
|
||||
sectionId, widgetIndex, mountPath)
|
||||
}
|
||||
onMinimumWidthChanged: (sectionId, widgetIndex, enabled) => {
|
||||
dankBarTab.handleMinimumWidthChanged(
|
||||
sectionId, widgetIndex, enabled)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1280,6 +1338,10 @@ Item {
|
||||
dankBarTab.handleDiskMountSelectionChanged(
|
||||
sectionId, widgetIndex, mountPath)
|
||||
}
|
||||
onMinimumWidthChanged: (sectionId, widgetIndex, enabled) => {
|
||||
dankBarTab.handleMinimumWidthChanged(
|
||||
sectionId, widgetIndex, enabled)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1352,6 +1414,10 @@ Item {
|
||||
dankBarTab.handleDiskMountSelectionChanged(
|
||||
sectionId, widgetIndex, mountPath)
|
||||
}
|
||||
onMinimumWidthChanged: (sectionId, widgetIndex, enabled) => {
|
||||
dankBarTab.handleMinimumWidthChanged(
|
||||
sectionId, widgetIndex, enabled)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ Column {
|
||||
signal gpuSelectionChanged(string sectionId, int widgetIndex, int selectedIndex)
|
||||
signal diskMountSelectionChanged(string sectionId, int widgetIndex, string mountPath)
|
||||
signal controlCenterSettingChanged(string sectionId, int widgetIndex, string settingName, bool value)
|
||||
signal minimumWidthChanged(string sectionId, int widgetIndex, bool enabled)
|
||||
|
||||
width: parent.width
|
||||
height: implicitHeight
|
||||
@@ -283,6 +284,37 @@ Column {
|
||||
}
|
||||
}
|
||||
|
||||
DankActionButton {
|
||||
id: minimumWidthButton
|
||||
buttonSize: 28
|
||||
visible: modelData.id === "cpuUsage"
|
||||
|| modelData.id === "memUsage"
|
||||
|| modelData.id === "cpuTemp"
|
||||
|| modelData.id === "gpuTemp"
|
||||
iconName: "straighten"
|
||||
iconSize: 16
|
||||
iconColor: (modelData.minimumWidth !== undefined ? modelData.minimumWidth : true) ? Theme.primary : Theme.outline
|
||||
onClicked: {
|
||||
var currentEnabled = modelData.minimumWidth !== undefined ? modelData.minimumWidth : true
|
||||
root.minimumWidthChanged(root.sectionId, index, !currentEnabled)
|
||||
}
|
||||
onEntered: {
|
||||
minimumWidthTooltipLoader.active = true
|
||||
if (minimumWidthTooltipLoader.item) {
|
||||
var currentEnabled = modelData.minimumWidth !== undefined ? modelData.minimumWidth : true
|
||||
const tooltipText = currentEnabled ? "Force Padding" : "Dynamic Width"
|
||||
const p = minimumWidthButton.mapToItem(null, minimumWidthButton.width / 2, 0)
|
||||
minimumWidthTooltipLoader.item.show(tooltipText, p.x, p.y - 40, null)
|
||||
}
|
||||
}
|
||||
onExited: {
|
||||
if (minimumWidthTooltipLoader.item) {
|
||||
minimumWidthTooltipLoader.item.hide()
|
||||
}
|
||||
minimumWidthTooltipLoader.active = false
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
spacing: Theme.spacingXS
|
||||
visible: modelData.id === "clock"
|
||||
@@ -892,4 +924,10 @@ Column {
|
||||
active: false
|
||||
sourceComponent: DankTooltip {}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: minimumWidthTooltipLoader
|
||||
active: false
|
||||
sourceComponent: DankTooltip {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ Singleton {
|
||||
|
||||
property int currentScanIndex: 0
|
||||
property var scanResults: []
|
||||
property var foundPlugins: ({})
|
||||
|
||||
property var lsProcess: Process {
|
||||
id: dirScanner
|
||||
@@ -68,12 +69,14 @@ Singleton {
|
||||
scanNextDirectory()
|
||||
} else {
|
||||
currentScanIndex = 0
|
||||
cleanupRemovedPlugins()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function scanPlugins() {
|
||||
currentScanIndex = 0
|
||||
foundPlugins = {}
|
||||
scanNextDirectory()
|
||||
}
|
||||
|
||||
@@ -88,39 +91,57 @@ Singleton {
|
||||
function loadPluginManifest(manifestPath) {
|
||||
var readerId = "reader_" + Date.now() + "_" + Math.random()
|
||||
|
||||
var catProcess = Qt.createComponent("data:text/plain,import Quickshell.Io; Process { stdout: StdioCollector { } }")
|
||||
if (catProcess.status === Component.Ready) {
|
||||
var process = catProcess.createObject(root)
|
||||
process.command = ["cat", manifestPath]
|
||||
process.stdout.streamFinished.connect(function() {
|
||||
try {
|
||||
var manifest = JSON.parse(process.stdout.text.trim())
|
||||
processManifest(manifest, manifestPath)
|
||||
} catch (e) {
|
||||
console.error("PluginService: Failed to parse manifest", manifestPath, ":", e.message)
|
||||
}
|
||||
process.destroy()
|
||||
delete manifestReaders[readerId]
|
||||
})
|
||||
process.exited.connect(function(exitCode) {
|
||||
var checkProcess = Qt.createComponent("data:text/plain,import Quickshell.Io; Process { stdout: StdioCollector { } }")
|
||||
if (checkProcess.status === Component.Ready) {
|
||||
var checker = checkProcess.createObject(root)
|
||||
checker.command = ["test", "-f", manifestPath]
|
||||
checker.exited.connect(function(exitCode) {
|
||||
if (exitCode !== 0) {
|
||||
console.error("PluginService: Failed to read manifest file:", manifestPath, "exit code:", exitCode)
|
||||
process.destroy()
|
||||
checker.destroy()
|
||||
delete manifestReaders[readerId]
|
||||
return
|
||||
}
|
||||
|
||||
var catProcess = Qt.createComponent("data:text/plain,import Quickshell.Io; Process { stdout: StdioCollector { } }")
|
||||
if (catProcess.status === Component.Ready) {
|
||||
var process = catProcess.createObject(root)
|
||||
process.command = ["cat", manifestPath]
|
||||
process.stdout.streamFinished.connect(function() {
|
||||
try {
|
||||
var manifest = JSON.parse(process.stdout.text.trim())
|
||||
processManifest(manifest, manifestPath)
|
||||
} catch (e) {
|
||||
console.error("PluginService: Failed to parse manifest", manifestPath, ":", e.message)
|
||||
}
|
||||
process.destroy()
|
||||
delete manifestReaders[readerId]
|
||||
})
|
||||
process.exited.connect(function(exitCode) {
|
||||
if (exitCode !== 0) {
|
||||
console.error("PluginService: Failed to read manifest file:", manifestPath, "exit code:", exitCode)
|
||||
process.destroy()
|
||||
delete manifestReaders[readerId]
|
||||
}
|
||||
})
|
||||
manifestReaders[readerId] = process
|
||||
process.running = true
|
||||
} else {
|
||||
console.error("PluginService: Failed to create manifest reader process")
|
||||
}
|
||||
|
||||
checker.destroy()
|
||||
})
|
||||
manifestReaders[readerId] = process
|
||||
process.running = true
|
||||
manifestReaders[readerId] = checker
|
||||
checker.running = true
|
||||
} else {
|
||||
console.error("PluginService: Failed to create manifest reader process")
|
||||
console.error("PluginService: Failed to create file check process")
|
||||
}
|
||||
}
|
||||
|
||||
function processManifest(manifest, manifestPath) {
|
||||
registerPlugin(manifest, manifestPath)
|
||||
|
||||
// Auto-load plugin if it's enabled in settings (default to enabled)
|
||||
var enabled = SettingsData.getPluginSetting(manifest.id, "enabled", true)
|
||||
var enabled = SettingsData.getPluginSetting(manifest.id, "enabled", false)
|
||||
if (enabled) {
|
||||
loadPlugin(manifest.id)
|
||||
}
|
||||
@@ -156,7 +177,10 @@ Singleton {
|
||||
pluginInfo.loaded = false
|
||||
pluginInfo.type = manifest.type || "widget"
|
||||
|
||||
availablePlugins[manifest.id] = pluginInfo
|
||||
var newPlugins = Object.assign({}, availablePlugins)
|
||||
newPlugins[manifest.id] = pluginInfo
|
||||
availablePlugins = newPlugins
|
||||
foundPlugins[manifest.id] = true
|
||||
}
|
||||
|
||||
function hasPermission(pluginId, permission) {
|
||||
@@ -168,6 +192,27 @@ Singleton {
|
||||
return permissions.indexOf(permission) !== -1
|
||||
}
|
||||
|
||||
function cleanupRemovedPlugins() {
|
||||
var pluginsToRemove = []
|
||||
for (var pluginId in availablePlugins) {
|
||||
if (!foundPlugins[pluginId]) {
|
||||
pluginsToRemove.push(pluginId)
|
||||
}
|
||||
}
|
||||
|
||||
if (pluginsToRemove.length > 0) {
|
||||
var newPlugins = Object.assign({}, availablePlugins)
|
||||
for (var i = 0; i < pluginsToRemove.length; i++) {
|
||||
var pluginId = pluginsToRemove[i]
|
||||
if (isPluginLoaded(pluginId)) {
|
||||
unloadPlugin(pluginId)
|
||||
}
|
||||
delete newPlugins[pluginId]
|
||||
}
|
||||
availablePlugins = newPlugins
|
||||
}
|
||||
}
|
||||
|
||||
function loadPlugin(pluginId) {
|
||||
var plugin = availablePlugins[pluginId]
|
||||
if (!plugin) {
|
||||
@@ -184,14 +229,15 @@ Singleton {
|
||||
var componentMap = isDaemon ? pluginDaemonComponents : pluginWidgetComponents
|
||||
|
||||
if (componentMap[pluginId]) {
|
||||
var oldComponent = componentMap[pluginId]
|
||||
if (oldComponent) {
|
||||
oldComponent.destroy()
|
||||
}
|
||||
componentMap[pluginId]?.destroy()
|
||||
if (isDaemon) {
|
||||
delete pluginDaemonComponents[pluginId]
|
||||
var newDaemons = Object.assign({}, pluginDaemonComponents)
|
||||
delete newDaemons[pluginId]
|
||||
pluginDaemonComponents = newDaemons
|
||||
} else {
|
||||
delete pluginWidgetComponents[pluginId]
|
||||
var newComponents = Object.assign({}, pluginWidgetComponents)
|
||||
delete newComponents[pluginId]
|
||||
pluginWidgetComponents = newComponents
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,7 +250,6 @@ Singleton {
|
||||
if (component.status === Component.Error) {
|
||||
console.error("PluginService: Failed to create component for plugin:", pluginId, "Error:", component.errorString())
|
||||
pluginLoadFailed(pluginId, component.errorString())
|
||||
component.destroy()
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -212,7 +257,6 @@ Singleton {
|
||||
if (component.status === Component.Error) {
|
||||
console.error("PluginService: Failed to create component for plugin:", pluginId, "Error:", component.errorString())
|
||||
pluginLoadFailed(pluginId, component.errorString())
|
||||
component.destroy()
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -250,18 +294,12 @@ Singleton {
|
||||
var isDaemon = plugin.type === "daemon"
|
||||
|
||||
if (isDaemon && pluginDaemonComponents[pluginId]) {
|
||||
var daemonComponent = pluginDaemonComponents[pluginId]
|
||||
if (daemonComponent) {
|
||||
daemonComponent.destroy()
|
||||
}
|
||||
pluginDaemonComponents[pluginId]?.destroy()
|
||||
var newDaemons = Object.assign({}, pluginDaemonComponents)
|
||||
delete newDaemons[pluginId]
|
||||
pluginDaemonComponents = newDaemons
|
||||
} else if (pluginWidgetComponents[pluginId]) {
|
||||
var component = pluginWidgetComponents[pluginId]
|
||||
if (component) {
|
||||
component.destroy()
|
||||
}
|
||||
pluginWidgetComponents[pluginId]?.destroy()
|
||||
var newComponents = Object.assign({}, pluginWidgetComponents)
|
||||
delete newComponents[pluginId]
|
||||
pluginWidgetComponents = newComponents
|
||||
|
||||
Reference in New Issue
Block a user