mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-05 21:15:38 -05:00
Compare commits
27 Commits
v0.1.16
...
wip-filebr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a5d612599 | ||
|
|
205c43181b | ||
|
|
05a72abf41 | ||
|
|
14262ba510 | ||
|
|
d847b1e09c | ||
|
|
0086e42a86 | ||
|
|
7474d5a7bf | ||
|
|
5696a36115 | ||
|
|
3cdc1a9c81 | ||
|
|
b095fb9005 | ||
|
|
ce6c16214c | ||
|
|
b6f7f2734e | ||
|
|
4db55e4d77 | ||
|
|
b21f6e80b3 | ||
|
|
a804fb849e | ||
|
|
4ca91cd9f7 | ||
|
|
16e1b587b4 | ||
|
|
5e2756d200 | ||
|
|
ce9ab22ae1 | ||
|
|
72ad35e1f9 | ||
|
|
c0d110cde0 | ||
|
|
b9d5deb2ae | ||
|
|
d4b13ef46b | ||
|
|
748d9e342e | ||
|
|
f49312fc0e | ||
|
|
e0d8bbb243 | ||
|
|
153f2a49f8 |
58
.github/workflows/copr-release.yml
vendored
58
.github/workflows/copr-release.yml
vendored
@@ -1,6 +1,9 @@
|
||||
name: DMS Copr Stable Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
@@ -28,6 +31,10 @@ jobs:
|
||||
VERSION="${{ github.event.release.tag_name }}"
|
||||
VERSION="${VERSION#v}"
|
||||
echo "Using release version: $VERSION"
|
||||
elif [ "${{ github.event_name }}" = "push" ] && [[ "${{ github.ref }}" == refs/tags/* ]]; then
|
||||
VERSION="${{ github.ref_name }}"
|
||||
VERSION="${VERSION#v}"
|
||||
echo "Using tag version: $VERSION"
|
||||
else
|
||||
# Fallback to latest release
|
||||
VERSION=$(curl -s https://api.github.com/repos/AvengeMedia/DankMaterialShell/releases/latest | jq -r '.tag_name' | sed 's/^v//')
|
||||
@@ -49,7 +56,7 @@ jobs:
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
cd ~/rpmbuild/SOURCES
|
||||
|
||||
echo "📦 Downloading DMS release assets for v${VERSION}..."
|
||||
echo "📦 Downloading DMS QML source for v${VERSION}..."
|
||||
|
||||
# Download DMS QML source
|
||||
wget "https://github.com/AvengeMedia/DankMaterialShell/releases/download/v${VERSION}/dms-qml.tar.gz" || {
|
||||
@@ -57,21 +64,8 @@ jobs:
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Download dms-cli (always use latest)
|
||||
echo "📦 Downloading latest dms-cli..."
|
||||
wget "https://github.com/AvengeMedia/danklinux/releases/latest/download/dms-distropkg-amd64.gz" || {
|
||||
echo "❌ Failed to download dms-cli"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Download dgop (always use latest)
|
||||
echo "📦 Downloading latest dgop..."
|
||||
wget "https://github.com/AvengeMedia/dgop/releases/latest/download/dgop-linux-amd64.gz" || {
|
||||
echo "❌ Failed to download dgop"
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "✅ All sources downloaded"
|
||||
echo "✅ Source downloaded"
|
||||
echo "Note: dms-cli and dgop binaries will be downloaded during build based on target architecture"
|
||||
ls -lh
|
||||
|
||||
- name: Generate stable spec file
|
||||
@@ -95,10 +89,9 @@ jobs:
|
||||
URL: https://github.com/AvengeMedia/DankMaterialShell
|
||||
|
||||
Source0: dms-qml.tar.gz
|
||||
Source1: dms-distropkg-amd64.gz
|
||||
Source2: dgop-linux-amd64.gz
|
||||
|
||||
BuildRequires: gzip
|
||||
BuildRequires: wget
|
||||
|
||||
Requires: (quickshell or quickshell-git)
|
||||
Requires: dms-cli
|
||||
@@ -150,10 +143,35 @@ jobs:
|
||||
%prep
|
||||
%setup -q -c -n dms-qml
|
||||
|
||||
gunzip -c %{SOURCE1} > %{_builddir}/dms-cli
|
||||
# Download architecture-specific binaries during build
|
||||
# This ensures the correct architecture is used for each build target
|
||||
case "%{_arch}" in
|
||||
x86_64)
|
||||
ARCH_SUFFIX="amd64"
|
||||
;;
|
||||
aarch64)
|
||||
ARCH_SUFFIX="arm64"
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported architecture: %{_arch}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Download dms-cli for target architecture
|
||||
wget -O %{_builddir}/dms-cli.gz "https://github.com/AvengeMedia/danklinux/releases/latest/download/dms-distropkg-${ARCH_SUFFIX}.gz" || {
|
||||
echo "Failed to download dms-cli for architecture %{_arch}"
|
||||
exit 1
|
||||
}
|
||||
gunzip -c %{_builddir}/dms-cli.gz > %{_builddir}/dms-cli
|
||||
chmod +x %{_builddir}/dms-cli
|
||||
|
||||
gunzip -c %{SOURCE2} > %{_builddir}/dgop
|
||||
# Download dgop for target architecture
|
||||
wget -O %{_builddir}/dgop.gz "https://github.com/AvengeMedia/dgop/releases/latest/download/dgop-linux-${ARCH_SUFFIX}.gz" || {
|
||||
echo "Failed to download dgop for architecture %{_arch}"
|
||||
exit 1
|
||||
}
|
||||
gunzip -c %{_builddir}/dgop.gz > %{_builddir}/dgop
|
||||
chmod +x %{_builddir}/dgop
|
||||
|
||||
%build
|
||||
|
||||
144
.github/workflows/poeditor-export.yml
vendored
144
.github/workflows/poeditor-export.yml
vendored
@@ -10,106 +10,98 @@ concurrency:
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
diff-and-trigger:
|
||||
sync-translations:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: ja
|
||||
po_lang: "ja"
|
||||
repo_file: "translations/poexports/ja.json"
|
||||
webhook_secret: "POEDITOR_WEBHOOK_JA"
|
||||
|
||||
- name: zh_hans
|
||||
po_lang: "zh-Hans"
|
||||
repo_file: "translations/poexports/zh_CN.json"
|
||||
webhook_secret: "POEDITOR_WEBHOOK_ZH_HANS"
|
||||
|
||||
- name: pt
|
||||
po_lang: "pt-br"
|
||||
repo_file: "translations/poexports/pt.json"
|
||||
webhook_secret: "POEDITOR_WEBHOOK_PT"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install jq
|
||||
run: sudo apt-get update && sudo apt-get install -y jq
|
||||
|
||||
- name: Export from POEditor (key/value JSON) and compare
|
||||
id: diffcheck
|
||||
- name: Export and update translations from POEditor
|
||||
env:
|
||||
API_TOKEN: ${{ secrets.POEDITOR_API_TOKEN }}
|
||||
PROJECT_ID: ${{ secrets.POEDITOR_PROJECT_ID }}
|
||||
PO_LANG: ${{ matrix.po_lang }}
|
||||
REPO_FILE: ${{ matrix.repo_file }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
# 1) Request an export URL for key/value json
|
||||
echo "::group::POEditor export request"
|
||||
RESP=$(curl -sS -X POST https://api.poeditor.com/v2/projects/export \
|
||||
-d api_token="$API_TOKEN" \
|
||||
-d id="$PROJECT_ID" \
|
||||
-d language="$PO_LANG" \
|
||||
-d type="key_value_json")
|
||||
echo "$RESP" | jq -r '.'
|
||||
STATUS=$(echo "$RESP" | jq -r '.response.status')
|
||||
if [[ "$STATUS" != "success" ]]; then
|
||||
echo "POEditor export request failed: $RESP" >&2
|
||||
exit 1
|
||||
fi
|
||||
URL=$(echo "$RESP" | jq -r '.result.url')
|
||||
if [[ -z "$URL" || "$URL" == "null" ]]; then
|
||||
echo "No export URL returned from POEditor." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "::endgroup::"
|
||||
LANGUAGES=(
|
||||
"ja:translations/poexports/ja.json"
|
||||
"zh-Hans:translations/poexports/zh_CN.json"
|
||||
"pt-br:translations/poexports/pt.json"
|
||||
)
|
||||
|
||||
# 2) Download exported content
|
||||
curl -sS -L "$URL" -o /tmp/po_export.json
|
||||
ANY_CHANGED=false
|
||||
|
||||
# 3) Normalize JSON (sorted keys) for stable diff
|
||||
jq -S . /tmp/po_export.json > /tmp/po_export.norm.json
|
||||
for lang_pair in "${LANGUAGES[@]}"; do
|
||||
IFS=':' read -r PO_LANG REPO_FILE <<< "$lang_pair"
|
||||
|
||||
# 4) Normalize repo file (or empty {}) and diff
|
||||
if [[ -f "$REPO_FILE" ]]; then
|
||||
jq -S . "$REPO_FILE" > /tmp/repo.norm.json || echo "{}" > /tmp/repo.norm.json
|
||||
else
|
||||
echo "{}" > /tmp/repo.norm.json
|
||||
fi
|
||||
echo "::group::Processing $PO_LANG"
|
||||
|
||||
# 5) Set output changed=true|false
|
||||
if diff -q /tmp/po_export.norm.json /tmp/repo.norm.json >/dev/null; then
|
||||
echo "changed=false" >> "$GITHUB_OUTPUT"
|
||||
echo "No changes for $PO_LANG"
|
||||
else
|
||||
echo "changed=true" >> "$GITHUB_OUTPUT"
|
||||
echo "Detected changes for $PO_LANG"
|
||||
fi
|
||||
RESP=$(curl -sS -X POST https://api.poeditor.com/v2/projects/export \
|
||||
-d api_token="$API_TOKEN" \
|
||||
-d id="$PROJECT_ID" \
|
||||
-d language="$PO_LANG" \
|
||||
-d type="key_value_json")
|
||||
|
||||
- name: Trigger POEditor webhook for this language, if changed
|
||||
if: steps.diffcheck.outputs.changed == 'true'
|
||||
env:
|
||||
WEBHOOK_URL: ${{ secrets[matrix.webhook_secret] }}
|
||||
STATUS=$(echo "$RESP" | jq -r '.response.status')
|
||||
if [[ "$STATUS" != "success" ]]; then
|
||||
echo "POEditor export request failed for $PO_LANG: $RESP" >&2
|
||||
continue
|
||||
fi
|
||||
|
||||
URL=$(echo "$RESP" | jq -r '.result.url')
|
||||
if [[ -z "$URL" || "$URL" == "null" ]]; then
|
||||
echo "No export URL returned for $PO_LANG" >&2
|
||||
continue
|
||||
fi
|
||||
|
||||
curl -sS -L "$URL" -o "/tmp/po_export_${PO_LANG}.json"
|
||||
jq -S . "/tmp/po_export_${PO_LANG}.json" > "/tmp/po_export_${PO_LANG}.norm.json"
|
||||
|
||||
if [[ -f "$REPO_FILE" ]]; then
|
||||
jq -S . "$REPO_FILE" > "/tmp/repo_${PO_LANG}.norm.json" || echo "{}" > "/tmp/repo_${PO_LANG}.norm.json"
|
||||
else
|
||||
echo "{}" > "/tmp/repo_${PO_LANG}.norm.json"
|
||||
fi
|
||||
|
||||
if diff -q "/tmp/po_export_${PO_LANG}.norm.json" "/tmp/repo_${PO_LANG}.norm.json" >/dev/null; then
|
||||
echo "No changes for $PO_LANG"
|
||||
else
|
||||
echo "Detected changes for $PO_LANG"
|
||||
mkdir -p "$(dirname "$REPO_FILE")"
|
||||
cp "/tmp/po_export_${PO_LANG}.norm.json" "$REPO_FILE"
|
||||
ANY_CHANGED=true
|
||||
fi
|
||||
|
||||
echo "::endgroup::"
|
||||
done
|
||||
|
||||
echo "any_changed=$ANY_CHANGED" >> "$GITHUB_OUTPUT"
|
||||
id: export
|
||||
|
||||
- name: Commit and push translation updates
|
||||
if: steps.export.outputs.any_changed == 'true'
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ -z "${WEBHOOK_URL:-}" ]]; then
|
||||
echo "Missing webhook secret for this language: ${{ matrix.webhook_secret }}" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "Calling POEditor export webhook for ${{ matrix.name }}"
|
||||
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
git add translations/poexports/*.json
|
||||
git commit -m "i18n: update translations"
|
||||
|
||||
for attempt in 1 2 3; do
|
||||
code=$(curl -sS -o /tmp/resp.txt -w '%{http_code}' -X POST "$WEBHOOK_URL" || true)
|
||||
if [[ "$code" == "200" || "$code" == "204" ]]; then
|
||||
echo "Webhook OK ($code)"
|
||||
if git push; then
|
||||
echo "Successfully pushed translation updates"
|
||||
exit 0
|
||||
fi
|
||||
echo "Attempt $attempt failed ($code) → $(cat /tmp/resp.txt)"
|
||||
sleep $((attempt*3))
|
||||
echo "Push attempt $attempt failed, pulling and retrying..."
|
||||
git pull --rebase
|
||||
sleep $((attempt*2))
|
||||
done
|
||||
echo "Webhook failed after retries." >&2
|
||||
|
||||
echo "Failed to push after retries" >&2
|
||||
exit 1
|
||||
|
||||
@@ -99,6 +99,7 @@ Singleton {
|
||||
|
||||
property bool showWorkspaceIndex: false
|
||||
property bool showWorkspacePadding: false
|
||||
property bool workspaceScrolling: false
|
||||
property bool showWorkspaceApps: false
|
||||
property int maxWorkspaceIcons: 3
|
||||
property bool workspacesPerMonitor: true
|
||||
@@ -238,6 +239,7 @@ Singleton {
|
||||
property bool osdAlwaysShowValue: false
|
||||
|
||||
property bool powerActionConfirm: true
|
||||
property string customPowerActionLock: ""
|
||||
property string customPowerActionLogout: ""
|
||||
property string customPowerActionSuspend: ""
|
||||
property string customPowerActionHibernate: ""
|
||||
@@ -361,6 +363,7 @@ Singleton {
|
||||
]
|
||||
showWorkspaceIndex = settings.showWorkspaceIndex !== undefined ? settings.showWorkspaceIndex : false
|
||||
showWorkspacePadding = settings.showWorkspacePadding !== undefined ? settings.showWorkspacePadding : false
|
||||
workspaceScrolling = settings.workspaceScrolling !== undefined ? settings.workspaceScrolling : false
|
||||
showWorkspaceApps = settings.showWorkspaceApps !== undefined ? settings.showWorkspaceApps : false
|
||||
maxWorkspaceIcons = settings.maxWorkspaceIcons !== undefined ? settings.maxWorkspaceIcons : 3
|
||||
workspaceNameIcons = settings.workspaceNameIcons !== undefined ? settings.workspaceNameIcons : ({})
|
||||
@@ -452,6 +455,7 @@ Singleton {
|
||||
notificationPopupPosition = settings.notificationPopupPosition !== undefined ? settings.notificationPopupPosition : SettingsData.Position.Top
|
||||
osdAlwaysShowValue = settings.osdAlwaysShowValue !== undefined ? settings.osdAlwaysShowValue : false
|
||||
powerActionConfirm = settings.powerActionConfirm !== undefined ? settings.powerActionConfirm : true
|
||||
customPowerActionLock = settings.customPowerActionLock != undefined ? settings.customPowerActionLock : ""
|
||||
customPowerActionLogout = settings.customPowerActionLogout != undefined ? settings.customPowerActionLogout : ""
|
||||
customPowerActionSuspend = settings.customPowerActionSuspend != undefined ? settings.customPowerActionSuspend : ""
|
||||
customPowerActionHibernate = settings.customPowerActionHibernate != undefined ? settings.customPowerActionHibernate : ""
|
||||
@@ -561,6 +565,7 @@ Singleton {
|
||||
"controlCenterShowAudioIcon": controlCenterShowAudioIcon,
|
||||
"controlCenterWidgets": controlCenterWidgets,
|
||||
"showWorkspaceIndex": showWorkspaceIndex,
|
||||
"workspaceScrolling": workspaceScrolling,
|
||||
"showWorkspacePadding": showWorkspacePadding,
|
||||
"showWorkspaceApps": showWorkspaceApps,
|
||||
"maxWorkspaceIcons": maxWorkspaceIcons,
|
||||
@@ -646,6 +651,7 @@ Singleton {
|
||||
"notificationPopupPosition": notificationPopupPosition,
|
||||
"osdAlwaysShowValue": osdAlwaysShowValue,
|
||||
"powerActionConfirm": powerActionConfirm,
|
||||
"customPowerActionLock": customPowerActionLock,
|
||||
"customPowerActionLogout": customPowerActionLogout,
|
||||
"customPowerActionSuspend": customPowerActionSuspend,
|
||||
"customPowerActionHibernate": customPowerActionHibernate,
|
||||
@@ -692,7 +698,7 @@ Singleton {
|
||||
"selectedGpuIndex", "enabledGpuPciIds", "showSystemTray", "showClock",
|
||||
"showNotificationButton", "showBattery", "showControlCenterButton",
|
||||
"controlCenterShowNetworkIcon", "controlCenterShowBluetoothIcon", "controlCenterShowAudioIcon",
|
||||
"controlCenterWidgets", "showWorkspaceIndex", "showWorkspacePadding", "showWorkspaceApps",
|
||||
"controlCenterWidgets", "showWorkspaceIndex", "workspaceScrolling", "showWorkspacePadding", "showWorkspaceApps",
|
||||
"maxWorkspaceIcons", "workspacesPerMonitor", "workspaceNameIcons", "waveProgressEnabled",
|
||||
"clockCompactMode", "focusedWindowCompactMode", "runningAppsCompactMode",
|
||||
"runningAppsCurrentWorkspace", "clockDateFormat", "lockDateFormat", "mediaSize",
|
||||
@@ -716,8 +722,8 @@ Singleton {
|
||||
"hideBrightnessSlider", "widgetBackgroundColor", "surfaceBase",
|
||||
"notificationTimeoutLow", "notificationTimeoutNormal", "notificationTimeoutCritical",
|
||||
"notificationPopupPosition", "osdAlwaysShowValue", "powerActionConfirm",
|
||||
"customPowerActionLogout", "customPowerActionSuspend", "customPowerActionHibernate",
|
||||
"customPowerActionReboot", "customPowerActionPowerOff",
|
||||
"customPowerActionLock", "customPowerActionLogout", "customPowerActionSuspend",
|
||||
"customPowerActionHibernate", "customPowerActionReboot", "customPowerActionPowerOff",
|
||||
"updaterUseCustomCommand", "updaterCustomCommand", "updaterTerminalAdditionalParams",
|
||||
"screenPreferences", "animationSpeed", "acMonitorTimeout", "acLockTimeout",
|
||||
"acSuspendTimeout", "acHibernateTimeout", "batteryMonitorTimeout", "batteryLockTimeout",
|
||||
@@ -1155,6 +1161,11 @@ Singleton {
|
||||
showWorkspaceIndex = enabled
|
||||
saveSettings()
|
||||
}
|
||||
|
||||
function setWorkspaceScrolling(enabled) {
|
||||
workspaceScrolling = enabled
|
||||
saveSettings()
|
||||
}
|
||||
|
||||
function setShowWorkspacePadding(enabled) {
|
||||
showWorkspacePadding = enabled
|
||||
@@ -1713,6 +1724,11 @@ Singleton {
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
function setCustomPowerActionLock(command) {
|
||||
customPowerActionLock = command;
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
function setCustomPowerActionLogout(command) {
|
||||
customPowerActionLogout = command;
|
||||
saveSettings();
|
||||
|
||||
954
DMSShell.qml
954
DMSShell.qml
@@ -25,515 +25,517 @@ import qs.Modules.DankBar.Popouts
|
||||
import qs.Modules.Plugins
|
||||
import qs.Services
|
||||
|
||||
|
||||
Item {
|
||||
id: root
|
||||
id: root
|
||||
|
||||
Instantiator {
|
||||
id: daemonPluginInstantiator
|
||||
asynchronous: true
|
||||
model: Object.keys(PluginService.pluginDaemonComponents)
|
||||
Instantiator {
|
||||
id: daemonPluginInstantiator
|
||||
asynchronous: true
|
||||
model: Object.keys(PluginService.pluginDaemonComponents)
|
||||
|
||||
delegate: Loader {
|
||||
id: daemonLoader
|
||||
property string pluginId: modelData
|
||||
sourceComponent: PluginService.pluginDaemonComponents[pluginId]
|
||||
delegate: Loader {
|
||||
id: daemonLoader
|
||||
property string pluginId: modelData
|
||||
sourceComponent: PluginService.pluginDaemonComponents[pluginId]
|
||||
|
||||
onLoaded: {
|
||||
if (item) {
|
||||
item.pluginService = PluginService
|
||||
if (item.popoutService !== undefined) {
|
||||
item.popoutService = PopoutService
|
||||
}
|
||||
item.pluginId = pluginId
|
||||
console.log("Daemon plugin loaded:", pluginId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WallpaperBackground {}
|
||||
|
||||
Lock {
|
||||
id: lock
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: dankBarLoader
|
||||
asynchronous: false
|
||||
|
||||
property var currentPosition: SettingsData.dankBarPosition
|
||||
property bool initialized: false
|
||||
|
||||
sourceComponent: DankBar {
|
||||
onColorPickerRequested: {
|
||||
if (colorPickerModal.shouldBeVisible) {
|
||||
colorPickerModal.close()
|
||||
} else {
|
||||
colorPickerModal.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
initialized = true
|
||||
}
|
||||
|
||||
onCurrentPositionChanged: {
|
||||
if (!initialized) return
|
||||
|
||||
const component = sourceComponent
|
||||
sourceComponent = null
|
||||
sourceComponent = component
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: dockLoader
|
||||
active: true
|
||||
asynchronous: false
|
||||
|
||||
property var currentPosition: SettingsData.dockPosition
|
||||
property bool initialized: false
|
||||
|
||||
sourceComponent: Dock {
|
||||
contextMenu: dockContextMenuLoader.item ? dockContextMenuLoader.item : null
|
||||
}
|
||||
|
||||
onLoaded: {
|
||||
if (item) {
|
||||
dockContextMenuLoader.active = true
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
initialized = true
|
||||
}
|
||||
|
||||
onCurrentPositionChanged: {
|
||||
if (!initialized) return
|
||||
|
||||
console.log("DEBUG: Dock position changed to:", currentPosition, "- recreating dock")
|
||||
const comp = sourceComponent
|
||||
sourceComponent = null
|
||||
sourceComponent = comp
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: dankDashPopoutLoader
|
||||
|
||||
active: false
|
||||
asynchronous: true
|
||||
|
||||
sourceComponent: Component {
|
||||
DankDashPopout {
|
||||
id: dankDashPopout
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.dankDashPopout = dankDashPopout
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: dockContextMenuLoader
|
||||
|
||||
active: false
|
||||
|
||||
DockContextMenu {
|
||||
id: dockContextMenu
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: notificationCenterLoader
|
||||
|
||||
active: false
|
||||
|
||||
NotificationCenterPopout {
|
||||
id: notificationCenter
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.notificationCenterPopout = notificationCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Variants {
|
||||
model: SettingsData.getFilteredScreens("notifications")
|
||||
|
||||
delegate: NotificationPopupManager {
|
||||
modelData: item
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: controlCenterLoader
|
||||
|
||||
active: false
|
||||
|
||||
property var modalRef: colorPickerModal
|
||||
property LazyLoader powerModalLoaderRef: powerMenuModalLoader
|
||||
|
||||
ControlCenterPopout {
|
||||
id: controlCenterPopout
|
||||
colorPickerModal: controlCenterLoader.modalRef
|
||||
powerMenuModalLoader: controlCenterLoader.powerModalLoaderRef
|
||||
|
||||
onLockRequested: {
|
||||
lock.activate()
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.controlCenterPopout = controlCenterPopout
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: wifiPasswordModalLoader
|
||||
|
||||
active: false
|
||||
|
||||
WifiPasswordModal {
|
||||
id: wifiPasswordModal
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.wifiPasswordModal = wifiPasswordModal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: networkInfoModalLoader
|
||||
|
||||
active: false
|
||||
|
||||
NetworkInfoModal {
|
||||
id: networkInfoModal
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.networkInfoModal = networkInfoModal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: batteryPopoutLoader
|
||||
|
||||
active: false
|
||||
|
||||
BatteryPopout {
|
||||
id: batteryPopout
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.batteryPopout = batteryPopout
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: vpnPopoutLoader
|
||||
|
||||
active: false
|
||||
|
||||
VpnPopout {
|
||||
id: vpnPopout
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.vpnPopout = vpnPopout
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: powerMenuLoader
|
||||
|
||||
active: false
|
||||
|
||||
PowerMenu {
|
||||
id: powerMenu
|
||||
|
||||
onPowerActionRequested: (action, title, message) => {
|
||||
if (SettingsData.powerActionConfirm) {
|
||||
powerConfirmModalLoader.active = true
|
||||
if (powerConfirmModalLoader.item) {
|
||||
powerConfirmModalLoader.item.confirmButtonColor = action === "poweroff" ? Theme.error : action === "reboot" ? Theme.warning : Theme.primary
|
||||
powerConfirmModalLoader.item.show(title, message, () => actionApply(action), function () {})
|
||||
onLoaded: {
|
||||
if (item) {
|
||||
item.pluginService = PluginService
|
||||
if (item.popoutService !== undefined) {
|
||||
item.popoutService = PopoutService
|
||||
}
|
||||
item.pluginId = pluginId
|
||||
console.log("Daemon plugin loaded:", pluginId)
|
||||
}
|
||||
} else {
|
||||
actionApply(action)
|
||||
}
|
||||
}
|
||||
|
||||
function actionApply(action) {
|
||||
switch (action) {
|
||||
case "logout":
|
||||
SessionService.logout()
|
||||
break
|
||||
case "suspend":
|
||||
SessionService.suspend()
|
||||
break
|
||||
case "hibernate":
|
||||
SessionService.hibernate()
|
||||
break
|
||||
case "reboot":
|
||||
SessionService.reboot()
|
||||
break
|
||||
case "poweroff":
|
||||
SessionService.poweroff()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: powerConfirmModalLoader
|
||||
WallpaperBackground {}
|
||||
|
||||
active: false
|
||||
Lock {
|
||||
id: lock
|
||||
}
|
||||
|
||||
ConfirmModal {
|
||||
id: powerConfirmModal
|
||||
}
|
||||
}
|
||||
Loader {
|
||||
id: dankBarLoader
|
||||
asynchronous: false
|
||||
|
||||
LazyLoader {
|
||||
id: processListPopoutLoader
|
||||
property var currentPosition: SettingsData.dankBarPosition
|
||||
property bool initialized: false
|
||||
|
||||
active: false
|
||||
|
||||
ProcessListPopout {
|
||||
id: processListPopout
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.processListPopout = processListPopout
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SettingsModal {
|
||||
id: settingsModal
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.settingsModal = settingsModal
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: appDrawerLoader
|
||||
|
||||
active: false
|
||||
|
||||
AppDrawerPopout {
|
||||
id: appDrawerPopout
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.appDrawerPopout = appDrawerPopout
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SpotlightModal {
|
||||
id: spotlightModal
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.spotlightModal = spotlightModal
|
||||
}
|
||||
}
|
||||
|
||||
ClipboardHistoryModal {
|
||||
id: clipboardHistoryModalPopup
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.clipboardHistoryModal = clipboardHistoryModalPopup
|
||||
}
|
||||
}
|
||||
|
||||
NotificationModal {
|
||||
id: notificationModal
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.notificationModal = notificationModal
|
||||
}
|
||||
}
|
||||
|
||||
DankColorPickerModal {
|
||||
id: colorPickerModal
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.colorPickerModal = colorPickerModal
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: processListModalLoader
|
||||
|
||||
active: false
|
||||
|
||||
ProcessListModal {
|
||||
id: processListModal
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.processListModal = processListModal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: systemUpdateLoader
|
||||
|
||||
active: false
|
||||
|
||||
SystemUpdatePopout {
|
||||
id: systemUpdatePopout
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.systemUpdatePopout = systemUpdatePopout
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Variants {
|
||||
id: notepadSlideoutVariants
|
||||
model: SettingsData.getFilteredScreens("notepad")
|
||||
|
||||
delegate: DankSlideout {
|
||||
id: notepadSlideout
|
||||
modelData: item
|
||||
title: I18n.tr("Notepad")
|
||||
slideoutWidth: 480
|
||||
expandable: true
|
||||
expandedWidthValue: 960
|
||||
customTransparency: SettingsData.notepadTransparencyOverride
|
||||
|
||||
content: Component {
|
||||
Notepad {
|
||||
onHideRequested: {
|
||||
notepadSlideout.hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
if (isVisible) {
|
||||
hide()
|
||||
} else {
|
||||
show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: powerMenuModalLoader
|
||||
|
||||
active: false
|
||||
|
||||
PowerMenuModal {
|
||||
id: powerMenuModal
|
||||
|
||||
onPowerActionRequested: (action, title, message) => {
|
||||
if (SettingsData.powerActionConfirm) {
|
||||
powerConfirmModalLoader.active = true
|
||||
if (powerConfirmModalLoader.item) {
|
||||
powerConfirmModalLoader.item.confirmButtonColor = action === "poweroff" ? Theme.error : action === "reboot" ? Theme.warning : Theme.primary
|
||||
powerConfirmModalLoader.item.show(title, message, () => actionApply(action), function () {})
|
||||
sourceComponent: DankBar {
|
||||
onColorPickerRequested: {
|
||||
if (colorPickerModal.shouldBeVisible) {
|
||||
colorPickerModal.close()
|
||||
} else {
|
||||
colorPickerModal.show()
|
||||
}
|
||||
} else {
|
||||
actionApply(action)
|
||||
}
|
||||
}
|
||||
|
||||
function actionApply(action) {
|
||||
switch (action) {
|
||||
case "logout":
|
||||
SessionService.logout()
|
||||
break
|
||||
case "suspend":
|
||||
SessionService.suspend()
|
||||
break
|
||||
case "hibernate":
|
||||
SessionService.hibernate()
|
||||
break
|
||||
case "reboot":
|
||||
SessionService.reboot()
|
||||
break
|
||||
case "poweroff":
|
||||
SessionService.poweroff()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.powerMenuModal = powerMenuModal
|
||||
initialized = true
|
||||
}
|
||||
|
||||
onCurrentPositionChanged: {
|
||||
if (!initialized)
|
||||
return
|
||||
|
||||
const component = sourceComponent
|
||||
sourceComponent = null
|
||||
sourceComponent = component
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: hyprKeybindsModalLoader
|
||||
Loader {
|
||||
id: dockLoader
|
||||
active: true
|
||||
asynchronous: false
|
||||
|
||||
active: false
|
||||
property var currentPosition: SettingsData.dockPosition
|
||||
property bool initialized: false
|
||||
|
||||
HyprKeybindsModal {
|
||||
id: hyprKeybindsModal
|
||||
sourceComponent: Dock {
|
||||
contextMenu: dockContextMenuLoader.item ? dockContextMenuLoader.item : null
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.hyprKeybindsModal = hyprKeybindsModal
|
||||
}
|
||||
}
|
||||
}
|
||||
onLoaded: {
|
||||
if (item) {
|
||||
dockContextMenuLoader.active = true
|
||||
}
|
||||
}
|
||||
|
||||
DMSShellIPC {
|
||||
powerMenuModalLoader: powerMenuModalLoader
|
||||
processListModalLoader: processListModalLoader
|
||||
controlCenterLoader: controlCenterLoader
|
||||
dankDashPopoutLoader: dankDashPopoutLoader
|
||||
notepadSlideoutVariants: notepadSlideoutVariants
|
||||
hyprKeybindsModalLoader: hyprKeybindsModalLoader
|
||||
}
|
||||
Component.onCompleted: {
|
||||
initialized = true
|
||||
}
|
||||
|
||||
Variants {
|
||||
model: SettingsData.getFilteredScreens("toast")
|
||||
onCurrentPositionChanged: {
|
||||
if (!initialized)
|
||||
return
|
||||
|
||||
delegate: Toast {
|
||||
modelData: item
|
||||
visible: ToastService.toastVisible
|
||||
}
|
||||
}
|
||||
console.log("DEBUG: Dock position changed to:", currentPosition, "- recreating dock")
|
||||
const comp = sourceComponent
|
||||
sourceComponent = null
|
||||
sourceComponent = comp
|
||||
}
|
||||
}
|
||||
|
||||
Variants {
|
||||
model: SettingsData.getFilteredScreens("osd")
|
||||
Loader {
|
||||
id: dankDashPopoutLoader
|
||||
|
||||
delegate: VolumeOSD {
|
||||
modelData: item
|
||||
}
|
||||
}
|
||||
active: false
|
||||
asynchronous: true
|
||||
|
||||
Variants {
|
||||
model: SettingsData.getFilteredScreens("osd")
|
||||
sourceComponent: Component {
|
||||
DankDashPopout {
|
||||
id: dankDashPopout
|
||||
|
||||
delegate: MicMuteOSD {
|
||||
modelData: item
|
||||
}
|
||||
}
|
||||
Component.onCompleted: {
|
||||
PopoutService.dankDashPopout = dankDashPopout
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Variants {
|
||||
model: SettingsData.getFilteredScreens("osd")
|
||||
LazyLoader {
|
||||
id: dockContextMenuLoader
|
||||
|
||||
delegate: BrightnessOSD {
|
||||
modelData: item
|
||||
}
|
||||
}
|
||||
active: false
|
||||
|
||||
Variants {
|
||||
model: SettingsData.getFilteredScreens("osd")
|
||||
DockContextMenu {
|
||||
id: dockContextMenu
|
||||
}
|
||||
}
|
||||
|
||||
delegate: IdleInhibitorOSD {
|
||||
modelData: item
|
||||
}
|
||||
}
|
||||
LazyLoader {
|
||||
id: notificationCenterLoader
|
||||
|
||||
active: false
|
||||
|
||||
NotificationCenterPopout {
|
||||
id: notificationCenter
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.notificationCenterPopout = notificationCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Variants {
|
||||
model: SettingsData.getFilteredScreens("notifications")
|
||||
|
||||
delegate: NotificationPopupManager {
|
||||
modelData: item
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: controlCenterLoader
|
||||
|
||||
active: false
|
||||
|
||||
property var modalRef: colorPickerModal
|
||||
property LazyLoader powerModalLoaderRef: powerMenuModalLoader
|
||||
|
||||
ControlCenterPopout {
|
||||
id: controlCenterPopout
|
||||
colorPickerModal: controlCenterLoader.modalRef
|
||||
powerMenuModalLoader: controlCenterLoader.powerModalLoaderRef
|
||||
|
||||
onLockRequested: {
|
||||
lock.activate()
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.controlCenterPopout = controlCenterPopout
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: wifiPasswordModalLoader
|
||||
|
||||
active: false
|
||||
|
||||
WifiPasswordModal {
|
||||
id: wifiPasswordModal
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.wifiPasswordModal = wifiPasswordModal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: networkInfoModalLoader
|
||||
|
||||
active: false
|
||||
|
||||
NetworkInfoModal {
|
||||
id: networkInfoModal
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.networkInfoModal = networkInfoModal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: batteryPopoutLoader
|
||||
|
||||
active: false
|
||||
|
||||
BatteryPopout {
|
||||
id: batteryPopout
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.batteryPopout = batteryPopout
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: vpnPopoutLoader
|
||||
|
||||
active: false
|
||||
|
||||
VpnPopout {
|
||||
id: vpnPopout
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.vpnPopout = vpnPopout
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: powerMenuLoader
|
||||
|
||||
active: false
|
||||
|
||||
PowerMenu {
|
||||
id: powerMenu
|
||||
|
||||
onPowerActionRequested: (action, title, message) => {
|
||||
if (SettingsData.powerActionConfirm) {
|
||||
powerConfirmModalLoader.active = true
|
||||
if (powerConfirmModalLoader.item) {
|
||||
powerConfirmModalLoader.item.confirmButtonColor = action === "poweroff" ? Theme.error : action === "reboot" ? Theme.warning : Theme.primary
|
||||
powerConfirmModalLoader.item.show(title, message, () => actionApply(action), function () {})
|
||||
}
|
||||
} else {
|
||||
actionApply(action)
|
||||
}
|
||||
}
|
||||
|
||||
function actionApply(action) {
|
||||
switch (action) {
|
||||
case "logout":
|
||||
SessionService.logout()
|
||||
break
|
||||
case "suspend":
|
||||
SessionService.suspend()
|
||||
break
|
||||
case "hibernate":
|
||||
SessionService.hibernate()
|
||||
break
|
||||
case "reboot":
|
||||
SessionService.reboot()
|
||||
break
|
||||
case "poweroff":
|
||||
SessionService.poweroff()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: powerConfirmModalLoader
|
||||
|
||||
active: false
|
||||
|
||||
ConfirmModal {
|
||||
id: powerConfirmModal
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: processListPopoutLoader
|
||||
|
||||
active: false
|
||||
|
||||
ProcessListPopout {
|
||||
id: processListPopout
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.processListPopout = processListPopout
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SettingsModal {
|
||||
id: settingsModal
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.settingsModal = settingsModal
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: appDrawerLoader
|
||||
|
||||
active: false
|
||||
|
||||
AppDrawerPopout {
|
||||
id: appDrawerPopout
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.appDrawerPopout = appDrawerPopout
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SpotlightModal {
|
||||
id: spotlightModal
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.spotlightModal = spotlightModal
|
||||
}
|
||||
}
|
||||
|
||||
ClipboardHistoryModal {
|
||||
id: clipboardHistoryModalPopup
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.clipboardHistoryModal = clipboardHistoryModalPopup
|
||||
}
|
||||
}
|
||||
|
||||
NotificationModal {
|
||||
id: notificationModal
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.notificationModal = notificationModal
|
||||
}
|
||||
}
|
||||
|
||||
DankColorPickerModal {
|
||||
id: colorPickerModal
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.colorPickerModal = colorPickerModal
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: processListModalLoader
|
||||
|
||||
active: false
|
||||
|
||||
ProcessListModal {
|
||||
id: processListModal
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.processListModal = processListModal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: systemUpdateLoader
|
||||
|
||||
active: false
|
||||
|
||||
SystemUpdatePopout {
|
||||
id: systemUpdatePopout
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.systemUpdatePopout = systemUpdatePopout
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Variants {
|
||||
id: notepadSlideoutVariants
|
||||
model: SettingsData.getFilteredScreens("notepad")
|
||||
|
||||
delegate: DankSlideout {
|
||||
id: notepadSlideout
|
||||
modelData: item
|
||||
title: I18n.tr("Notepad")
|
||||
slideoutWidth: 480
|
||||
expandable: true
|
||||
expandedWidthValue: 960
|
||||
customTransparency: SettingsData.notepadTransparencyOverride
|
||||
|
||||
content: Component {
|
||||
Notepad {
|
||||
onHideRequested: {
|
||||
notepadSlideout.hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
if (isVisible) {
|
||||
hide()
|
||||
} else {
|
||||
show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: powerMenuModalLoader
|
||||
|
||||
active: false
|
||||
|
||||
PowerMenuModal {
|
||||
id: powerMenuModal
|
||||
|
||||
onPowerActionRequested: (action, title, message) => {
|
||||
if (SettingsData.powerActionConfirm) {
|
||||
powerConfirmModalLoader.active = true
|
||||
if (powerConfirmModalLoader.item) {
|
||||
powerConfirmModalLoader.item.confirmButtonColor = action === "poweroff" ? Theme.error : action === "reboot" ? Theme.warning : Theme.primary
|
||||
powerConfirmModalLoader.item.show(title, message, () => actionApply(action), function () {})
|
||||
}
|
||||
} else {
|
||||
actionApply(action)
|
||||
}
|
||||
}
|
||||
|
||||
function actionApply(action) {
|
||||
switch (action) {
|
||||
case "logout":
|
||||
SessionService.logout()
|
||||
break
|
||||
case "suspend":
|
||||
SessionService.suspend()
|
||||
break
|
||||
case "hibernate":
|
||||
SessionService.hibernate()
|
||||
break
|
||||
case "reboot":
|
||||
SessionService.reboot()
|
||||
break
|
||||
case "poweroff":
|
||||
SessionService.poweroff()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.powerMenuModal = powerMenuModal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: hyprKeybindsModalLoader
|
||||
|
||||
active: false
|
||||
|
||||
HyprKeybindsModal {
|
||||
id: hyprKeybindsModal
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.hyprKeybindsModal = hyprKeybindsModal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DMSShellIPC {
|
||||
powerMenuModalLoader: powerMenuModalLoader
|
||||
processListModalLoader: processListModalLoader
|
||||
controlCenterLoader: controlCenterLoader
|
||||
dankDashPopoutLoader: dankDashPopoutLoader
|
||||
notepadSlideoutVariants: notepadSlideoutVariants
|
||||
hyprKeybindsModalLoader: hyprKeybindsModalLoader
|
||||
dankBarLoader: dankBarLoader
|
||||
}
|
||||
|
||||
Variants {
|
||||
model: SettingsData.getFilteredScreens("toast")
|
||||
|
||||
delegate: Toast {
|
||||
modelData: item
|
||||
visible: ToastService.toastVisible
|
||||
}
|
||||
}
|
||||
|
||||
Variants {
|
||||
model: SettingsData.getFilteredScreens("osd")
|
||||
|
||||
delegate: VolumeOSD {
|
||||
modelData: item
|
||||
}
|
||||
}
|
||||
|
||||
Variants {
|
||||
model: SettingsData.getFilteredScreens("osd")
|
||||
|
||||
delegate: MicMuteOSD {
|
||||
modelData: item
|
||||
}
|
||||
}
|
||||
|
||||
Variants {
|
||||
model: SettingsData.getFilteredScreens("osd")
|
||||
|
||||
delegate: BrightnessOSD {
|
||||
modelData: item
|
||||
}
|
||||
}
|
||||
|
||||
Variants {
|
||||
model: SettingsData.getFilteredScreens("osd")
|
||||
|
||||
delegate: IdleInhibitorOSD {
|
||||
modelData: item
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ Item {
|
||||
required property var dankDashPopoutLoader
|
||||
required property var notepadSlideoutVariants
|
||||
required property var hyprKeybindsModalLoader
|
||||
required property var dankBarLoader
|
||||
|
||||
IpcHandler {
|
||||
function open() {
|
||||
@@ -76,9 +77,8 @@ Item {
|
||||
|
||||
IpcHandler {
|
||||
function open(): string {
|
||||
root.controlCenterLoader.active = true
|
||||
if (root.controlCenterLoader.item) {
|
||||
root.controlCenterLoader.item.open()
|
||||
if (root.dankBarLoader.item) {
|
||||
root.dankBarLoader.item.triggerControlCenterOnFocusedScreen()
|
||||
return "CONTROL_CENTER_OPEN_SUCCESS"
|
||||
}
|
||||
return "CONTROL_CENTER_OPEN_FAILED"
|
||||
@@ -93,9 +93,8 @@ Item {
|
||||
}
|
||||
|
||||
function toggle(): string {
|
||||
root.controlCenterLoader.active = true
|
||||
if (root.controlCenterLoader.item) {
|
||||
root.controlCenterLoader.item.toggle()
|
||||
if (root.dankBarLoader.item) {
|
||||
root.dankBarLoader.item.triggerControlCenterOnFocusedScreen()
|
||||
return "CONTROL_CENTER_TOGGLE_SUCCESS"
|
||||
}
|
||||
return "CONTROL_CENTER_TOGGLE_FAILED"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
162
Modals/NetworkWiredInfoModal.qml
Normal file
162
Modals/NetworkWiredInfoModal.qml
Normal file
@@ -0,0 +1,162 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import qs.Common
|
||||
import qs.Modals.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
DankModal {
|
||||
id: root
|
||||
|
||||
property bool networkWiredInfoModalVisible: false
|
||||
property string networkID: ""
|
||||
property var networkData: null
|
||||
|
||||
function showNetworkInfo(id, data) {
|
||||
networkID = id
|
||||
networkData = data
|
||||
networkWiredInfoModalVisible = true
|
||||
open()
|
||||
NetworkService.fetchWiredNetworkInfo(data.uuid)
|
||||
}
|
||||
|
||||
function hideDialog() {
|
||||
networkWiredInfoModalVisible = false
|
||||
close()
|
||||
networkID = ""
|
||||
networkData = null
|
||||
}
|
||||
|
||||
visible: networkWiredInfoModalVisible
|
||||
width: 600
|
||||
height: 500
|
||||
enableShadow: true
|
||||
onBackgroundClicked: hideDialog()
|
||||
onVisibleChanged: {
|
||||
if (!visible) {
|
||||
networkID = ""
|
||||
networkData = null
|
||||
}
|
||||
}
|
||||
|
||||
content: Component {
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingL
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
|
||||
Column {
|
||||
width: parent.width - 40
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("Network Information")
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: `Details for "${networkID}"`
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceTextMedium
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DankActionButton {
|
||||
iconName: "close"
|
||||
iconSize: Theme.iconSize - 4
|
||||
iconColor: Theme.surfaceText
|
||||
onClicked: root.hideDialog()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: detailsRect
|
||||
|
||||
width: parent.width
|
||||
height: parent.height - 140
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.surfaceHover
|
||||
border.color: Theme.outlineStrong
|
||||
border.width: 1
|
||||
clip: true
|
||||
|
||||
DankFlickable {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingM
|
||||
contentHeight: detailsText.contentHeight
|
||||
|
||||
StyledText {
|
||||
id: detailsText
|
||||
|
||||
width: parent.width
|
||||
text: NetworkService.networkWiredInfoDetails && NetworkService.networkWiredInfoDetails.replace(/\\n/g, '\n') || "No information available"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceText
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
height: 40
|
||||
|
||||
Rectangle {
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: Math.max(70, closeText.contentWidth + Theme.spacingM * 2)
|
||||
height: 36
|
||||
radius: Theme.cornerRadius
|
||||
color: closeArea.containsMouse ? Qt.darker(Theme.primary, 1.1) : Theme.primary
|
||||
|
||||
StyledText {
|
||||
id: closeText
|
||||
|
||||
anchors.centerIn: parent
|
||||
text: I18n.tr("Close")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.background
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: closeArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: root.hideDialog()
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -391,6 +391,38 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingXS
|
||||
anchors.left: parent.left
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("Command or script to run instead of the standard lock procedure")
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
|
||||
DankTextField {
|
||||
id: customLockCommand
|
||||
width: parent.width
|
||||
height: 48
|
||||
placeholderText: "/usr/bin/myLock.sh"
|
||||
backgroundColor: Theme.surfaceVariant
|
||||
normalBorderColor: Theme.primarySelected
|
||||
focusedBorderColor: Theme.primary
|
||||
|
||||
Component.onCompleted: {
|
||||
if (SettingsData.customPowerActionLock) {
|
||||
text = SettingsData.customPowerActionLock;
|
||||
}
|
||||
}
|
||||
|
||||
onTextEdited: {
|
||||
SettingsData.setCustomPowerActionLock(text.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
@@ -73,21 +73,21 @@ DankPopout {
|
||||
onShouldBeVisibleChanged: {
|
||||
if (shouldBeVisible) {
|
||||
Qt.callLater(() => {
|
||||
if (NetworkService.activeService) {
|
||||
NetworkService.activeService.autoRefreshEnabled = NetworkService.wifiEnabled
|
||||
}
|
||||
if (UserInfoService)
|
||||
UserInfoService.getUptime()
|
||||
})
|
||||
if (NetworkService.activeService) {
|
||||
NetworkService.activeService.autoRefreshEnabled = NetworkService.wifiEnabled
|
||||
}
|
||||
if (UserInfoService)
|
||||
UserInfoService.getUptime()
|
||||
})
|
||||
} else {
|
||||
Qt.callLater(() => {
|
||||
if (NetworkService.activeService) {
|
||||
NetworkService.activeService.autoRefreshEnabled = false
|
||||
}
|
||||
if (BluetoothService.adapter && BluetoothService.adapter.discovering)
|
||||
BluetoothService.adapter.discovering = false
|
||||
editMode = false
|
||||
})
|
||||
if (NetworkService.activeService) {
|
||||
NetworkService.activeService.autoRefreshEnabled = false
|
||||
}
|
||||
if (BluetoothService.adapter && BluetoothService.adapter.discovering)
|
||||
BluetoothService.adapter.discovering = false
|
||||
editMode = false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,8 +108,7 @@ DankPopout {
|
||||
return Qt.rgba(surface.r, surface.g, surface.b, transparency)
|
||||
}
|
||||
radius: Theme.cornerRadius
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
|
||||
Theme.outline.b, 0.08)
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||
border.width: 0
|
||||
antialiasing: true
|
||||
smooth: true
|
||||
@@ -156,19 +155,19 @@ DankPopout {
|
||||
bluetoothCodecSelector: bluetoothCodecSelector
|
||||
colorPickerModal: root.colorPickerModal
|
||||
onExpandClicked: (widgetData, globalIndex) => {
|
||||
root.expandedWidgetIndex = globalIndex
|
||||
root.expandedWidgetData = widgetData
|
||||
if (widgetData.id === "diskUsage") {
|
||||
root.toggleSection("diskUsage_" + (widgetData.instanceId || "default"))
|
||||
} else if (widgetData.id === "brightnessSlider") {
|
||||
root.toggleSection("brightnessSlider_" + (widgetData.instanceId || "default"))
|
||||
} else {
|
||||
root.toggleSection(widgetData.id)
|
||||
}
|
||||
}
|
||||
onRemoveWidget: (index) => widgetModel.removeWidget(index)
|
||||
root.expandedWidgetIndex = globalIndex
|
||||
root.expandedWidgetData = widgetData
|
||||
if (widgetData.id === "diskUsage") {
|
||||
root.toggleSection("diskUsage_" + (widgetData.instanceId || "default"))
|
||||
} else if (widgetData.id === "brightnessSlider") {
|
||||
root.toggleSection("brightnessSlider_" + (widgetData.instanceId || "default"))
|
||||
} else {
|
||||
root.toggleSection(widgetData.id)
|
||||
}
|
||||
}
|
||||
onRemoveWidget: index => widgetModel.removeWidget(index)
|
||||
onMoveWidget: (fromIndex, toIndex) => widgetModel.moveWidget(fromIndex, toIndex)
|
||||
onToggleWidgetSize: (index) => widgetModel.toggleWidgetSize(index)
|
||||
onToggleWidgetSize: index => widgetModel.toggleWidgetSize(index)
|
||||
onCollapseRequested: root.collapseAll()
|
||||
}
|
||||
|
||||
@@ -177,12 +176,13 @@ DankPopout {
|
||||
visible: editMode
|
||||
popoutContent: controlContent
|
||||
availableWidgets: {
|
||||
if (!editMode) return []
|
||||
if (!editMode)
|
||||
return []
|
||||
const existingIds = (SettingsData.controlCenterWidgets || []).map(w => w.id)
|
||||
const allWidgets = widgetModel.baseWidgetDefinitions.concat(widgetModel.getPluginWidgets())
|
||||
return allWidgets.filter(w => w.allowMultiple || !existingIds.includes(w.id))
|
||||
}
|
||||
onAddWidget: (widgetId) => widgetModel.addWidget(widgetId)
|
||||
onAddWidget: widgetId => widgetModel.addWidget(widgetId)
|
||||
onResetToDefault: () => widgetModel.resetToDefault()
|
||||
onClearAll: () => widgetModel.clearAll()
|
||||
}
|
||||
@@ -205,10 +205,10 @@ DankPopout {
|
||||
id: bluetoothDetailComponent
|
||||
BluetoothDetail {
|
||||
id: bluetoothDetail
|
||||
onShowCodecSelector: function(device) {
|
||||
onShowCodecSelector: function (device) {
|
||||
if (contentLoader.item && contentLoader.item.bluetoothCodecSelector) {
|
||||
contentLoader.item.bluetoothCodecSelector.show(device)
|
||||
contentLoader.item.bluetoothCodecSelector.codecSelected.connect(function(deviceAddress, codecName) {
|
||||
contentLoader.item.bluetoothCodecSelector.codecSelected.connect(function (deviceAddress, codecName) {
|
||||
bluetoothDetail.updateDeviceCodecDisplay(deviceAddress, codecName)
|
||||
})
|
||||
}
|
||||
@@ -233,4 +233,4 @@ DankPopout {
|
||||
|
||||
property var colorPickerModal: null
|
||||
property var powerMenuModalLoader: null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,26 @@ Rectangle {
|
||||
NetworkService.removeRef()
|
||||
}
|
||||
|
||||
property int currentPreferenceIndex: {
|
||||
if (DMSService.apiVersion < 5) {
|
||||
return 1
|
||||
}
|
||||
|
||||
const pref = NetworkService.userPreference
|
||||
const status = NetworkService.networkStatus
|
||||
let index = 1
|
||||
|
||||
if (pref === "ethernet") {
|
||||
index = 0
|
||||
} else if (pref === "wifi") {
|
||||
index = 1
|
||||
} else {
|
||||
index = status === "ethernet" ? 0 : 1
|
||||
}
|
||||
|
||||
return index
|
||||
}
|
||||
|
||||
Row {
|
||||
id: headerRow
|
||||
anchors.left: parent.left
|
||||
@@ -38,7 +58,7 @@ Rectangle {
|
||||
anchors.rightMargin: Theme.spacingM
|
||||
anchors.topMargin: Theme.spacingS
|
||||
height: 40
|
||||
|
||||
|
||||
StyledText {
|
||||
id: headerText
|
||||
text: I18n.tr("Network Settings")
|
||||
@@ -47,32 +67,16 @@ Rectangle {
|
||||
font.weight: Font.Medium
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
Item {
|
||||
width: Math.max(0, parent.width - headerText.implicitWidth - preferenceControls.width - Theme.spacingM)
|
||||
height: parent.height
|
||||
}
|
||||
|
||||
|
||||
DankButtonGroup {
|
||||
id: preferenceControls
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: NetworkService.ethernetConnected
|
||||
|
||||
property int currentPreferenceIndex: {
|
||||
const pref = NetworkService.userPreference
|
||||
const status = NetworkService.networkStatus
|
||||
let index = 1
|
||||
|
||||
if (pref === "ethernet") {
|
||||
index = 0
|
||||
} else if (pref === "wifi") {
|
||||
index = 1
|
||||
} else {
|
||||
index = status === "ethernet" ? 0 : 1
|
||||
}
|
||||
|
||||
return index
|
||||
}
|
||||
visible: DMSService.apiVersion >= 5
|
||||
|
||||
model: ["Ethernet", "WiFi"]
|
||||
currentIndex: currentPreferenceIndex
|
||||
@@ -92,7 +96,7 @@ Rectangle {
|
||||
anchors.right: parent.right
|
||||
anchors.margins: Theme.spacingM
|
||||
anchors.topMargin: Theme.spacingM
|
||||
visible: NetworkService.wifiToggling
|
||||
visible: currentPreferenceIndex === 1 && NetworkService.wifiToggling
|
||||
height: visible ? 80 : 0
|
||||
|
||||
Column {
|
||||
@@ -131,7 +135,7 @@ Rectangle {
|
||||
anchors.right: parent.right
|
||||
anchors.margins: Theme.spacingM
|
||||
anchors.topMargin: Theme.spacingM
|
||||
visible: !NetworkService.wifiEnabled && !NetworkService.wifiToggling
|
||||
visible: currentPreferenceIndex === 1 && !NetworkService.wifiEnabled && !NetworkService.wifiToggling
|
||||
height: visible ? 120 : 0
|
||||
|
||||
Column {
|
||||
@@ -179,7 +183,179 @@ Rectangle {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: NetworkService.toggleWifiRadio()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DankFlickable {
|
||||
id: wiredContent
|
||||
anchors.top: headerRow.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.margins: Theme.spacingM
|
||||
anchors.topMargin: Theme.spacingM
|
||||
visible: currentPreferenceIndex === 0 && DMSService.apiVersion >= 5
|
||||
contentHeight: wiredColumn.height
|
||||
clip: true
|
||||
|
||||
Column {
|
||||
id: wiredColumn
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
|
||||
Repeater {
|
||||
model: sortedNetworks
|
||||
|
||||
property var sortedNetworks: {
|
||||
const currentUuid = NetworkService.ethernetConnectionUuid
|
||||
const networks = NetworkService.wiredConnections
|
||||
let sorted = [...networks]
|
||||
sorted.sort((a, b) => {
|
||||
if (a.isActive && !b.isActive) return -1
|
||||
if (!a.isActive && b.isActive) return 1
|
||||
return a.id.localeCompare(b.id)
|
||||
})
|
||||
return sorted
|
||||
}
|
||||
delegate: Rectangle {
|
||||
required property var modelData
|
||||
required property int index
|
||||
|
||||
width: parent.width
|
||||
height: 50
|
||||
radius: Theme.cornerRadius
|
||||
color: wiredNetworkMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Theme.surfaceContainerHighest
|
||||
border.color: Theme.primary
|
||||
border.width: 0
|
||||
|
||||
Row {
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.leftMargin: Theme.spacingM
|
||||
spacing: Theme.spacingS
|
||||
|
||||
DankIcon {
|
||||
name: "lan"
|
||||
size: Theme.iconSize - 4
|
||||
color: modelData.isActive ? Theme.primary : Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 200
|
||||
|
||||
StyledText {
|
||||
text: modelData.id || "Unknown Config"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: modelData.isActive ? Theme.primary : Theme.surfaceText
|
||||
font.weight: modelData.isActive ? Font.Medium : Font.Normal
|
||||
elide: Text.ElideRight
|
||||
width: parent.width
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DankActionButton {
|
||||
id: wiredOptionsButton
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Theme.spacingS
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
iconName: "more_horiz"
|
||||
buttonSize: 28
|
||||
onClicked: {
|
||||
if (wiredNetworkContextMenu.visible) {
|
||||
wiredNetworkContextMenu.close()
|
||||
} else {
|
||||
wiredNetworkContextMenu.currentID = modelData.id
|
||||
wiredNetworkContextMenu.currentUUID = modelData.uuid
|
||||
wiredNetworkContextMenu.currentConnected = modelData.isActive
|
||||
wiredNetworkContextMenu.popup(wiredOptionsButton, -wiredNetworkContextMenu.width + wiredOptionsButton.width, wiredOptionsButton.height + Theme.spacingXS)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: wiredNetworkMouseArea
|
||||
anchors.fill: parent
|
||||
anchors.rightMargin: wiredOptionsButton.width + Theme.spacingS
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: function(event) {
|
||||
if (modelData.uuid !== NetworkService.ethernetConnectionUuid) {
|
||||
NetworkService.connectToSpecificWiredConfig(modelData.uuid)
|
||||
}
|
||||
event.accepted = true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Menu {
|
||||
id: wiredNetworkContextMenu
|
||||
width: 150
|
||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
|
||||
|
||||
property string currentID: ""
|
||||
property string currentUUID: ""
|
||||
property bool currentConnected: false
|
||||
|
||||
background: Rectangle {
|
||||
color: Theme.popupBackground()
|
||||
radius: Theme.cornerRadius
|
||||
border.width: 0
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
text: "Activate"
|
||||
height: !wiredNetworkContextMenu.currentConnected ? 32 : 0
|
||||
|
||||
contentItem: StyledText {
|
||||
text: parent.text
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceText
|
||||
leftPadding: Theme.spacingS
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: parent.hovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
|
||||
radius: Theme.cornerRadius / 2
|
||||
}
|
||||
|
||||
onTriggered: {
|
||||
if (!networkContextMenu.currentConnected) {
|
||||
NetworkService.connectToSpecificWiredConfig(wiredNetworkContextMenu.currentUUID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
text: I18n.tr("Network Info")
|
||||
height: wiredNetworkContextMenu.currentConnected ? 32 : 0
|
||||
|
||||
contentItem: StyledText {
|
||||
text: parent.text
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceText
|
||||
leftPadding: Theme.spacingS
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: parent.hovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
|
||||
radius: Theme.cornerRadius / 2
|
||||
}
|
||||
|
||||
onTriggered: {
|
||||
let networkData = NetworkService.getWiredNetworkInfo(wiredNetworkContextMenu.currentUUID)
|
||||
networkWiredInfoModal.showNetworkInfo(wiredNetworkContextMenu.currentID, networkData)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -192,10 +368,10 @@ Rectangle {
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.margins: Theme.spacingM
|
||||
anchors.topMargin: Theme.spacingM
|
||||
visible: NetworkService.wifiInterface && NetworkService.wifiEnabled && !NetworkService.wifiToggling
|
||||
visible: currentPreferenceIndex === 1 && NetworkService.wifiEnabled && !NetworkService.wifiToggling
|
||||
contentHeight: wifiColumn.height
|
||||
clip: true
|
||||
|
||||
|
||||
Column {
|
||||
id: wifiColumn
|
||||
width: parent.width
|
||||
@@ -282,20 +458,20 @@ Rectangle {
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
StyledText {
|
||||
text: modelData.ssid === NetworkService.currentWifiSSID ? "Connected" : (modelData.secured ? "Secured" : "Open")
|
||||
text: modelData.ssid === NetworkService.currentWifiSSID ? "Connected •" : (modelData.secured ? "Secured •" : "Open •")
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: modelData.saved ? "• Saved" : ""
|
||||
text: modelData.saved ? "Saved" : ""
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.primary
|
||||
visible: text.length > 0
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "• " + modelData.signal + "%"
|
||||
text: (modelData.saved ? "• " : "") + modelData.signal + "%"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
@@ -449,6 +625,8 @@ Rectangle {
|
||||
NetworkInfoModal {
|
||||
id: networkInfoModal
|
||||
}
|
||||
|
||||
|
||||
|
||||
NetworkWiredInfoModal {
|
||||
id: networkWiredInfoModal
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -153,7 +153,10 @@ Rectangle {
|
||||
|
||||
const name = split[0];
|
||||
const path = split[1];
|
||||
const fileName = name.substring(name.lastIndexOf("/") + 1);
|
||||
let fileName = name.substring(name.lastIndexOf("/") + 1);
|
||||
if (fileName.startsWith("dropboxstatus")) {
|
||||
fileName = `hicolor/16x16/status/${fileName}`;
|
||||
}
|
||||
return `file://${path}/${fileName}`;
|
||||
}
|
||||
if (icon.startsWith("/") && !icon.startsWith("file://")) {
|
||||
|
||||
@@ -15,6 +15,9 @@ Rectangle {
|
||||
property string screenName: ""
|
||||
property real widgetHeight: 30
|
||||
property real barThickness: 48
|
||||
readonly property var sortedToplevels: {
|
||||
return CompositorService.filterCurrentWorkspace(CompositorService.sortedToplevels, parentScreen?.name);
|
||||
}
|
||||
property int currentWorkspace: {
|
||||
if (CompositorService.isNiri) {
|
||||
return getNiriActiveWorkspace()
|
||||
@@ -252,14 +255,84 @@ Rectangle {
|
||||
const direction = deltaY < 0 ? 1 : -1
|
||||
|
||||
if (isMouseWheel) {
|
||||
switchWorkspace(direction)
|
||||
if (!SettingsData.workspaceScrolling || !CompositorService.isNiri) {
|
||||
switchWorkspace(direction)
|
||||
}
|
||||
else {
|
||||
const windows = root.sortedToplevels;
|
||||
if (windows.length < 2) {
|
||||
return;
|
||||
}
|
||||
let currentIndex = -1;
|
||||
for (let i = 0; i < windows.length; i++) {
|
||||
if (windows[i].activated) {
|
||||
currentIndex = i;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
let nextIndex;
|
||||
if (deltaY < 0) {
|
||||
if (currentIndex === -1) {
|
||||
nextIndex = 0;
|
||||
} else {
|
||||
nextIndex = currentIndex +1;
|
||||
}
|
||||
} else {
|
||||
if (currentIndex === -1) {
|
||||
nextIndex = windows.length -1;
|
||||
} else {
|
||||
nextIndex = currentIndex - 1
|
||||
}
|
||||
}
|
||||
const nextWindow = windows[nextIndex];
|
||||
if (nextWindow) {
|
||||
nextWindow.activate();
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
scrollAccumulator += deltaY
|
||||
|
||||
if (Math.abs(scrollAccumulator) >= touchpadThreshold) {
|
||||
const touchDirection = scrollAccumulator < 0 ? 1 : -1
|
||||
switchWorkspace(touchDirection)
|
||||
scrollAccumulator = 0
|
||||
if (!SettingsData.workspaceScrolling || !CompositorService.isNiri) {
|
||||
switchWorkspace(touchDirection)
|
||||
}
|
||||
else {
|
||||
const windows = root.sortedToplevels;
|
||||
if (windows.length < 2) {
|
||||
return;
|
||||
}
|
||||
let currentIndex = -1;
|
||||
for (let i = 0; i < windows.length; i++) {
|
||||
if (windows[i].activated) {
|
||||
currentIndex = i;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
let nextIndex;
|
||||
if (deltaY < 0) {
|
||||
if (currentIndex === -1) {
|
||||
nextIndex = 0;
|
||||
} else {
|
||||
nextIndex = currentIndex +1;
|
||||
}
|
||||
} else {
|
||||
if (currentIndex === -1) {
|
||||
nextIndex = windows.length -1;
|
||||
} else {
|
||||
nextIndex = currentIndex - 1
|
||||
}
|
||||
}
|
||||
const nextWindow = windows[nextIndex];
|
||||
if (nextWindow) {
|
||||
nextWindow.activate();
|
||||
}
|
||||
}
|
||||
|
||||
scrollAccumulator = 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,36 +22,100 @@ paru -S greetd-dms-greeter-git
|
||||
yay -S greetd-dms-greeter-git
|
||||
```
|
||||
|
||||
Then in your `/etc/greetd/config.toml` enable dms-greeter by replacing the greeter command with dms-greeter.
|
||||
|
||||
```bash
|
||||
# hyprland and sway are also supported as compositors
|
||||
command = "/usr/bin/dms-greeter --command niri"
|
||||
```
|
||||
|
||||
See `dms-greeter --help` for full options including custom compositor configurations.
|
||||
|
||||
Once installed, you should disable any existing greeter (such as gdm, sddm, lightdm), and you can configure the greeter to run at boot with:
|
||||
Once installed, disable any existing display manager and enable greetd:
|
||||
|
||||
```bash
|
||||
sudo systemctl disable gdm sddm lightdm
|
||||
sudo systemctl enable greetd
|
||||
```
|
||||
#### Syncing themes
|
||||
|
||||
To sync wallpapers, colors, and other settings from the logged in user, you can add your user to the `greeter` group and symlink the shell configurations.
|
||||
#### Syncing themes (Optional)
|
||||
|
||||
To sync your wallpaper and theme with the greeter login screen:
|
||||
|
||||
```bash
|
||||
sudo usermod -aG greeter <username>
|
||||
# LOGOUT and LOGIN after adding user to group
|
||||
|
||||
|
||||
ln -sf ~/.config/DankMaterialShell/settings.json /var/cache/dms-greeter/settings.json
|
||||
|
||||
ln -sf ~/.local/state/DankMaterialShell/session.json /var/cache/dms-greeter/session.json
|
||||
|
||||
ln -sf ~/.cache/quickshell/dankshell/dms-colors.json /var/cache/dms-greeter/colors.json
|
||||
dms-greeter-sync
|
||||
```
|
||||
|
||||
Then logout/login for changes to take effect. Your wallpaper and theme will appear on the greeter!
|
||||
|
||||
<details>
|
||||
<summary>What does dms-greeter-sync do?</summary>
|
||||
|
||||
The `dms-greeter-sync` helper automatically:
|
||||
- Adds you to the greeter group
|
||||
- Sets minimal ACL permissions on parent directories (traverse only)
|
||||
- Sets group ownership on your DMS config directories
|
||||
- Creates symlinks to share your theme files with the greeter
|
||||
|
||||
This uses standard Linux ACLs (Access Control Lists) - the same security model used by GNOME, KDE, and systemd. The greeter user only gets traverse permission through your directories and can only read the specific theme files you share.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Manual theme syncing (advanced)</summary>
|
||||
|
||||
If you prefer to set up theme syncing manually:
|
||||
|
||||
```bash
|
||||
# Add yourself to greeter group
|
||||
sudo usermod -aG greeter <username>
|
||||
|
||||
# Set ACLs to allow greeter to traverse your directories
|
||||
setfacl -m u:greeter:x ~ ~/.config ~/.local ~/.cache ~/.local/state
|
||||
|
||||
# Set group ownership on config directories
|
||||
sudo chgrp -R greeter ~/.config/DankMaterialShell
|
||||
sudo chgrp -R greeter ~/.local/state/DankMaterialShell
|
||||
sudo chgrp -R greeter ~/.cache/quickshell
|
||||
sudo chmod -R g+rX ~/.config/DankMaterialShell ~/.local/state/DankMaterialShell ~/.cache/quickshell
|
||||
|
||||
# Create symlinks
|
||||
sudo ln -sf ~/.config/DankMaterialShell/settings.json /var/cache/dms-greeter/settings.json
|
||||
sudo ln -sf ~/.local/state/DankMaterialShell/session.json /var/cache/dms-greeter/session.json
|
||||
sudo ln -sf ~/.cache/quickshell/dankshell/dms-colors.json /var/cache/dms-greeter/colors.json
|
||||
|
||||
# Logout and login for group membership to take effect
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Fedora / RHEL / Rocky / Alma
|
||||
|
||||
Install from COPR or build the RPM:
|
||||
|
||||
```bash
|
||||
# From COPR (when available)
|
||||
sudo dnf copr enable avenge/dms
|
||||
sudo dnf install dms-greeter
|
||||
|
||||
# Or build locally
|
||||
cd /path/to/DankMaterialShell
|
||||
rpkg local
|
||||
sudo rpm -ivh x86_64/dms-greeter-*.rpm
|
||||
```
|
||||
|
||||
The package automatically:
|
||||
- Creates the greeter user
|
||||
- Sets up directories and permissions
|
||||
- Configures greetd with auto-detected compositor
|
||||
- Applies SELinux contexts
|
||||
|
||||
Then disable existing display manager and enable greetd:
|
||||
|
||||
```bash
|
||||
sudo systemctl disable gdm sddm lightdm
|
||||
sudo systemctl enable greetd
|
||||
```
|
||||
|
||||
**Optional:** Sync your theme with the greeter:
|
||||
|
||||
```bash
|
||||
dms-greeter-sync
|
||||
```
|
||||
|
||||
Then logout/login to see your wallpaper on the greeter!
|
||||
|
||||
### Automatic
|
||||
|
||||
The easiest thing is to run `dms greeter install` or `dms` for interactive installation.
|
||||
@@ -59,21 +123,33 @@ The easiest thing is to run `dms greeter install` or `dms` for interactive insta
|
||||
### Manual
|
||||
|
||||
1. Install `greetd` (in most distro's standard repositories) and `quickshell`
|
||||
2. Clone the dms project to `/etc/xdg/quickshell/dms-greeter`
|
||||
|
||||
2. Create the greeter user (if not already created by greetd):
|
||||
```bash
|
||||
sudo groupadd -r greeter
|
||||
sudo useradd -r -g greeter -d /var/lib/greeter -s /bin/bash -c "System Greeter" greeter
|
||||
sudo mkdir -p /var/lib/greeter
|
||||
sudo chown greeter:greeter /var/lib/greeter
|
||||
```
|
||||
|
||||
3. Clone the dms project to `/etc/xdg/quickshell/dms-greeter`:
|
||||
```bash
|
||||
sudo git clone https://github.com/AvengeMedia/DankMaterialShell.git /etc/xdg/quickshell/dms-greeter
|
||||
```
|
||||
3. Copy `assets/dms-greeter` to `/usr/local/bin/dms-greeter`:
|
||||
|
||||
4. Copy `Modules/Greetd/assets/dms-greeter` to `/usr/local/bin/dms-greeter`:
|
||||
```bash
|
||||
sudo cp assets/dms-greeter /usr/local/bin/dms-greeter
|
||||
sudo cp /etc/xdg/quickshell/dms-greeter/Modules/Greetd/assets/dms-greeter /usr/local/bin/dms-greeter
|
||||
sudo chmod +x /usr/local/bin/dms-greeter
|
||||
```
|
||||
4. Create greeter cache directory with proper permissions:
|
||||
|
||||
5. Create greeter cache directory with proper permissions:
|
||||
```bash
|
||||
sudo mkdir -p /var/cache/dms-greeter
|
||||
sudo chown greeter:greeter /var/cache/dms-greeter
|
||||
sudo chmod 750 /var/cache/dms-greeter
|
||||
```
|
||||
|
||||
6. Edit or create `/etc/greetd/config.toml`:
|
||||
```toml
|
||||
[terminal]
|
||||
@@ -85,7 +161,18 @@ user = "greeter"
|
||||
command = "/usr/local/bin/dms-greeter --command niri"
|
||||
```
|
||||
|
||||
Enable the greeter with `sudo systemctl enable greetd`
|
||||
7. Disable existing display manager and enable greetd:
|
||||
```bash
|
||||
sudo systemctl disable gdm sddm lightdm
|
||||
sudo systemctl enable greetd
|
||||
```
|
||||
|
||||
8. (Optional) Install the `dms-greeter-sync` helper for easy theme syncing:
|
||||
```bash
|
||||
# Download or copy the dms-greeter-sync script from the spec file
|
||||
sudo cp /path/to/dms-greeter-sync /usr/local/bin/dms-greeter-sync
|
||||
sudo chmod +x /usr/local/bin/dms-greeter-sync
|
||||
```
|
||||
|
||||
#### Legacy installation (deprecated)
|
||||
|
||||
@@ -154,21 +241,31 @@ Simply edit `/etc/greetd/dms-niri.kdl` or `/etc/greetd/dms-hypr.conf` to change
|
||||
|
||||
#### Personalization
|
||||
|
||||
Wallpapers and themes and weather and clock formats and things are a TODO on the documentation, but it's configured exactly the same as dms.
|
||||
The greeter can be personalized with wallpapers, themes, weather, clock formats, and more - configured exactly the same as dms.
|
||||
|
||||
You can synchronize those configurations with a specific user if you want greeter settings to always mirror the shell.
|
||||
**Easiest method:** Run `dms-greeter-sync` to automatically sync your DMS theme with the greeter.
|
||||
|
||||
The greeter uses the `dms-greeter` group for file access permissions, so ensure your user and the greeter user are both members of this group.
|
||||
**Manual method:** You can manually synchronize configurations if you want greeter settings to always mirror your shell:
|
||||
|
||||
```bash
|
||||
# For core settings (theme, clock formats, etc)
|
||||
# Add yourself to the greeter group
|
||||
sudo usermod -aG greeter $USER
|
||||
|
||||
# Set ACLs to allow greeter user to traverse your home directory
|
||||
setfacl -m u:greeter:x ~ ~/.config ~/.local ~/.cache ~/.local/state
|
||||
|
||||
# Set group permissions on DMS directories
|
||||
sudo chgrp -R greeter ~/.config/DankMaterialShell ~/.local/state/DankMaterialShell ~/.cache/quickshell
|
||||
sudo chmod -R g+rX ~/.config/DankMaterialShell ~/.local/state/DankMaterialShell ~/.cache/quickshell
|
||||
|
||||
# Create symlinks for theme files
|
||||
sudo ln -sf ~/.config/DankMaterialShell/settings.json /var/cache/dms-greeter/settings.json
|
||||
# For state (mainly you would configure wallpaper in this file)
|
||||
sudo ln -sf ~/.local/state/DankMaterialShell/session.json /var/cache/dms-greeter/session.json
|
||||
# For wallpaper based theming
|
||||
sudo ln -sf ~/.cache/quickshell/dankshell/dms-colors.json /var/cache/dms-greeter/dms-colors.json
|
||||
sudo ln -sf ~/.cache/quickshell/dankshell/dms-colors.json /var/cache/dms-greeter/colors.json
|
||||
|
||||
# Logout and login for group membership to take effect
|
||||
```
|
||||
|
||||
You can override the configuration path with the `DMS_GREET_CFG_DIR` environment variable or the `--cache-dir` flag when using `dms-greeter`. The default is `/var/cache/dms-greeter`.
|
||||
**Advanced:** You can override the configuration path with the `DMS_GREET_CFG_DIR` environment variable or the `--cache-dir` flag when using `dms-greeter`. The default is `/var/cache/dms-greeter`.
|
||||
|
||||
The cache directory should be owned by `greeter:greeter` with `770` permissions.
|
||||
@@ -19,6 +19,10 @@ Scope {
|
||||
}
|
||||
|
||||
function lock() {
|
||||
if (SettingsData.customPowerActionLock && SettingsData.customPowerActionLock.length > 0) {
|
||||
Quickshell.execDetached(SettingsData.customPowerActionLock.split(" "))
|
||||
return
|
||||
}
|
||||
if (!processingExternalEvent && SettingsData.loginctlLockIntegration && DMSService.isConnected) {
|
||||
DMSService.lockSession(response => {
|
||||
if (response.error) {
|
||||
|
||||
@@ -28,6 +28,10 @@ Item {
|
||||
|
||||
signal hideRequested()
|
||||
|
||||
Ref {
|
||||
service: NotepadStorageService
|
||||
}
|
||||
|
||||
function hasUnsavedChanges() {
|
||||
return textEditor.hasUnsavedChanges()
|
||||
}
|
||||
|
||||
@@ -34,39 +34,18 @@ Item {
|
||||
buttonSize: 28
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
onClicked: SessionData.setDoNotDisturb(!SessionData.doNotDisturb)
|
||||
|
||||
Rectangle {
|
||||
id: doNotDisturbTooltip
|
||||
|
||||
width: tooltipText.contentWidth + Theme.spacingS * 2
|
||||
height: tooltipText.contentHeight + Theme.spacingXS * 2
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.surfaceContainer
|
||||
border.color: Theme.outline
|
||||
border.width: 1
|
||||
anchors.bottom: parent.top
|
||||
anchors.bottomMargin: Theme.spacingS
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: doNotDisturbButton.children[1].containsMouse
|
||||
opacity: visible ? 1 : 0
|
||||
|
||||
StyledText {
|
||||
id: tooltipText
|
||||
|
||||
text: I18n.tr("Do Not Disturb")
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
anchors.centerIn: parent
|
||||
font.hintingPreference: Font.PreferFullHinting
|
||||
onEntered: {
|
||||
tooltipLoader.active = true
|
||||
if (tooltipLoader.item) {
|
||||
const p = mapToItem(null, width / 2, 0)
|
||||
tooltipLoader.item.show(I18n.tr("Do Not Disturb"), p.x, p.y - 40, null)
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
onExited: {
|
||||
if (tooltipLoader.item) {
|
||||
tooltipLoader.item.hide()
|
||||
}
|
||||
tooltipLoader.active = false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -139,4 +118,11 @@ Item {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: tooltipLoader
|
||||
|
||||
active: false
|
||||
sourceComponent: DankTooltip {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,16 @@ Item {
|
||||
checked)
|
||||
}
|
||||
}
|
||||
DankToggle {
|
||||
width: parent.width
|
||||
text: I18n.tr("Window Scrolling")
|
||||
description: "Scroll through windows, rather than workspaces"
|
||||
checked: SettingsData.workspaceScrolling
|
||||
visible: CompositorService.isNiri
|
||||
onToggled: checked => {
|
||||
return SettingsData.setWorkspaceScrolling(checked)
|
||||
}
|
||||
}
|
||||
|
||||
DankToggle {
|
||||
width: parent.width
|
||||
|
||||
33
README.md
33
README.md
@@ -177,20 +177,39 @@ paru -S dms-shell-bin
|
||||
paru -S dms-shell-git
|
||||
```
|
||||
|
||||
#### nixOS - via flake
|
||||
#### Fedora - via COPR
|
||||
|
||||
```bash
|
||||
# Stable release
|
||||
sudo dnf copr enable avengemedia/dms && sudo dnf install dms
|
||||
# Latest -git
|
||||
sudo dnf copr enable avengemedia/dms-git && sudo dnf install dms
|
||||
```
|
||||
|
||||
#### NixOS - via flake
|
||||
|
||||
```bash
|
||||
nix profile install github:AvengeMedia/DankMaterialShell
|
||||
```
|
||||
|
||||
#### nixOS - via home-manager
|
||||
#### NixOS - via home-manager
|
||||
|
||||
To install using home-manager, you need to add this repo into your flake inputs:
|
||||
|
||||
``` nix
|
||||
dgop = {
|
||||
url = "github:AvengeMedia/dgop";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
dms-cli = {
|
||||
url = "github:AvengeMedia/danklinux";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
dankMaterialShell = {
|
||||
url = "github:AvengeMedia/DankMaterialShell";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.dgop.follows = "dgop";
|
||||
inputs.dms-cli.follows = "dms-cli";
|
||||
};
|
||||
```
|
||||
|
||||
@@ -244,7 +263,7 @@ There are a lot of possible configurations that you can enable/disable in the fl
|
||||
# Arch
|
||||
paru -S quickshell-git
|
||||
# Fedora
|
||||
sudo dnf copr enable errornointernet/quickshell && sudo dnf install quickshell-git
|
||||
sudo dnf copr enable avengemedia/danklinux && sudo dnf install quickshell-git
|
||||
# ! TODO - document other distros
|
||||
```
|
||||
|
||||
@@ -291,10 +310,10 @@ sudo pacman -S cava wl-clipboard cliphist brightnessctl qt6-multimedia
|
||||
paru -S matugen-bin dgop
|
||||
|
||||
# Fedora
|
||||
sudo dnf install cava wl-clipboard brightnessctl qt6-qtmultimedia
|
||||
sudo dnf copr enable wef/cliphist && sudo dnf install cliphist
|
||||
sudo dnf copr enable heus-sueh/packages && sudo dnf install matugen
|
||||
sudo dnf install cava wl-clipboard brightnessctl qt6-qtmultimedia
|
||||
sudo dnf copr enable avengemedia/danklinux && sudo dnf install cliphist ghostty hyprpicker material-symbols-fonts matugen
|
||||
```
|
||||
Note: by enabling and installing the avengemedia/dms copr above, these core dependencies will automatically be available for use.
|
||||
|
||||
*Other distros will just need to find sources for the above packages*
|
||||
|
||||
@@ -665,7 +684,7 @@ cp -R ./PLUGINS/ExampleEmojiPlugin ~/.config/DankMaterialShell/plugins
|
||||
|
||||
**Only install plugins from TRUSTED sources.** Plugins execute QML and javascript at runtime, plugins from third parties should be reviewed before enabling them in dms.
|
||||
|
||||
### nixOS - via home-manager
|
||||
### NixOS - via home-manager
|
||||
|
||||
Add the following to your home-manager config to install a plugin:
|
||||
|
||||
|
||||
@@ -342,13 +342,13 @@ Singleton {
|
||||
}
|
||||
|
||||
function playNormalNotificationSound() {
|
||||
if (soundsAvailable && normalNotificationSound) {
|
||||
if (soundsAvailable && normalNotificationSound && !SessionData.doNotDisturb) {
|
||||
normalNotificationSound.play()
|
||||
}
|
||||
}
|
||||
|
||||
function playCriticalNotificationSound() {
|
||||
if (soundsAvailable && criticalNotificationSound) {
|
||||
if (soundsAvailable && criticalNotificationSound && !SessionData.doNotDisturb) {
|
||||
criticalNotificationSound.play()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ Singleton {
|
||||
property bool ethernetConnected: false
|
||||
property string ethernetConnectionUuid: ""
|
||||
|
||||
property var wiredConnections: []
|
||||
|
||||
property string wifiIP: ""
|
||||
property string wifiInterface: ""
|
||||
property bool wifiConnected: false
|
||||
@@ -73,6 +75,10 @@ Singleton {
|
||||
property string networkInfoSSID: ""
|
||||
property string networkInfoDetails: ""
|
||||
property bool networkInfoLoading: false
|
||||
|
||||
property string networkWiredInfoUUID: ""
|
||||
property string networkWiredInfoDetails: ""
|
||||
property bool networkWiredInfoLoading: false
|
||||
|
||||
signal networksUpdated
|
||||
signal connectionChanged
|
||||
|
||||
@@ -20,6 +20,8 @@ Singleton {
|
||||
property bool ethernetConnected: false
|
||||
property string ethernetConnectionUuid: ""
|
||||
|
||||
property var wiredConnections: []
|
||||
|
||||
property string wifiIP: ""
|
||||
property string wifiInterface: ""
|
||||
property bool wifiConnected: false
|
||||
@@ -69,6 +71,10 @@ Singleton {
|
||||
property string networkInfoSSID: ""
|
||||
property string networkInfoDetails: ""
|
||||
property bool networkInfoLoading: false
|
||||
|
||||
property string networkWiredInfoUUID: ""
|
||||
property string networkWiredInfoDetails: ""
|
||||
property bool networkWiredInfoLoading: false
|
||||
|
||||
property int refCount: 0
|
||||
property bool stateInitialized: false
|
||||
@@ -179,6 +185,8 @@ Singleton {
|
||||
ethernetConnected = state.ethernetConnected || false
|
||||
ethernetConnectionUuid = state.ethernetConnectionUuid || ""
|
||||
|
||||
wiredConnections = state.wiredConnections || []
|
||||
|
||||
wifiIP = state.wifiIP || ""
|
||||
wifiInterface = state.wifiDevice || ""
|
||||
wifiConnected = state.wifiConnected || false
|
||||
@@ -219,6 +227,31 @@ Singleton {
|
||||
|
||||
connectionChanged()
|
||||
}
|
||||
|
||||
function connectToSpecificWiredConfig(uuid) {
|
||||
if (!networkAvailable || isConnecting) return
|
||||
|
||||
isConnecting = true
|
||||
connectionError = ""
|
||||
connectionStatus = "connecting"
|
||||
|
||||
const params = { uuid: uuid }
|
||||
|
||||
DMSService.sendRequest("network.ethernet.connect.config", params, response => {
|
||||
if (response.error) {
|
||||
connectionError = response.error
|
||||
lastConnectionError = response.error
|
||||
connectionStatus = "failed"
|
||||
ToastService.showError(`Failed to activate configuration`)
|
||||
} else {
|
||||
connectionError = ""
|
||||
connectionStatus = "connected"
|
||||
ToastService.showInfo(`Configuration activated`)
|
||||
}
|
||||
|
||||
isConnecting = false
|
||||
})
|
||||
}
|
||||
|
||||
function scanWifi() {
|
||||
if (!networkAvailable || isScanning || !wifiEnabled) return
|
||||
@@ -413,6 +446,61 @@ Singleton {
|
||||
autoScan = false
|
||||
autoRefreshEnabled = false
|
||||
}
|
||||
|
||||
function fetchWiredNetworkInfo(uuid) {
|
||||
if (!networkAvailable) return
|
||||
|
||||
networkWiredInfoUUID = uuid
|
||||
networkWiredInfoLoading = true
|
||||
networkWiredInfoDetails = "Loading network information..."
|
||||
|
||||
DMSService.sendRequest("network.ethernet.info", { uuid: uuid }, response => {
|
||||
networkWiredInfoLoading = false
|
||||
|
||||
if (response.error) {
|
||||
networkWiredInfoDetails = "Failed to fetch network information"
|
||||
} else if (response.result) {
|
||||
formatWiredNetworkInfo(response.result)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function formatWiredNetworkInfo(info) {
|
||||
let details = ""
|
||||
|
||||
if (!info) {
|
||||
details = "Network information not found or network not available."
|
||||
} else {
|
||||
details += "Inteface: " + info.iface + "\\n"
|
||||
details += "Driver: " + info.driver + "\\n"
|
||||
details += "MAC Addr: " + info.hwAddr + "\\n"
|
||||
details += "Speed: " + info.speed + " Mb/s\\n\\n"
|
||||
|
||||
details += "IPv4 informations:\\n"
|
||||
|
||||
for (const ip4 of info.IPv4s.ips) {
|
||||
details += " IPv4 address: " + ip4 + "\\n"
|
||||
}
|
||||
details += " Gateway: " + info.IPv4s.gateway + "\\n"
|
||||
details += " DNS: " + info.IPv4s.dns + "\\n"
|
||||
|
||||
if (info.IPv6s.ips) {
|
||||
details += "\\nIPv6 informations:\\n"
|
||||
|
||||
for (const ip6 of info.IPv6s.ips) {
|
||||
details += " IPv6 address: " + ip6 + "\\n"
|
||||
}
|
||||
if (info.IPv6s.gateway.length > 0) {
|
||||
details += " Gateway: " + info.IPv6s.gateway + "\\n"
|
||||
}
|
||||
if (info.IPv6s.dns.length > 0) {
|
||||
details += " DNS: " + info.IPv6s.dns + "\\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
networkWiredInfoDetails = details
|
||||
}
|
||||
|
||||
function fetchNetworkInfo(ssid) {
|
||||
if (!networkAvailable) return
|
||||
@@ -483,6 +571,17 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
function getWiredNetworkInfo(uuid) {
|
||||
const network = wiredConnections.find(n => n.uuid === uuid)
|
||||
if (!network) {
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
"uuid": uuid,
|
||||
}
|
||||
}
|
||||
|
||||
function refreshNetworkState() {
|
||||
if (networkAvailable) {
|
||||
getState()
|
||||
|
||||
@@ -19,6 +19,8 @@ Singleton {
|
||||
property bool ethernetConnected: activeService?.ethernetConnected ?? false
|
||||
property string ethernetConnectionUuid: activeService?.ethernetConnectionUuid ?? ""
|
||||
|
||||
property var wiredConnections: activeService?.wiredConnections ?? []
|
||||
|
||||
property string wifiIP: activeService?.wifiIP ?? ""
|
||||
property string wifiInterface: activeService?.wifiInterface ?? ""
|
||||
property bool wifiConnected: activeService?.wifiConnected ?? false
|
||||
@@ -57,6 +59,10 @@ Singleton {
|
||||
property string networkInfoSSID: activeService?.networkInfoSSID ?? ""
|
||||
property string networkInfoDetails: activeService?.networkInfoDetails ?? ""
|
||||
property bool networkInfoLoading: activeService?.networkInfoLoading ?? false
|
||||
|
||||
property string networkWiredInfoUUID: activeService?.networkWiredInfoUUID ?? ""
|
||||
property string networkWiredInfoDetails: activeService?.networkWiredInfoDetails ?? ""
|
||||
property bool networkWiredInfoLoading: activeService?.networkWiredInfoLoading ?? false
|
||||
|
||||
property int refCount: activeService?.refCount ?? 0
|
||||
property bool stateInitialized: activeService?.stateInitialized ?? false
|
||||
@@ -221,6 +227,12 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
function fetchWiredNetworkInfo(uuid) {
|
||||
if (activeService && activeService.fetchWiredNetworkInfo) {
|
||||
activeService.fetchWiredNetworkInfo(uuid)
|
||||
}
|
||||
}
|
||||
|
||||
function getNetworkInfo(ssid) {
|
||||
if (activeService && activeService.getNetworkInfo) {
|
||||
return activeService.getNetworkInfo(ssid)
|
||||
@@ -228,9 +240,22 @@ Singleton {
|
||||
return null
|
||||
}
|
||||
|
||||
function getWiredNetworkInfo(uuid) {
|
||||
if (activeService && activeService.getWiredNetworkInfo) {
|
||||
return activeService.getWiredNetworkInfo(uuid)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function refreshNetworkState() {
|
||||
if (activeService && activeService.refreshNetworkState) {
|
||||
activeService.refreshNetworkState()
|
||||
}
|
||||
}
|
||||
|
||||
function connectToSpecificWiredConfig(uuid) {
|
||||
if (activeService && activeService.connectToSpecificWiredConfig) {
|
||||
activeService.connectToSpecificWiredConfig(uuid)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ import qs.Common
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
property int refCount: 0
|
||||
|
||||
readonly property string baseDir: Paths.strip(StandardPaths.writableLocation(StandardPaths.GenericStateLocation) + "/DankMaterialShell")
|
||||
readonly property string filesDir: baseDir + "/notepad-files"
|
||||
readonly property string metadataPath: baseDir + "/notepad-session.json"
|
||||
@@ -17,10 +19,11 @@ Singleton {
|
||||
property var tabs: []
|
||||
property int currentTabIndex: 0
|
||||
property var tabsBeingCreated: ({})
|
||||
property bool metadataLoaded: false
|
||||
|
||||
FileView {
|
||||
id: metadataFile
|
||||
path: root.metadataPath
|
||||
path: root.refCount > 0 ? root.metadataPath : ""
|
||||
blockWrites: true
|
||||
atomicWrites: true
|
||||
|
||||
@@ -29,6 +32,7 @@ Singleton {
|
||||
var data = JSON.parse(text())
|
||||
root.tabs = data.tabs || []
|
||||
root.currentTabIndex = data.currentTabIndex || 0
|
||||
root.metadataLoaded = true
|
||||
validateTabs()
|
||||
} catch(e) {
|
||||
console.warn("Failed to parse notepad metadata:", e)
|
||||
@@ -41,6 +45,13 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
onRefCountChanged: {
|
||||
if (refCount === 1 && !metadataLoaded) {
|
||||
metadataFile.path = ""
|
||||
metadataFile.path = root.metadataPath
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function loadMetadata() {
|
||||
metadataFile.path = ""
|
||||
|
||||
@@ -17,6 +17,7 @@ Singleton {
|
||||
property int systemColorScheme: 0
|
||||
|
||||
property bool freedeskAvailable: false
|
||||
property string colorSchemeCommand: ""
|
||||
|
||||
readonly property string socketPath: Quickshell.env("DMS_SOCKET")
|
||||
|
||||
@@ -98,18 +99,22 @@ Singleton {
|
||||
if (typeof SettingsData !== "undefined" && SettingsData.syncModeWithPortal === false) {
|
||||
return
|
||||
}
|
||||
if (settingsPortalAvailable) {
|
||||
setSystemColorScheme(isLightMode)
|
||||
}
|
||||
setSystemColorScheme(isLightMode)
|
||||
}
|
||||
|
||||
function setSystemColorScheme(isLightMode) {
|
||||
if (typeof SettingsData !== "undefined" && SettingsData.syncModeWithPortal === false) {
|
||||
return
|
||||
}
|
||||
if (!settingsPortalAvailable || !freedeskAvailable) return
|
||||
|
||||
DMSService.sendRequest("freedesktop.settings.setColorScheme", { preferDark: !isLightMode }, response => {})
|
||||
const targetScheme = isLightMode ? "default": "prefer-dark"
|
||||
|
||||
if (colorSchemeCommand === "gsettings") {
|
||||
Quickshell.execDetached(["gsettings", "set", "org.gnome.desktop.interface", "color-scheme", targetScheme])
|
||||
}
|
||||
if (colorSchemeCommand === "dconf") {
|
||||
Quickshell.execDetached(["dconf", "write", "/org/gnome/desktop/interface/color-scheme", `'${targetScheme}'`])
|
||||
}
|
||||
}
|
||||
|
||||
function setSystemIconTheme(themeName) {
|
||||
@@ -140,6 +145,7 @@ Singleton {
|
||||
} else {
|
||||
console.log("PortalService: DMS_SOCKET not set")
|
||||
}
|
||||
colorSchemeDetector.running = true
|
||||
}
|
||||
|
||||
Connections {
|
||||
@@ -240,6 +246,23 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
id: colorSchemeDetector
|
||||
command: ["bash", "-c", "command -v gsettings || command -v dconf"]
|
||||
running: false
|
||||
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
const cmd = text.trim()
|
||||
if (cmd.includes("gsettings")) {
|
||||
root.colorSchemeCommand = "gsettings"
|
||||
} else if (cmd.includes("dconf")) {
|
||||
root.colorSchemeCommand = "dconf"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IpcHandler {
|
||||
target: "profile"
|
||||
|
||||
|
||||
228
dms-greeter.spec
228
dms-greeter.spec
@@ -20,7 +20,10 @@ BuildRequires: rpkg
|
||||
Requires: greetd
|
||||
Requires: (quickshell-git or quickshell)
|
||||
Requires: material-symbols-fonts
|
||||
Requires(post): /usr/sbin/useradd
|
||||
Requires(post): /usr/sbin/groupadd
|
||||
|
||||
Recommends: policycoreutils-python-utils
|
||||
Suggests: niri
|
||||
Suggests: hyprland
|
||||
Suggests: sway
|
||||
@@ -50,12 +53,112 @@ cp -r * %{buildroot}%{_sysconfdir}/xdg/quickshell/dms-greeter/
|
||||
# Install launcher script
|
||||
install -Dm755 Modules/Greetd/assets/dms-greeter %{buildroot}%{_bindir}/dms-greeter
|
||||
|
||||
# Install theme sync helper script
|
||||
cat > %{buildroot}%{_bindir}/dms-greeter-sync << 'SYNC_EOF'
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
if [ "$EUID" -eq 0 ]; then
|
||||
echo "Error: Do not run this script as root. Run as your regular user:"
|
||||
echo " dms-greeter-sync"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CURRENT_USER=$(whoami)
|
||||
CACHE_DIR="/var/cache/dms-greeter"
|
||||
|
||||
echo "=== DMS Greeter Theme Sync Setup ==="
|
||||
echo
|
||||
echo "This will sync your DMS theme with the greeter login screen."
|
||||
echo "User: $CURRENT_USER"
|
||||
echo
|
||||
|
||||
# Add user to greeter group
|
||||
if ! groups "$CURRENT_USER" | grep -q greeter; then
|
||||
echo "Adding $CURRENT_USER to greeter group..."
|
||||
sudo usermod -aG greeter "$CURRENT_USER"
|
||||
echo "✓ Added to greeter group (logout/login required for group membership)"
|
||||
else
|
||||
echo "✓ Already in greeter group"
|
||||
fi
|
||||
|
||||
# Set group permissions on config directories
|
||||
echo
|
||||
echo "Setting group permissions on config directories..."
|
||||
|
||||
# First, ensure parent directories are traversable by greeter user (using ACLs)
|
||||
echo "Making parent directories traversable by greeter..."
|
||||
if command -v setfacl >/dev/null 2>&1; then
|
||||
# Set ACL on home directory
|
||||
setfacl -m u:greeter:x ~ 2>/dev/null && echo "✓ Home directory" || echo "⚠ Home directory (may need sudo)"
|
||||
|
||||
# Set ACLs on parent config directories
|
||||
setfacl -m u:greeter:x ~/.config 2>/dev/null && echo "✓ .config directory" || true
|
||||
setfacl -m u:greeter:x ~/.local 2>/dev/null && echo "✓ .local directory" || true
|
||||
setfacl -m u:greeter:x ~/.cache 2>/dev/null && echo "✓ .cache directory" || true
|
||||
setfacl -m u:greeter:x ~/.local/state 2>/dev/null && echo "✓ .local/state directory" || true
|
||||
else
|
||||
echo "⚠ setfacl not found, you need to run:"
|
||||
echo " setfacl -m u:greeter:x ~ ~/.config ~/.local ~/.cache ~/.local/state"
|
||||
fi
|
||||
|
||||
# Then set permissions on target directories
|
||||
for dir in ~/.config/DankMaterialShell ~/.local/state/DankMaterialShell ~/.cache/quickshell; do
|
||||
if [ -d "$dir" ]; then
|
||||
sudo chgrp -R greeter "$dir"
|
||||
sudo chmod -R g+rX "$dir"
|
||||
echo "✓ $(basename $dir)"
|
||||
else
|
||||
echo "⚠ $dir not found (will be created when you run DMS)"
|
||||
fi
|
||||
done
|
||||
|
||||
# Set group read on parent state directory
|
||||
sudo chmod g+x ~/.local/state 2>/dev/null || true
|
||||
|
||||
# Create symlinks
|
||||
echo
|
||||
echo "Creating symlinks to sync theme..."
|
||||
|
||||
declare -A links=(
|
||||
["$HOME/.config/DankMaterialShell/settings.json"]="$CACHE_DIR/settings.json"
|
||||
["$HOME/.local/state/DankMaterialShell/session.json"]="$CACHE_DIR/session.json"
|
||||
["$HOME/.cache/quickshell/dankshell/dms-colors.json"]="$CACHE_DIR/colors.json"
|
||||
)
|
||||
|
||||
for source in "${!links[@]}"; do
|
||||
target="${links[$source]}"
|
||||
target_name=$(basename "$source")
|
||||
|
||||
if [ -f "$source" ]; then
|
||||
sudo ln -sf "$source" "$target"
|
||||
echo "✓ Synced $target_name"
|
||||
else
|
||||
echo "⚠ $target_name not found yet (run DMS to generate it)"
|
||||
fi
|
||||
done
|
||||
|
||||
echo
|
||||
echo "=== Setup Complete! ==="
|
||||
echo
|
||||
echo "IMPORTANT: You must LOGOUT and LOGIN for group membership to take effect."
|
||||
echo "After logging back in, your theme will be synced with the greeter."
|
||||
SYNC_EOF
|
||||
|
||||
chmod 755 %{buildroot}%{_bindir}/dms-greeter-sync
|
||||
|
||||
# Install documentation
|
||||
install -Dm644 Modules/Greetd/README.md %{buildroot}%{_docdir}/dms-greeter/README.md
|
||||
|
||||
# Create cache directory for greeter data
|
||||
install -dm750 %{buildroot}%{_localstatedir}/cache/dms-greeter
|
||||
|
||||
# Create greeter home directory
|
||||
install -dm755 %{buildroot}%{_sharedstatedir}/greeter
|
||||
|
||||
# Note: We do NOT install a PAM config here to avoid conflicting with greetd package
|
||||
# Instead, we verify/fix it in %post if needed
|
||||
|
||||
# Remove build and development files
|
||||
rm -rf %{buildroot}%{_sysconfdir}/xdg/quickshell/dms-greeter/.git*
|
||||
rm -f %{buildroot}%{_sysconfdir}/xdg/quickshell/dms-greeter/.gitignore
|
||||
@@ -68,23 +171,94 @@ rm -f %{buildroot}%{_sysconfdir}/xdg/quickshell/dms-greeter/dms-greeter.spec
|
||||
%license LICENSE
|
||||
%doc %{_docdir}/dms-greeter/README.md
|
||||
%{_bindir}/dms-greeter
|
||||
%{_bindir}/dms-greeter-sync
|
||||
%{_sysconfdir}/xdg/quickshell/dms-greeter/
|
||||
%dir %attr(0750,greeter,greeter) %{_localstatedir}/cache/dms-greeter
|
||||
%dir %attr(0755,greeter,greeter) %{_sharedstatedir}/greeter
|
||||
|
||||
%pre
|
||||
# Create greeter user/group if they don't exist (greetd expects this)
|
||||
getent group greeter >/dev/null || groupadd -r greeter
|
||||
getent passwd greeter >/dev/null || \
|
||||
useradd -r -g greeter -d /var/lib/greeter -s /sbin/nologin \
|
||||
useradd -r -g greeter -d %{_sharedstatedir}/greeter -s /bin/bash \
|
||||
-c "System Greeter" greeter
|
||||
exit 0
|
||||
|
||||
%post
|
||||
|
||||
# Set SELinux context for the wrapper script on Fedora systems
|
||||
if [ -x /usr/sbin/semanage ]; then
|
||||
semanage fcontext -a -t bin_t %{_bindir}/dms-greeter 2>/dev/null || true
|
||||
restorecon -v %{_bindir}/dms-greeter 2>/dev/null || true
|
||||
# Set SELinux contexts for greeter files on Fedora systems
|
||||
if [ -x /usr/sbin/semanage ] && [ -x /usr/sbin/restorecon ]; then
|
||||
# Greeter launcher binary
|
||||
semanage fcontext -a -t bin_t '%{_bindir}/dms-greeter' >/dev/null 2>&1 || true
|
||||
restorecon %{_bindir}/dms-greeter >/dev/null 2>&1 || true
|
||||
|
||||
# Greeter home directory
|
||||
semanage fcontext -a -t user_home_dir_t '%{_sharedstatedir}/greeter(/.*)?' >/dev/null 2>&1 || true
|
||||
restorecon -R %{_sharedstatedir}/greeter >/dev/null 2>&1 || true
|
||||
|
||||
# Cache directory for greeter data
|
||||
semanage fcontext -a -t cache_home_t '%{_localstatedir}/cache/dms-greeter(/.*)?' >/dev/null 2>&1 || true
|
||||
restorecon -R %{_localstatedir}/cache/dms-greeter >/dev/null 2>&1 || true
|
||||
|
||||
# Config directory
|
||||
semanage fcontext -a -t etc_t '%{_sysconfdir}/xdg/quickshell/dms-greeter(/.*)?' >/dev/null 2>&1 || true
|
||||
restorecon -R %{_sysconfdir}/xdg/quickshell/dms-greeter >/dev/null 2>&1 || true
|
||||
|
||||
# PAM configuration
|
||||
restorecon %{_sysconfdir}/pam.d/greetd >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
# Ensure proper ownership of greeter directories
|
||||
chown -R greeter:greeter %{_localstatedir}/cache/dms-greeter 2>/dev/null || true
|
||||
chown -R greeter:greeter %{_sharedstatedir}/greeter 2>/dev/null || true
|
||||
|
||||
# Verify PAM configuration - only fix if insufficient
|
||||
PAM_CONFIG="/etc/pam.d/greetd"
|
||||
if [ ! -f "$PAM_CONFIG" ]; then
|
||||
# PAM config doesn't exist - create it
|
||||
cat > "$PAM_CONFIG" << 'PAM_EOF'
|
||||
#%PAM-1.0
|
||||
auth substack system-auth
|
||||
auth include postlogin
|
||||
|
||||
account required pam_nologin.so
|
||||
account include system-auth
|
||||
|
||||
password include system-auth
|
||||
|
||||
session required pam_selinux.so close
|
||||
session required pam_loginuid.so
|
||||
session required pam_selinux.so open
|
||||
session optional pam_keyinit.so force revoke
|
||||
session include system-auth
|
||||
session include postlogin
|
||||
PAM_EOF
|
||||
chmod 644 "$PAM_CONFIG"
|
||||
# Only show message on initial install
|
||||
[ "$1" -eq 1 ] && echo "Created PAM configuration for greetd"
|
||||
elif ! grep -q "pam_systemd\|system-auth" "$PAM_CONFIG"; then
|
||||
# PAM config exists but looks insufficient - back it up and replace
|
||||
cp "$PAM_CONFIG" "$PAM_CONFIG.backup-dms-greeter"
|
||||
cat > "$PAM_CONFIG" << 'PAM_EOF'
|
||||
#%PAM-1.0
|
||||
auth substack system-auth
|
||||
auth include postlogin
|
||||
|
||||
account required pam_nologin.so
|
||||
account include system-auth
|
||||
|
||||
password include system-auth
|
||||
|
||||
session required pam_selinux.so close
|
||||
session required pam_loginuid.so
|
||||
session required pam_selinux.so open
|
||||
session optional pam_keyinit.so force revoke
|
||||
session include system-auth
|
||||
session include postlogin
|
||||
PAM_EOF
|
||||
chmod 644 "$PAM_CONFIG"
|
||||
# Only show message on initial install
|
||||
[ "$1" -eq 1 ] && echo "Updated PAM configuration (old config backed up to $PAM_CONFIG.backup-dms-greeter)"
|
||||
fi
|
||||
|
||||
# Auto-configure greetd config
|
||||
@@ -132,42 +306,40 @@ cat << EOF
|
||||
DMS Greeter Installation Complete!
|
||||
===============================================================================
|
||||
|
||||
Configuration status:
|
||||
- Greeter cache directory: /var/cache/dms-greeter (created with proper permissions)
|
||||
- SELinux contexts: Applied (if semanage available)
|
||||
Status:
|
||||
- Greeter user: Created ✓
|
||||
- Greeter directories: /var/cache/dms-greeter, /var/lib/greeter ✓
|
||||
- SELinux contexts: Applied ✓
|
||||
- Greetd config: $CONFIG_STATUS
|
||||
|
||||
Next steps to enable the greeter:
|
||||
Next steps:
|
||||
|
||||
1. IMPORTANT: Disable any existing display managers:
|
||||
1. Disable any existing display managers (IMPORTANT):
|
||||
sudo systemctl disable gdm sddm lightdm
|
||||
(Only greetd should run as the display manager)
|
||||
|
||||
2. Verify greetd configuration:
|
||||
Check /etc/greetd/config.toml contains:
|
||||
|
||||
[default_session]
|
||||
user = "greeter"
|
||||
command = "/usr/bin/dms-greeter --command niri"
|
||||
|
||||
(Also supported: hyprland, sway)
|
||||
Note: Existing config backed up to config.toml.backup-* if modified
|
||||
|
||||
3. Enable greetd service:
|
||||
2. Enable greetd service:
|
||||
sudo systemctl enable greetd
|
||||
|
||||
4. (Optional) Sync your user's theme with the greeter:
|
||||
sudo usermod -aG greeter YOUR_USERNAME
|
||||
# Then LOGOUT and LOGIN to apply group membership
|
||||
ln -sf ~/.config/DankMaterialShell/settings.json /var/cache/dms-greeter/settings.json
|
||||
ln -sf ~/.local/state/DankMaterialShell/session.json /var/cache/dms-greeter/session.json
|
||||
ln -sf ~/.cache/quickshell/dankshell/dms-colors.json /var/cache/dms-greeter/colors.json
|
||||
3. (Optional) Sync your theme with the greeter:
|
||||
dms-greeter-sync
|
||||
|
||||
Then logout/login to see your wallpaper on the greeter!
|
||||
|
||||
Ready to test? Reboot or run: sudo systemctl start greetd
|
||||
Documentation: /usr/share/doc/dms-greeter/README.md
|
||||
===============================================================================
|
||||
|
||||
EOF
|
||||
fi
|
||||
|
||||
%postun
|
||||
# Clean up SELinux contexts on package removal
|
||||
if [ "$1" -eq 0 ] && [ -x /usr/sbin/semanage ]; then
|
||||
semanage fcontext -d '%{_bindir}/dms-greeter' 2>/dev/null || true
|
||||
semanage fcontext -d '%{_sharedstatedir}/greeter(/.*)?' 2>/dev/null || true
|
||||
semanage fcontext -d '%{_localstatedir}/cache/dms-greeter(/.*)?' 2>/dev/null || true
|
||||
semanage fcontext -d '%{_sysconfdir}/xdg/quickshell/dms-greeter(/.*)?' 2>/dev/null || true
|
||||
fi
|
||||
|
||||
%changelog
|
||||
{{{ git_dir_changelog }}}
|
||||
|
||||
42
dms.spec
42
dms.spec
@@ -18,14 +18,12 @@ Source0: {{{ git_dir_pack }}}
|
||||
# DMS CLI from danklinux latest commit
|
||||
Source1: https://github.com/AvengeMedia/danklinux/archive/refs/heads/master.tar.gz
|
||||
|
||||
# DGOP binary from dgop latest release
|
||||
Source2: https://github.com/AvengeMedia/dgop/releases/latest/download/dgop-linux-amd64.gz
|
||||
|
||||
BuildRequires: git-core
|
||||
BuildRequires: rpkg
|
||||
BuildRequires: gzip
|
||||
BuildRequires: golang >= 1.24
|
||||
BuildRequires: make
|
||||
BuildRequires: wget
|
||||
|
||||
# Core requirements
|
||||
Requires: (quickshell-git or quickshell)
|
||||
@@ -85,8 +83,25 @@ used standalone. This package always includes the latest stable dgop release.
|
||||
# Extract DankLinux source
|
||||
tar -xzf %{SOURCE1} -C %{_builddir}
|
||||
|
||||
# Extract DGOP binary
|
||||
gunzip -c %{SOURCE2} > %{_builddir}/dgop
|
||||
# Download and extract DGOP binary for target architecture
|
||||
case "%{_arch}" in
|
||||
x86_64)
|
||||
DGOP_ARCH="amd64"
|
||||
;;
|
||||
aarch64)
|
||||
DGOP_ARCH="arm64"
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported architecture: %{_arch}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
wget -O %{_builddir}/dgop.gz "https://github.com/AvengeMedia/dgop/releases/latest/download/dgop-linux-${DGOP_ARCH}.gz" || {
|
||||
echo "Failed to download dgop for architecture %{_arch}"
|
||||
exit 1
|
||||
}
|
||||
gunzip -c %{_builddir}/dgop.gz > %{_builddir}/dgop
|
||||
chmod +x %{_builddir}/dgop
|
||||
|
||||
%build
|
||||
@@ -95,8 +110,21 @@ cd %{_builddir}/danklinux-master
|
||||
make dist
|
||||
|
||||
%install
|
||||
# Install dms-cli binary (built from source)
|
||||
install -Dm755 %{_builddir}/danklinux-master/bin/dms-linux-amd64 %{buildroot}%{_bindir}/dms
|
||||
# Install dms-cli binary (built from source) - use architecture-specific path
|
||||
case "%{_arch}" in
|
||||
x86_64)
|
||||
DMS_BINARY="dms-linux-amd64"
|
||||
;;
|
||||
aarch64)
|
||||
DMS_BINARY="dms-linux-arm64"
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported architecture: %{_arch}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
install -Dm755 %{_builddir}/danklinux-master/bin/${DMS_BINARY} %{buildroot}%{_bindir}/dms
|
||||
|
||||
# Install dgop binary
|
||||
install -Dm755 %{_builddir}/dgop %{buildroot}%{_bindir}/dgop
|
||||
|
||||
@@ -140,7 +140,7 @@
|
||||
{
|
||||
"term": "Always Show OSD Percentage",
|
||||
"context": "Always Show OSD Percentage",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:637",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:647",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -152,7 +152,7 @@
|
||||
{
|
||||
"term": "Anonymous Identity (optional)",
|
||||
"context": "Anonymous Identity (optional)",
|
||||
"reference": "Modals/WifiPasswordModal.qml:388",
|
||||
"reference": "Modals/WifiPasswordModal.qml:282",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -368,7 +368,7 @@
|
||||
{
|
||||
"term": "Back",
|
||||
"context": "Back",
|
||||
"reference": "Modules/DankBar/Widgets/SystemTrayBar.qml:451",
|
||||
"reference": "Modules/DankBar/Widgets/SystemTrayBar.qml:454",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -482,7 +482,7 @@
|
||||
{
|
||||
"term": "Cancel",
|
||||
"context": "Cancel",
|
||||
"reference": "Modals/DankColorPickerModal.qml:510, Modals/WifiPasswordModal.qml:491, Modals/FileBrowser/FileBrowserModal.qml:952, Modules/Settings/PluginsTab.qml:1220",
|
||||
"reference": "Modals/DankColorPickerModal.qml:510, Modals/WifiPasswordModal.qml:385, Modals/FileBrowser/FileBrowserModal.qml:952, Modules/Settings/PluginsTab.qml:1220",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -530,7 +530,7 @@
|
||||
{
|
||||
"term": "Choose where notification popups appear on screen",
|
||||
"context": "Choose where notification popups appear on screen",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:564",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:574",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -542,7 +542,7 @@
|
||||
{
|
||||
"term": "Clear All",
|
||||
"context": "Clear All",
|
||||
"reference": "Modals/Clipboard/ClipboardHistoryModal.qml:157, Modules/Notifications/Center/NotificationHeader.qml:123",
|
||||
"reference": "Modals/Clipboard/ClipboardHistoryModal.qml:157, Modules/Notifications/Center/NotificationHeader.qml:102",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -578,7 +578,7 @@
|
||||
{
|
||||
"term": "Close",
|
||||
"context": "Close",
|
||||
"reference": "Modules/SystemUpdatePopout.qml:333, Modals/NetworkInfoModal.qml:129, Modules/DankBar/Widgets/RunningApps.qml:614",
|
||||
"reference": "Modules/SystemUpdatePopout.qml:333, Modals/NetworkWiredInfoModal.qml:129, Modals/NetworkInfoModal.qml:129, Modules/DankBar/Widgets/RunningApps.qml:614",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -602,31 +602,37 @@
|
||||
{
|
||||
"term": "Command or script to run instead of the standard hibernate procedure",
|
||||
"context": "Command or script to run instead of the standard hibernate procedure",
|
||||
"reference": "Modals/Settings/PowerSettings.qml:464",
|
||||
"reference": "Modals/Settings/PowerSettings.qml:496",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Command or script to run instead of the standard lock procedure",
|
||||
"context": "Command or script to run instead of the standard lock procedure",
|
||||
"reference": "Modals/Settings/PowerSettings.qml:400",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Command or script to run instead of the standard logout procedure",
|
||||
"context": "Command or script to run instead of the standard logout procedure",
|
||||
"reference": "Modals/Settings/PowerSettings.qml:400",
|
||||
"reference": "Modals/Settings/PowerSettings.qml:432",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Command or script to run instead of the standard power off procedure",
|
||||
"context": "Command or script to run instead of the standard power off procedure",
|
||||
"reference": "Modals/Settings/PowerSettings.qml:528",
|
||||
"reference": "Modals/Settings/PowerSettings.qml:560",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Command or script to run instead of the standard reboot procedure",
|
||||
"context": "Command or script to run instead of the standard reboot procedure",
|
||||
"reference": "Modals/Settings/PowerSettings.qml:496",
|
||||
"reference": "Modals/Settings/PowerSettings.qml:528",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Command or script to run instead of the standard suspend procedure",
|
||||
"context": "Command or script to run instead of the standard suspend procedure",
|
||||
"reference": "Modals/Settings/PowerSettings.qml:432",
|
||||
"reference": "Modals/Settings/PowerSettings.qml:464",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -650,7 +656,7 @@
|
||||
{
|
||||
"term": "Configure icons for named workspaces. Icons take priority over numbers when both are enabled.",
|
||||
"context": "Configure icons for named workspaces. Icons take priority over numbers when both are enabled.",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:400",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:410",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -662,13 +668,13 @@
|
||||
{
|
||||
"term": "Connect",
|
||||
"context": "Connect",
|
||||
"reference": "Modals/WifiPasswordModal.qml:527",
|
||||
"reference": "Modals/WifiPasswordModal.qml:419",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Connect to Wi-Fi",
|
||||
"context": "Connect to Wi-Fi",
|
||||
"reference": "Modals/WifiPasswordModal.qml:124",
|
||||
"reference": "Modals/WifiPasswordModal.qml:114",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -938,7 +944,7 @@
|
||||
{
|
||||
"term": "Display volume and brightness percentage values by default in OSD popups",
|
||||
"context": "Display volume and brightness percentage values by default in OSD popups",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:644",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:654",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -956,7 +962,7 @@
|
||||
{
|
||||
"term": "Do Not Disturb",
|
||||
"context": "Do Not Disturb",
|
||||
"reference": "Modules/Notifications/Center/NotificationHeader.qml:56, Modules/Notifications/Center/NotificationSettings.qml:131",
|
||||
"reference": "Modules/Notifications/Center/NotificationHeader.qml:41, Modules/Notifications/Center/NotificationSettings.qml:131",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -977,6 +983,12 @@
|
||||
"reference": "Modules/Settings/DockTab.qml:530",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Domain (optional)",
|
||||
"context": "Domain (optional)",
|
||||
"reference": "Modals/WifiPasswordModal.qml:314",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Drag widgets to reorder within sections. Use the eye icon to hide/show widgets (maintains spacing), or X to remove them completely.",
|
||||
"context": "Drag widgets to reorder within sections. Use the eye icon to hide/show widgets (maintains spacing), or X to remove them completely.",
|
||||
@@ -1028,7 +1040,7 @@
|
||||
{
|
||||
"term": "Enable WiFi",
|
||||
"context": "Enable WiFi",
|
||||
"reference": "Modules/ControlCenter/Details/NetworkDetail.qml:169",
|
||||
"reference": "Modules/ControlCenter/Details/NetworkDetail.qml:173",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -1052,7 +1064,7 @@
|
||||
{
|
||||
"term": "Enter credentials for ",
|
||||
"context": "Enter credentials for ",
|
||||
"reference": "Modals/WifiPasswordModal.qml:131",
|
||||
"reference": "Modals/WifiPasswordModal.qml:121",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -1076,7 +1088,7 @@
|
||||
{
|
||||
"term": "Enter password for ",
|
||||
"context": "Enter password for ",
|
||||
"reference": "Modals/WifiPasswordModal.qml:131",
|
||||
"reference": "Modals/WifiPasswordModal.qml:121",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -1178,7 +1190,7 @@
|
||||
{
|
||||
"term": "Forget Network",
|
||||
"context": "Forget Network",
|
||||
"reference": "Modules/ControlCenter/Details/NetworkDetail.qml:422",
|
||||
"reference": "Modules/ControlCenter/Details/NetworkDetail.qml:598",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -1574,7 +1586,7 @@
|
||||
{
|
||||
"term": "Max apps to show",
|
||||
"context": "Max apps to show",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:104",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:114",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -1592,7 +1604,7 @@
|
||||
{
|
||||
"term": "Media Player Settings",
|
||||
"context": "Media Player Settings",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:173",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:183",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -1664,7 +1676,7 @@
|
||||
{
|
||||
"term": "Named Workspace Icons",
|
||||
"context": "Named Workspace Icons",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:390",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:400",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -1688,19 +1700,19 @@
|
||||
{
|
||||
"term": "Network Info",
|
||||
"context": "Network Info",
|
||||
"reference": "Modules/ControlCenter/Details/NetworkDetail.qml:399",
|
||||
"reference": "Modules/ControlCenter/Details/NetworkDetail.qml:340, Modules/ControlCenter/Details/NetworkDetail.qml:575",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Network Information",
|
||||
"context": "Network Information",
|
||||
"reference": "Modals/NetworkInfoModal.qml:59",
|
||||
"reference": "Modals/NetworkWiredInfoModal.qml:59, Modals/NetworkInfoModal.qml:59",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Network Settings",
|
||||
"context": "Network Settings",
|
||||
"reference": "Modules/ControlCenter/Details/NetworkDetail.qml:44",
|
||||
"reference": "Modules/ControlCenter/Details/NetworkDetail.qml:64",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -1814,7 +1826,7 @@
|
||||
{
|
||||
"term": "Notepad",
|
||||
"context": "Notepad",
|
||||
"reference": "DMSShell.qml:406, Modules/Settings/DankBarTab.qml:175",
|
||||
"reference": "DMSShell.qml:407, Modules/Settings/DankBarTab.qml:175",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -1844,7 +1856,7 @@
|
||||
{
|
||||
"term": "Notification Popups",
|
||||
"context": "Notification Popups",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:547",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:557",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -1898,7 +1910,7 @@
|
||||
{
|
||||
"term": "Open Notepad File",
|
||||
"context": "Open Notepad File",
|
||||
"reference": "Modules/Notepad/Notepad.qml:321",
|
||||
"reference": "Modules/Notepad/Notepad.qml:325",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -1928,7 +1940,7 @@
|
||||
{
|
||||
"term": "Password",
|
||||
"context": "Password",
|
||||
"reference": "Modals/WifiPasswordModal.qml:211",
|
||||
"reference": "Modals/WifiPasswordModal.qml:203",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -1946,7 +1958,7 @@
|
||||
{
|
||||
"term": "Per-Monitor Workspaces",
|
||||
"context": "Per-Monitor Workspaces",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:135",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:145",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -2036,7 +2048,7 @@
|
||||
{
|
||||
"term": "Popup Position",
|
||||
"context": "Popup Position",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:563",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:573",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -2141,12 +2153,6 @@
|
||||
"reference": "Modules/DankDash/WeatherTab.qml:448, Modules/Settings/TimeWeatherTab.qml:1275",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Realm / Domain (optional)",
|
||||
"context": "Realm / Domain (optional)",
|
||||
"reference": "Modals/WifiPasswordModal.qml:294",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Reboot",
|
||||
"context": "Reboot",
|
||||
@@ -2204,25 +2210,25 @@
|
||||
{
|
||||
"term": "Running Apps Only In Current Workspace",
|
||||
"context": "Running Apps Only In Current Workspace",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:350",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:360",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Running Apps Settings",
|
||||
"context": "Running Apps Settings",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:340",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:350",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Save",
|
||||
"context": "Save",
|
||||
"reference": "Modals/FileBrowser/FileBrowserModal.qml:818, Modules/Notepad/NotepadTextEditor.qml:511, Modules/Notepad/Notepad.qml:476",
|
||||
"reference": "Modals/FileBrowser/FileBrowserModal.qml:818, Modules/Notepad/NotepadTextEditor.qml:511, Modules/Notepad/Notepad.qml:480",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Save Notepad File",
|
||||
"context": "Save Notepad File",
|
||||
"reference": "Modules/Notepad/Notepad.qml:257",
|
||||
"reference": "Modules/Notepad/Notepad.qml:261",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -2339,12 +2345,6 @@
|
||||
"reference": "Modules/Settings/DankBarTab.qml:156",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Server Domain for certificate (optional)",
|
||||
"context": "Server Domain for certificate (optional)",
|
||||
"reference": "Modals/WifiPasswordModal.qml:420",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Set different wallpapers for each connected monitor",
|
||||
"context": "Set different wallpapers for each connected monitor",
|
||||
@@ -2396,7 +2396,7 @@
|
||||
{
|
||||
"term": "Show Workspace Apps",
|
||||
"context": "Show Workspace Apps",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:82",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:92",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -2420,7 +2420,7 @@
|
||||
{
|
||||
"term": "Show password",
|
||||
"context": "Show password",
|
||||
"reference": "Modals/WifiPasswordModal.qml:463",
|
||||
"reference": "Modals/WifiPasswordModal.qml:357",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -2612,7 +2612,7 @@
|
||||
{
|
||||
"term": "System Updater",
|
||||
"context": "System Updater",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:220",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:230",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -2630,7 +2630,7 @@
|
||||
{
|
||||
"term": "System update custom command",
|
||||
"context": "System update custom command",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:251",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:261",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -2654,7 +2654,7 @@
|
||||
{
|
||||
"term": "Terminal custom additional parameters",
|
||||
"context": "Terminal custom additional parameters",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:284",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:294",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -2774,7 +2774,7 @@
|
||||
{
|
||||
"term": "Unsaved Changes",
|
||||
"context": "Unsaved Changes",
|
||||
"reference": "Modules/Notepad/Notepad.qml:384",
|
||||
"reference": "Modules/Notepad/Notepad.qml:388",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -2792,7 +2792,7 @@
|
||||
{
|
||||
"term": "Untitled",
|
||||
"context": "Untitled",
|
||||
"reference": "Services/NotepadStorageService.qml:62, Services/NotepadStorageService.qml:132, Services/NotepadStorageService.qml:173",
|
||||
"reference": "Services/NotepadStorageService.qml:73, Services/NotepadStorageService.qml:143, Services/NotepadStorageService.qml:184",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -2810,7 +2810,7 @@
|
||||
{
|
||||
"term": "Use Custom Command",
|
||||
"context": "Use Custom Command",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:230",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:240",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -2840,7 +2840,7 @@
|
||||
{
|
||||
"term": "Use custom command for update your system",
|
||||
"context": "Use custom command for update your system",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:231",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:241",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -2876,7 +2876,7 @@
|
||||
{
|
||||
"term": "Username",
|
||||
"context": "Username",
|
||||
"reference": "Modals/WifiPasswordModal.qml:174",
|
||||
"reference": "Modals/WifiPasswordModal.qml:166",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -2942,7 +2942,7 @@
|
||||
{
|
||||
"term": "Wave Progress Bars",
|
||||
"context": "Wave Progress Bars",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:183",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:193",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -2966,7 +2966,7 @@
|
||||
{
|
||||
"term": "WiFi is off",
|
||||
"context": "WiFi is off",
|
||||
"reference": "Modules/ControlCenter/Details/NetworkDetail.qml:151",
|
||||
"reference": "Modules/ControlCenter/Details/NetworkDetail.qml:155",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -2993,6 +2993,12 @@
|
||||
"reference": "Modules/DankDash/WeatherTab.qml:354, Modules/Settings/TimeWeatherTab.qml:1181",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Window Scrolling",
|
||||
"context": "Window Scrolling",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:70",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Workspace",
|
||||
"context": "Workspace",
|
||||
@@ -3008,7 +3014,7 @@
|
||||
{
|
||||
"term": "Workspace Padding",
|
||||
"context": "Workspace Padding",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:71",
|
||||
"reference": "Modules/Settings/WidgetTweaksTab.qml:81",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
@@ -3026,25 +3032,25 @@
|
||||
{
|
||||
"term": "You have unsaved changes. Save before closing this tab?",
|
||||
"context": "You have unsaved changes. Save before closing this tab?",
|
||||
"reference": "Modules/Notepad/Notepad.qml:394",
|
||||
"reference": "Modules/Notepad/Notepad.qml:398",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "You have unsaved changes. Save before continuing?",
|
||||
"context": "You have unsaved changes. Save before continuing?",
|
||||
"reference": "Modules/Notepad/Notepad.qml:397",
|
||||
"reference": "Modules/Notepad/Notepad.qml:401",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "You have unsaved changes. Save before creating a new file?",
|
||||
"context": "You have unsaved changes. Save before creating a new file?",
|
||||
"reference": "Modules/Notepad/Notepad.qml:392",
|
||||
"reference": "Modules/Notepad/Notepad.qml:396",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "You have unsaved changes. Save before opening a file?",
|
||||
"context": "You have unsaved changes. Save before opening a file?",
|
||||
"reference": "Modules/Notepad/Notepad.qml:396",
|
||||
"reference": "Modules/Notepad/Notepad.qml:400",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -706,6 +706,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Command or script to run instead of the standard lock procedure",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Command or script to run instead of the standard logout procedure",
|
||||
"translation": "",
|
||||
@@ -1140,6 +1147,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Domain (optional)",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Drag widgets to reorder within sections. Use the eye icon to hide/show widgets (maintains spacing), or X to remove them completely.",
|
||||
"translation": "",
|
||||
@@ -2498,13 +2512,6 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Realm / Domain (optional)",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Reboot",
|
||||
"translation": "",
|
||||
@@ -2729,13 +2736,6 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Server Domain for certificate (optional)",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Set different wallpapers for each connected monitor",
|
||||
"translation": "",
|
||||
@@ -3492,6 +3492,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Window Scrolling",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Workspace",
|
||||
"translation": "",
|
||||
|
||||
Reference in New Issue
Block a user