1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-04-06 22:02:07 -04:00

(frameMode): Restore user settings when exiting frame mode

- Align blur settings in non-FrameMode motion settings
This commit is contained in:
purian23
2026-04-06 17:48:59 -04:00
parent 20d208b8bf
commit 2261883426
6 changed files with 217 additions and 12 deletions

View File

@@ -237,6 +237,21 @@ Singleton {
onFrameBlurEnabledChanged: saveSettings()
property int previousDirectionalMode: 1
onPreviousDirectionalModeChanged: saveSettings()
property var connectedFrameBarStyleBackups: ({})
onConnectedFrameBarStyleBackupsChanged: saveSettings()
readonly property bool connectedFrameModeActive: frameEnabled
&& motionEffect === SettingsData.AnimationEffect.Directional
&& directionalAnimationMode === 3
onConnectedFrameModeActiveChanged: {
if (_loading)
return;
if (connectedFrameModeActive) {
_captureConnectedFrameBarStyleBackups(barConfigs, true);
_enforceConnectedModeBarStyleReset();
} else {
_restoreConnectedFrameBarStyleBackups();
}
}
readonly property color effectiveFrameColor: {
const fc = frameColor;
@@ -1331,6 +1346,7 @@ Singleton {
_loading = false;
}
loadPluginSettings();
Qt.callLater(() => _reconcileConnectedFrameBarStyles());
}
property var _pendingMigration: null
@@ -1444,6 +1460,149 @@ Singleton {
pluginSettingsFile.setText(JSON.stringify(pluginSettings, null, 2));
}
function _connectedFrameBarStyleSnapshot(config) {
return {
"shadowIntensity": config?.shadowIntensity ?? 0,
"squareCorners": config?.squareCorners ?? false,
"gothCornersEnabled": config?.gothCornersEnabled ?? false,
"borderEnabled": config?.borderEnabled ?? false
};
}
function _hasConnectedFrameBarStyleBackups() {
return connectedFrameBarStyleBackups && Object.keys(connectedFrameBarStyleBackups).length > 0;
}
function _captureConnectedFrameBarStyleBackups(configs, overwriteExisting) {
if (!Array.isArray(configs))
return;
const nextBackups = JSON.parse(JSON.stringify(connectedFrameBarStyleBackups || {}));
const validIds = {};
let changed = false;
for (let i = 0; i < configs.length; i++) {
const config = configs[i];
if (!config?.id)
continue;
validIds[config.id] = true;
if (!overwriteExisting && nextBackups[config.id] !== undefined)
continue;
const snapshot = _connectedFrameBarStyleSnapshot(config);
if (JSON.stringify(nextBackups[config.id]) !== JSON.stringify(snapshot)) {
nextBackups[config.id] = snapshot;
changed = true;
}
}
if (overwriteExisting) {
for (const barId in nextBackups) {
if (validIds[barId])
continue;
delete nextBackups[barId];
changed = true;
}
}
if (changed)
connectedFrameBarStyleBackups = nextBackups;
}
function _restoreConnectedFrameBarStyleBackups() {
if (!_hasConnectedFrameBarStyleBackups())
return;
const backups = connectedFrameBarStyleBackups || {};
const configs = JSON.parse(JSON.stringify(barConfigs));
let changed = false;
for (let i = 0; i < configs.length; i++) {
const backup = backups[configs[i].id];
if (!backup)
continue;
for (const key in backup) {
if (configs[i][key] === backup[key])
continue;
configs[i][key] = backup[key];
changed = true;
}
}
if (changed)
barConfigs = configs;
connectedFrameBarStyleBackups = ({});
if (changed)
updateBarConfigs();
}
function _reconcileConnectedFrameBarStyles() {
if (connectedFrameModeActive) {
if (!_hasConnectedFrameBarStyleBackups())
_captureConnectedFrameBarStyleBackups(barConfigs, true);
_enforceConnectedModeBarStyleReset();
return;
}
_restoreConnectedFrameBarStyleBackups();
}
function _sanitizeBarConfigForConnectedFrame(config) {
if (!connectedFrameModeActive || !config)
return config;
let changed = false;
const sanitized = Object.assign({}, config);
if ((sanitized.shadowIntensity ?? 0) !== 0) {
sanitized.shadowIntensity = 0;
changed = true;
}
if (sanitized.squareCorners ?? false) {
sanitized.squareCorners = false;
changed = true;
}
if (sanitized.gothCornersEnabled ?? false) {
sanitized.gothCornersEnabled = false;
changed = true;
}
if (sanitized.borderEnabled ?? false) {
sanitized.borderEnabled = false;
changed = true;
}
return changed ? sanitized : config;
}
function _sanitizeBarConfigsForConnectedFrame(configs) {
if (!connectedFrameModeActive || !Array.isArray(configs))
return {
"configs": configs,
"changed": false
};
let changed = false;
const sanitizedConfigs = configs.map(config => {
const sanitized = _sanitizeBarConfigForConnectedFrame(config);
if (sanitized !== config)
changed = true;
return sanitized;
});
return {
"configs": changed ? sanitizedConfigs : configs,
"changed": changed
};
}
function _enforceConnectedModeBarStyleReset() {
const result = _sanitizeBarConfigsForConnectedFrame(barConfigs);
if (!result.changed)
return;
barConfigs = result.configs;
updateBarConfigs();
}
function detectAvailableIconThemes() {
const xdgDataDirs = Quickshell.env("XDG_DATA_DIRS") || "";
const localData = Paths.strip(StandardPaths.writableLocation(StandardPaths.GenericDataLocation));
@@ -1591,7 +1750,7 @@ Singleton {
const spacing = barSpacing !== undefined ? barSpacing : (defaultBar?.spacing ?? 4);
const position = barPosition !== undefined ? barPosition : (defaultBar?.position ?? SettingsData.Position.Top);
const rawBottomGap = barConfig ? (barConfig.bottomGap !== undefined ? barConfig.bottomGap : (defaultBar?.bottomGap ?? 0)) : (defaultBar?.bottomGap ?? 0);
const isConnected = frameEnabled && motionEffect === 1 && directionalAnimationMode === 3;
const isConnected = connectedFrameModeActive;
const bottomGap = isConnected ? 0 : Math.max(0, rawBottomGap);
const useAutoGaps = (barConfig && barConfig.popupGapsAuto !== undefined) ? barConfig.popupGapsAuto : (defaultBar?.popupGapsAuto ?? true);
@@ -1715,7 +1874,7 @@ Singleton {
const screenWidth = screen.width;
const screenHeight = screen.height;
const position = barPosition !== undefined ? barPosition : (defaultBar?.position ?? SettingsData.Position.Top);
const isConnected = frameEnabled && motionEffect === 1 && directionalAnimationMode === 3;
const isConnected = connectedFrameModeActive;
const rawBottomGap = barConfig ? (barConfig.bottomGap !== undefined ? barConfig.bottomGap : (defaultBar?.bottomGap ?? 0)) : (defaultBar?.bottomGap ?? 0);
const bottomGap = isConnected ? 0 : rawBottomGap;
@@ -1830,7 +1989,9 @@ Singleton {
function addBarConfig(config) {
const configs = JSON.parse(JSON.stringify(barConfigs));
configs.push(config);
barConfigs = configs;
if (connectedFrameModeActive)
_captureConnectedFrameBarStyleBackups(configs, false);
barConfigs = _sanitizeBarConfigsForConnectedFrame(configs).configs;
updateBarConfigs();
}
@@ -1842,7 +2003,7 @@ Singleton {
const positionChanged = updates.position !== undefined && configs[index].position !== updates.position;
Object.assign(configs[index], updates);
barConfigs = configs;
barConfigs = _sanitizeBarConfigsForConnectedFrame(configs).configs;
updateBarConfigs();
if (positionChanged) {
@@ -1896,6 +2057,11 @@ Singleton {
return;
const configs = barConfigs.filter(cfg => cfg.id !== barId);
barConfigs = configs;
if (connectedFrameBarStyleBackups?.[barId] !== undefined) {
const nextBackups = JSON.parse(JSON.stringify(connectedFrameBarStyleBackups || {}));
delete nextBackups[barId];
connectedFrameBarStyleBackups = nextBackups;
}
updateBarConfigs();
}

View File

@@ -445,6 +445,7 @@ var SPEC = {
displayProfileAutoSelect: { def: false },
displayShowDisconnected: { def: false },
displaySnapToEdge: { def: true },
connectedFrameBarStyleBackups: { def: {} },
barConfigs: {
def: [{

View File

@@ -27,6 +27,7 @@ Item {
const pos = selectedBarConfig?.position ?? SettingsData.Position.Top;
return pos === SettingsData.Position.Left || pos === SettingsData.Position.Right;
}
readonly property bool connectedFrameModeActive: SettingsData.connectedFrameModeActive
Timer {
id: horizontalBarChangeDebounce
@@ -1110,6 +1111,35 @@ Item {
}
}
Item {
visible: dankBarTab.connectedFrameModeActive
width: parent.width
implicitHeight: connectedFrameStyleNote.implicitHeight + Theme.spacingS * 2
Row {
id: connectedFrameStyleNote
x: Theme.spacingM
width: parent.width - Theme.spacingM * 2
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingS
DankIcon {
name: "frame_source"
size: Theme.fontSizeMedium
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: I18n.tr("Connected Frame mode keeps bar shadow override, border, and corner overrides off while active")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
wrapMode: Text.WordWrap
width: parent.width - Theme.fontSizeMedium - Theme.spacingS
}
}
}
SettingsCard {
id: shadowCard
iconName: "layers"
@@ -1118,6 +1148,8 @@ Item {
collapsible: true
expanded: true
visible: selectedBarConfig?.enabled
enabled: !dankBarTab.connectedFrameModeActive
opacity: dankBarTab.connectedFrameModeActive ? 0.5 : 1.0
readonly property bool shadowActive: (selectedBarConfig?.shadowIntensity ?? 0) > 0
readonly property bool isCustomColor: (selectedBarConfig?.shadowColorMode ?? "default") === "custom"
@@ -1451,6 +1483,8 @@ Item {
iconName: "border_style"
title: I18n.tr("Border")
visible: selectedBarConfig?.enabled
enabled: !dankBarTab.connectedFrameModeActive
opacity: dankBarTab.connectedFrameModeActive ? 0.5 : 1.0
checked: selectedBarConfig?.borderEnabled ?? false
onToggled: checked => SettingsData.updateBarConfig(selectedBarId, {
borderEnabled: checked

View File

@@ -281,7 +281,7 @@ Item {
tags: ["frame", "connected", "popout", "corner", "animation"]
text: I18n.tr("Connected Mode")
description: I18n.tr("Popouts emerge flush from the bar edge as one continuous piece (based on Slide)")
checked: SettingsData.motionEffect === 1 && SettingsData.directionalAnimationMode === 3
checked: SettingsData.connectedFrameModeActive
onToggled: checked => {
if (checked) {
if (SettingsData.directionalAnimationMode !== 3)

View File

@@ -207,7 +207,7 @@ Item {
settingKey: "directionalAnimationMode"
text: I18n.tr("Directional Behavior")
description: {
if (SettingsData.directionalAnimationMode === 3 && SettingsData.frameEnabled)
if (SettingsData.connectedFrameModeActive)
return I18n.tr("Popouts emerge flush from the bar edge as a single continuous piece, with corner connectors bridging the junction");
return I18n.tr("How the popout emerges from the DankBar");
}

View File

@@ -539,9 +539,13 @@ Item {
blurEnabled: root.effectiveSurfaceBlurEnabled
readonly property real s: Math.min(1, contentContainer.scaleValue)
readonly property bool trackBlurFromBarEdge: Theme.isConnectedEffect
|| (typeof SettingsData !== "undefined"
&& Theme.isDirectionalEffect
&& SettingsData.directionalAnimationMode !== 2)
// Connected mode: clamp animY/animX to popup bounds so blur grows from the
// bar edge in sync with the slide-in animation, never entering the bar area.
// Directional popouts clip to the bar edge, so the blur needs to grow from
// that same edge instead of translating through the bar before settling.
readonly property real _dyClamp: (contentContainer.barTop || contentContainer.barBottom)
? Math.max(-contentContainer.height, Math.min(contentContainer.animY, contentContainer.height))
: 0
@@ -549,23 +553,23 @@ Item {
? Math.max(-contentContainer.width, Math.min(contentContainer.animX, contentContainer.width))
: 0
blurX: Theme.isConnectedEffect
blurX: trackBlurFromBarEdge
? contentContainer.x + (contentContainer.barRight ? _dxClamp : 0)
: contentContainer.x + contentContainer.width * (1 - s) * 0.5
+ Theme.snap(contentContainer.animX, root.dpr)
- contentContainer.horizontalConnectorExtent * s
blurY: Theme.isConnectedEffect
blurY: trackBlurFromBarEdge
? contentContainer.y + (contentContainer.barBottom ? _dyClamp : 0)
: contentContainer.y + contentContainer.height * (1 - s) * 0.5
+ Theme.snap(contentContainer.animY, root.dpr)
- contentContainer.verticalConnectorExtent * s
blurWidth: (shouldBeVisible && contentWrapper.opacity > 0)
? (Theme.isConnectedEffect
? (trackBlurFromBarEdge
? Math.max(0, contentContainer.width - Math.abs(_dxClamp))
: (contentContainer.width + contentContainer.horizontalConnectorExtent * 2) * s)
: 0
blurHeight: (shouldBeVisible && contentWrapper.opacity > 0)
? (Theme.isConnectedEffect
? (trackBlurFromBarEdge
? Math.max(0, contentContainer.height - Math.abs(_dyClamp))
: (contentContainer.height + contentContainer.verticalConnectorExtent * 2) * s)
: 0