1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-05-13 07:42:46 -04:00

refactor: (Framemode) Added DeferredAction for dbar/dock state handling

This commit is contained in:
purian23
2026-05-04 10:43:07 -04:00
parent cc47703d48
commit 19c561da14
7 changed files with 245 additions and 84 deletions
+55
View File
@@ -0,0 +1,55 @@
import QtQuick
Item {
id: root
visible: false
width: 0
height: 0
property int interval: 0
property bool pending: false
signal triggered
function schedule() {
if (!root.enabled || root.pending)
return;
root.pending = true;
deferTimer.restart();
}
function restart() {
if (!root.enabled)
return;
root.pending = true;
deferTimer.restart();
}
function flush() {
if (!root.pending)
return;
deferTimer.stop();
root.pending = false;
root.triggered();
}
function cancel() {
deferTimer.stop();
root.pending = false;
}
onEnabledChanged: {
if (!enabled)
cancel();
}
Timer {
id: deferTimer
interval: root.interval
repeat: false
onTriggered: root.flush()
}
Component.onDestruction: cancel()
}
+29 -1
View File
@@ -164,7 +164,22 @@ Item {
} }
} }
property bool barSurfacesLoaded: true
function recreateBarSurfaces() {
if (barSurfacesLoaded)
barSurfacesLoaded = false;
barSurfaceReloadAction.schedule();
}
DeferredAction {
id: barSurfaceReloadAction
onTriggered: root.barSurfacesLoaded = true
}
property string _barLayoutStateJson: { property string _barLayoutStateJson: {
if (!barSurfacesLoaded)
return "[]";
const configs = SettingsData.barConfigs; const configs = SettingsData.barConfigs;
const mapped = configs.map(c => ({ const mapped = configs.map(c => ({
id: c.id, id: c.id,
@@ -188,6 +203,19 @@ Item {
} }
} }
Connections {
target: SettingsData
function onFrameEnabledChanged() {
root.recreateBarSurfaces();
}
function onConnectedFrameModeActiveChanged() {
root.recreateBarSurfaces();
}
function onForceDankBarLayoutRefresh() {
root.recreateBarSurfaces();
}
}
Frame {} Frame {}
Repeater { Repeater {
@@ -203,7 +231,7 @@ Item {
id: barLoader id: barLoader
required property var modelData required property var modelData
property var barConfig: SettingsData.barConfigs.find(cfg => cfg.id === modelData.id) || null property var barConfig: SettingsData.barConfigs.find(cfg => cfg.id === modelData.id) || null
active: barConfig?.enabled ?? false active: root.barSurfacesLoaded && (barConfig?.enabled ?? false)
asynchronous: false asynchronous: false
sourceComponent: DankBar { sourceComponent: DankBar {
+112 -43
View File
@@ -19,33 +19,52 @@ Item {
property var leftWidgetsModel property var leftWidgetsModel
property var centerWidgetsModel property var centerWidgetsModel
property var rightWidgetsModel property var rightWidgetsModel
property bool _animateFrameInsets: false
readonly property real innerPadding: barConfig?.innerPadding ?? 4 readonly property real innerPadding: barConfig?.innerPadding ?? 4
readonly property real outlineThickness: (barConfig?.widgetOutlineEnabled ?? false) ? (barConfig?.widgetOutlineThickness ?? 1) : 0 readonly property real outlineThickness: (barConfig?.widgetOutlineEnabled ?? false) ? (barConfig?.widgetOutlineThickness ?? 1) : 0
readonly property real _edgeBaseMargin: Math.max(Theme.spacingXS, innerPadding * 0.8)
readonly property real _frameEdgeFloorInset: SettingsData.frameEnabled ? Math.max(0, SettingsData.frameThickness - _edgeBaseMargin) : 0
readonly property bool _hasBarWindow: barWindow !== undefined && barWindow !== null
readonly property bool _barIsVertical: _hasBarWindow ? barWindow.isVertical : false
readonly property string _barScreenName: _hasBarWindow ? (barWindow.screenName || "") : ""
readonly property bool hasAdjacentTopBarLive: _hasBarWindow && barWindow.hasAdjacentTopBar
readonly property bool hasAdjacentBottomBarLive: _hasBarWindow && barWindow.hasAdjacentBottomBar
readonly property bool hasAdjacentLeftBarLive: _hasBarWindow && barWindow.hasAdjacentLeftBar
readonly property bool hasAdjacentRightBarLive: _hasBarWindow && barWindow.hasAdjacentRightBar
property bool _hadAdjacentTopBar: false
property bool _hadAdjacentBottomBar: false
property bool _hadAdjacentLeftBar: false
property bool _hadAdjacentRightBar: false
onHasAdjacentTopBarLiveChanged: if (hasAdjacentTopBarLive) _hadAdjacentTopBar = true
onHasAdjacentBottomBarLiveChanged: if (hasAdjacentBottomBarLive) _hadAdjacentBottomBar = true
onHasAdjacentLeftBarLiveChanged: if (hasAdjacentLeftBarLive) _hadAdjacentLeftBar = true
onHasAdjacentRightBarLiveChanged: if (hasAdjacentRightBarLive) _hadAdjacentRightBar = true
readonly property real _frameLeftInset: { readonly property real _frameLeftInset: {
if (!SettingsData.frameEnabled || barWindow.isVertical) return 0 if (!_hasBarWindow || !SettingsData.frameEnabled || _barIsVertical) return 0
return barWindow.hasAdjacentLeftBar return hasAdjacentLeftBarLive
? SettingsData.frameBarSize ? SettingsData.frameBarSize
: 0 : (_hadAdjacentLeftBar ? _frameEdgeFloorInset : 0)
} }
readonly property real _frameRightInset: { readonly property real _frameRightInset: {
if (!SettingsData.frameEnabled || barWindow.isVertical) return 0 if (!_hasBarWindow || !SettingsData.frameEnabled || _barIsVertical) return 0
return barWindow.hasAdjacentRightBar return hasAdjacentRightBarLive
? SettingsData.frameBarSize ? SettingsData.frameBarSize
: 0 : (_hadAdjacentRightBar ? _frameEdgeFloorInset : 0)
} }
readonly property real _frameTopInset: { readonly property real _frameTopInset: {
if (!SettingsData.frameEnabled || !barWindow.isVertical) return 0 if (!_hasBarWindow || !SettingsData.frameEnabled || !_barIsVertical) return 0
return barWindow.hasAdjacentTopBar return hasAdjacentTopBarLive
? SettingsData.frameThickness ? SettingsData.frameThickness
: 0 : (_hadAdjacentTopBar ? _frameEdgeFloorInset : 0)
} }
readonly property real _frameBottomInset: { readonly property real _frameBottomInset: {
if (!SettingsData.frameEnabled || !barWindow.isVertical) return 0 if (!_hasBarWindow || !SettingsData.frameEnabled || !_barIsVertical) return 0
return barWindow.hasAdjacentBottomBar return hasAdjacentBottomBarLive
? SettingsData.frameThickness ? SettingsData.frameThickness
: 0 : (_hadAdjacentBottomBar ? _frameEdgeFloorInset : 0)
} }
property alias hLeftSection: hLeftSection property alias hLeftSection: hLeftSection
@@ -56,16 +75,61 @@ Item {
property alias vRightSection: vRightSection property alias vRightSection: vRightSection
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: Math.max(Theme.spacingXS, innerPadding * 0.8) + _frameLeftInset anchors.leftMargin: _edgeBaseMargin + _frameLeftInset
anchors.rightMargin: Math.max(Theme.spacingXS, innerPadding * 0.8) + _frameRightInset anchors.rightMargin: _edgeBaseMargin + _frameRightInset
anchors.topMargin: (barWindow.isVertical anchors.topMargin: (_barIsVertical
? (barWindow.hasAdjacentTopBar ? outlineThickness : Theme.spacingXS) ? (hasAdjacentTopBarLive ? outlineThickness : Theme.spacingXS)
: 0) + _frameTopInset : 0) + _frameTopInset
anchors.bottomMargin: (barWindow.isVertical anchors.bottomMargin: (_barIsVertical
? (barWindow.hasAdjacentBottomBar ? outlineThickness : Theme.spacingXS) ? (hasAdjacentBottomBarLive ? outlineThickness : Theme.spacingXS)
: 0) + _frameBottomInset : 0) + _frameBottomInset
clip: false clip: false
DeferredAction {
id: enableFrameInsetAnimation
onTriggered: topBarContent._animateFrameInsets = true
}
Component.onCompleted: {
_hadAdjacentTopBar = hasAdjacentTopBarLive;
_hadAdjacentBottomBar = hasAdjacentBottomBarLive;
_hadAdjacentLeftBar = hasAdjacentLeftBarLive;
_hadAdjacentRightBar = hasAdjacentRightBarLive;
enableFrameInsetAnimation.schedule();
}
Behavior on anchors.leftMargin {
enabled: _animateFrameInsets && SettingsData.frameEnabled
NumberAnimation {
duration: Theme.shortDuration
easing.type: Easing.OutCubic
}
}
Behavior on anchors.rightMargin {
enabled: _animateFrameInsets && SettingsData.frameEnabled
NumberAnimation {
duration: Theme.shortDuration
easing.type: Easing.OutCubic
}
}
Behavior on anchors.topMargin {
enabled: _animateFrameInsets && SettingsData.frameEnabled
NumberAnimation {
duration: Theme.shortDuration
easing.type: Easing.OutCubic
}
}
Behavior on anchors.bottomMargin {
enabled: _animateFrameInsets && SettingsData.frameEnabled
NumberAnimation {
duration: Theme.shortDuration
easing.type: Easing.OutCubic
}
}
property int componentMapRevision: 0 property int componentMapRevision: 0
function updateComponentMap() { function updateComponentMap() {
@@ -73,10 +137,14 @@ Item {
} }
readonly property var sortedToplevels: { readonly property var sortedToplevels: {
return CompositorService.filterCurrentWorkspace(CompositorService.sortedToplevels, barWindow.screenName); if (!_hasBarWindow) {
return [];
}
return CompositorService.filterCurrentWorkspace(CompositorService.sortedToplevels, _barScreenName);
} }
function getRealWorkspaces() { function getRealWorkspaces() {
const screenName = _barScreenName;
if (CompositorService.isNiri) { if (CompositorService.isNiri) {
const fallbackWorkspaces = [ const fallbackWorkspaces = [
{ {
@@ -90,16 +158,16 @@ Item {
"name": "" "name": ""
} }
]; ];
if (!barWindow.screenName || SettingsData.workspaceFollowFocus) { if (!screenName || SettingsData.workspaceFollowFocus) {
const currentWorkspaces = NiriService.getCurrentOutputWorkspaces(); const currentWorkspaces = NiriService.getCurrentOutputWorkspaces();
return currentWorkspaces.length > 0 ? currentWorkspaces : fallbackWorkspaces; return currentWorkspaces.length > 0 ? currentWorkspaces : fallbackWorkspaces;
} }
const workspaces = NiriService.allWorkspaces.filter(ws => ws.output === barWindow.screenName); const workspaces = NiriService.allWorkspaces.filter(ws => ws.output === screenName);
return workspaces.length > 0 ? workspaces : fallbackWorkspaces; return workspaces.length > 0 ? workspaces : fallbackWorkspaces;
} else if (CompositorService.isHyprland) { } else if (CompositorService.isHyprland) {
const workspaces = Hyprland.workspaces?.values || []; const workspaces = Hyprland.workspaces?.values || [];
if (!barWindow.screenName || SettingsData.workspaceFollowFocus) { if (!screenName || SettingsData.workspaceFollowFocus) {
const sorted = workspaces.slice().sort((a, b) => a.id - b.id); const sorted = workspaces.slice().sort((a, b) => a.id - b.id);
const filtered = sorted.filter(ws => ws.id > -1); const filtered = sorted.filter(ws => ws.id > -1);
return filtered.length > 0 ? filtered : [ return filtered.length > 0 ? filtered : [
@@ -111,7 +179,7 @@ Item {
} }
const monitorWorkspaces = workspaces.filter(ws => { const monitorWorkspaces = workspaces.filter(ws => {
return ws.lastIpcObject && ws.lastIpcObject.monitor === barWindow.screenName && ws.id > -1; return ws.lastIpcObject && ws.lastIpcObject.monitor === screenName && ws.id > -1;
}); });
if (monitorWorkspaces.length === 0) { if (monitorWorkspaces.length === 0) {
@@ -133,7 +201,7 @@ Item {
length: DwlService.tagCount length: DwlService.tagCount
}, (_, i) => i); }, (_, i) => i);
} }
return DwlService.getVisibleTags(barWindow.screenName); return DwlService.getVisibleTags(screenName);
} else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) { } else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) {
const workspaces = I3.workspaces?.values || []; const workspaces = I3.workspaces?.values || [];
if (workspaces.length === 0) if (workspaces.length === 0)
@@ -143,11 +211,11 @@ Item {
} }
]; ];
if (!barWindow.screenName || SettingsData.workspaceFollowFocus) { if (!screenName || SettingsData.workspaceFollowFocus) {
return workspaces.slice().sort((a, b) => a.num - b.num); return workspaces.slice().sort((a, b) => a.num - b.num);
} }
const monitorWorkspaces = workspaces.filter(ws => ws.monitor?.name === barWindow.screenName); const monitorWorkspaces = workspaces.filter(ws => ws.monitor?.name === screenName);
return monitorWorkspaces.length > 0 ? monitorWorkspaces.sort((a, b) => a.num - b.num) : [ return monitorWorkspaces.length > 0 ? monitorWorkspaces.sort((a, b) => a.num - b.num) : [
{ {
"num": 1 "num": 1
@@ -158,31 +226,32 @@ Item {
} }
function getCurrentWorkspace() { function getCurrentWorkspace() {
const screenName = _barScreenName;
if (CompositorService.isNiri) { if (CompositorService.isNiri) {
if (!barWindow.screenName || SettingsData.workspaceFollowFocus) { if (!screenName || SettingsData.workspaceFollowFocus) {
return NiriService.getCurrentWorkspaceNumber(); return NiriService.getCurrentWorkspaceNumber();
} }
const activeWs = NiriService.allWorkspaces.find(ws => ws.output === barWindow.screenName && ws.is_active); const activeWs = NiriService.allWorkspaces.find(ws => ws.output === screenName && ws.is_active);
return activeWs ? activeWs.idx : 1; return activeWs ? activeWs.idx : 1;
} else if (CompositorService.isHyprland) { } else if (CompositorService.isHyprland) {
const monitors = Hyprland.monitors?.values || []; const monitors = Hyprland.monitors?.values || [];
const currentMonitor = monitors.find(monitor => monitor.name === barWindow.screenName); const currentMonitor = monitors.find(monitor => monitor.name === screenName);
return currentMonitor?.activeWorkspace?.id ?? 1; return currentMonitor?.activeWorkspace?.id ?? 1;
} else if (CompositorService.isDwl) { } else if (CompositorService.isDwl) {
if (!DwlService.dwlAvailable) if (!DwlService.dwlAvailable)
return 0; return 0;
const outputState = DwlService.getOutputState(barWindow.screenName); const outputState = DwlService.getOutputState(screenName);
if (!outputState || !outputState.tags) if (!outputState || !outputState.tags)
return 0; return 0;
const activeTags = DwlService.getActiveTags(barWindow.screenName); const activeTags = DwlService.getActiveTags(screenName);
return activeTags.length > 0 ? activeTags[0] : 0; return activeTags.length > 0 ? activeTags[0] : 0;
} else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) { } else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) {
if (!barWindow.screenName || SettingsData.workspaceFollowFocus) { if (!screenName || SettingsData.workspaceFollowFocus) {
const focusedWs = I3.workspaces?.values?.find(ws => ws.focused === true); const focusedWs = I3.workspaces?.values?.find(ws => ws.focused === true);
return focusedWs ? focusedWs.num : 1; return focusedWs ? focusedWs.num : 1;
} }
const focusedWs = I3.workspaces?.values?.find(ws => ws.monitor?.name === barWindow.screenName && ws.focused === true); const focusedWs = I3.workspaces?.values?.find(ws => ws.monitor?.name === screenName && ws.focused === true);
return focusedWs ? focusedWs.num : 1; return focusedWs ? focusedWs.num : 1;
} }
return 1; return 1;
@@ -223,7 +292,7 @@ Item {
const nextIndex = direction > 0 ? Math.min(validIndex + 1, realWorkspaces.length - 1) : Math.max(validIndex - 1, 0); const nextIndex = direction > 0 ? Math.min(validIndex + 1, realWorkspaces.length - 1) : Math.max(validIndex - 1, 0);
if (nextIndex !== validIndex) { if (nextIndex !== validIndex) {
DwlService.switchToTag(barWindow.screenName, realWorkspaces[nextIndex]); DwlService.switchToTag(_barScreenName, realWorkspaces[nextIndex]);
} }
} else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) { } else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) {
const currentWs = getCurrentWorkspace(); const currentWs = getCurrentWorkspace();
@@ -290,8 +359,8 @@ Item {
readonly property int leftToMediaGap: mediaMaxWidth > 0 ? Math.max(0, mediaLeftEdge - leftSectionRightEdge) : leftToClockGap readonly property int leftToMediaGap: mediaMaxWidth > 0 ? Math.max(0, mediaLeftEdge - leftSectionRightEdge) : leftToClockGap
readonly property int mediaToClockGap: mediaMaxWidth > 0 ? Theme.spacingS : 0 readonly property int mediaToClockGap: mediaMaxWidth > 0 ? Theme.spacingS : 0
readonly property int clockToRightGap: validLayout ? Math.max(0, rightSectionLeftEdge - clockRightEdge) : 1000 readonly property int clockToRightGap: validLayout ? Math.max(0, rightSectionLeftEdge - clockRightEdge) : 1000
readonly property bool spacingTight: !barWindow.isVertical && validLayout && (leftToMediaGap < 150 || clockToRightGap < 100) readonly property bool spacingTight: !_barIsVertical && validLayout && (leftToMediaGap < 150 || clockToRightGap < 100)
readonly property bool overlapping: !barWindow.isVertical && validLayout && (leftToMediaGap < 100 || clockToRightGap < 50) readonly property bool overlapping: !_barIsVertical && validLayout && (leftToMediaGap < 100 || clockToRightGap < 50)
function getWidgetEnabled(enabled) { function getWidgetEnabled(enabled) {
return enabled !== false; return enabled !== false;
@@ -761,7 +830,7 @@ Item {
WorkspaceSwitcher { WorkspaceSwitcher {
axis: barWindow.axis axis: barWindow.axis
screenName: barWindow.screenName screenName: _barScreenName
widgetHeight: barWindow.widgetThickness widgetHeight: barWindow.widgetThickness
barThickness: barWindow.effectiveBarThickness barThickness: barWindow.effectiveBarThickness
parentScreen: barWindow.screen parentScreen: barWindow.screen
@@ -1378,8 +1447,8 @@ Item {
id: spacerComponent id: spacerComponent
Item { Item {
width: barWindow.isVertical ? barWindow.widgetThickness : (parent.spacerSize || 20) width: _barIsVertical ? barWindow.widgetThickness : (parent.spacerSize || 20)
height: barWindow.isVertical ? (parent.spacerSize || 20) : barWindow.widgetThickness height: _barIsVertical ? (parent.spacerSize || 20) : barWindow.widgetThickness
implicitWidth: width implicitWidth: width
implicitHeight: height implicitHeight: height
@@ -1408,14 +1477,14 @@ Item {
id: separatorComponent id: separatorComponent
Item { Item {
width: barWindow.isVertical ? parent.barThickness : 1 width: _barIsVertical ? parent.barThickness : 1
height: barWindow.isVertical ? 1 : parent.barThickness height: _barIsVertical ? 1 : parent.barThickness
implicitWidth: width implicitWidth: width
implicitHeight: height implicitHeight: height
Rectangle { Rectangle {
width: barWindow.isVertical ? parent.width * 0.6 : 1 width: _barIsVertical ? parent.width * 0.6 : 1
height: barWindow.isVertical ? 1 : parent.height * 0.6 height: _barIsVertical ? 1 : parent.height * 0.6
anchors.centerIn: parent anchors.centerIn: parent
color: Theme.outline color: Theme.outline
opacity: 0.3 opacity: 0.3
@@ -510,17 +510,6 @@ PanelWindow {
property var nativeInhibitor: null property var nativeInhibitor: null
Component.onCompleted: { Component.onCompleted: {
if (SettingsData.forceStatusBarLayoutRefresh) {
SettingsData.forceStatusBarLayoutRefresh.connect(() => {
Qt.callLater(() => {
stackContainer.visible = false;
Qt.callLater(() => {
stackContainer.visible = true;
});
});
});
}
updateGpuTempConfig(); updateGpuTempConfig();
_updateBackgroundAlpha(); _updateBackgroundAlpha();
_updateHasMaximizedToplevel(); _updateHasMaximizedToplevel();
+18 -10
View File
@@ -202,18 +202,21 @@ Variants {
ConnectedModeState.setDockSlide(dock._dockScreenName, dockSlide.x, dockSlide.y); ConnectedModeState.setDockSlide(dock._dockScreenName, dockSlide.x, dockSlide.y);
} }
property bool _slideSyncPending: false DeferredAction {
id: dockSlideSync
enabled: SettingsData.connectedFrameModeActive
onTriggered: dock._syncDockSlide()
}
function _queueSlideSync() { function _queueSlideSync() {
if (!SettingsData.connectedFrameModeActive) if (!SettingsData.connectedFrameModeActive)
return; return;
if (_slideSyncPending) dockSlideSync.schedule();
return;
_slideSyncPending = true;
Qt.callLater(dock._flushSlideSync);
} }
function _flushSlideSync() {
_slideSyncPending = false; DeferredAction {
dock._syncDockSlide(); id: dockChromeSync
onTriggered: dock._syncDockChromeState()
} }
property bool contextMenuOpen: (dockVariants.contextMenu && dockVariants.contextMenu.visible && dockVariants.contextMenu.screen === modelData) property bool contextMenuOpen: (dockVariants.contextMenu && dockVariants.contextMenu.visible && dockVariants.contextMenu.screen === modelData)
@@ -390,8 +393,12 @@ Variants {
} }
} }
Component.onCompleted: Qt.callLater(() => dock._syncDockChromeState()) Component.onCompleted: dockChromeSync.schedule()
Component.onDestruction: ConnectedModeState.clearDockState(dock._dockScreenName) Component.onDestruction: {
dockChromeSync.cancel();
dockSlideSync.cancel();
ConnectedModeState.clearDockState(dock._dockScreenName);
}
onRevealChanged: dock._syncDockChromeState() onRevealChanged: dock._syncDockChromeState()
onWidthChanged: dock._syncDockChromeState() onWidthChanged: dock._syncDockChromeState()
@@ -404,6 +411,7 @@ Variants {
Connections { Connections {
target: SettingsData target: SettingsData
function onConnectedFrameModeActiveChanged() { function onConnectedFrameModeActiveChanged() {
dockSlideSync.cancel();
dock._syncDockChromeState(); dock._syncDockChromeState();
} }
} }
+11 -8
View File
@@ -1195,16 +1195,16 @@ PanelWindow {
// Coalesce bursts of settings-change signals into a single _buildBlur() call // Coalesce bursts of settings-change signals into a single _buildBlur() call
// on the next event loop tick. // on the next event loop tick.
property bool _blurRebuildPending: false DeferredAction {
id: blurRebuildAction
onTriggered: win._runBlurRebuild()
}
function _scheduleBlurRebuild() { function _scheduleBlurRebuild() {
if (_blurRebuildPending) blurRebuildAction.schedule();
return;
_blurRebuildPending = true;
Qt.callLater(_runBlurRebuild);
} }
function _runBlurRebuild() { function _runBlurRebuild() {
_blurRebuildPending = false; _buildBlur();
win._buildBlur();
} }
Connections { Connections {
@@ -1257,7 +1257,10 @@ PanelWindow {
} }
Component.onCompleted: win._scheduleBlurRebuild() Component.onCompleted: win._scheduleBlurRebuild()
Component.onDestruction: win._teardownBlur() Component.onDestruction: {
blurRebuildAction.cancel();
win._teardownBlur();
}
FrameBorder { FrameBorder {
anchors.fill: parent anchors.fill: parent
+20 -11
View File
@@ -18,13 +18,12 @@ Singleton {
function registerWidget(widgetId, screenName, widgetRef) { function registerWidget(widgetId, screenName, widgetRef) {
if (!widgetId || !screenName || !widgetRef) if (!widgetId || !screenName || !widgetRef)
return; return;
if (typeof widgetRegistry !== "object" || widgetRegistry === null)
widgetRegistry = ({});
if (!widgetRegistry[widgetId]) const nextRegistry = (typeof widgetRegistry === "object" && widgetRegistry !== null) ? Object.assign({}, widgetRegistry) : {};
widgetRegistry[widgetId] = {}; const screenMap = (typeof nextRegistry[widgetId] === "object" && nextRegistry[widgetId] !== null) ? Object.assign({}, nextRegistry[widgetId]) : {};
screenMap[screenName] = widgetRef;
widgetRegistry[widgetId][screenName] = widgetRef; nextRegistry[widgetId] = screenMap;
widgetRegistry = nextRegistry;
widgetRegistered(widgetId, screenName); widgetRegistered(widgetId, screenName);
} }
@@ -36,15 +35,21 @@ Singleton {
if (!widgetRegistry[widgetId]) if (!widgetRegistry[widgetId])
return; return;
delete widgetRegistry[widgetId][screenName]; const nextRegistry = Object.assign({}, widgetRegistry);
if (Object.keys(widgetRegistry[widgetId]).length === 0) const screenMap = (typeof nextRegistry[widgetId] === "object" && nextRegistry[widgetId] !== null) ? Object.assign({}, nextRegistry[widgetId]) : {};
delete widgetRegistry[widgetId]; delete screenMap[screenName];
if (Object.keys(screenMap).length === 0) {
delete nextRegistry[widgetId];
} else {
nextRegistry[widgetId] = screenMap;
}
widgetRegistry = nextRegistry;
widgetUnregistered(widgetId, screenName); widgetUnregistered(widgetId, screenName);
} }
function getWidget(widgetId, screenName) { function getWidget(widgetId, screenName) {
if (!widgetRegistry[widgetId]) if (typeof widgetRegistry !== "object" || widgetRegistry === null || !widgetRegistry[widgetId])
return null; return null;
if (screenName) if (screenName)
return widgetRegistry[widgetId][screenName] || null; return widgetRegistry[widgetId][screenName] || null;
@@ -54,7 +59,7 @@ Singleton {
} }
function getWidgetOnFocusedScreen(widgetId) { function getWidgetOnFocusedScreen(widgetId) {
if (!widgetRegistry[widgetId]) if (typeof widgetRegistry !== "object" || widgetRegistry === null || !widgetRegistry[widgetId])
return null; return null;
const focusedScreen = getFocusedScreenName(); const focusedScreen = getFocusedScreenName();
@@ -78,10 +83,14 @@ Singleton {
} }
function getRegisteredWidgetIds() { function getRegisteredWidgetIds() {
if (typeof widgetRegistry !== "object" || widgetRegistry === null)
return [];
return Object.keys(widgetRegistry); return Object.keys(widgetRegistry);
} }
function hasWidget(widgetId) { function hasWidget(widgetId) {
if (typeof widgetRegistry !== "object" || widgetRegistry === null)
return false;
return widgetRegistry[widgetId] && Object.keys(widgetRegistry[widgetId]).length > 0; return widgetRegistry[widgetId] && Object.keys(widgetRegistry[widgetId]).length > 0;
} }