1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-24 21:42:51 -05:00

Merge branch 'master' of github.com:bbedward/DankMaterialShell into wip/plugins

This commit is contained in:
bbedward
2025-10-01 13:38:49 -04:00
48 changed files with 3303 additions and 1057 deletions

53
Common/Facts.qml Normal file
View File

@@ -0,0 +1,53 @@
pragma Singleton
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
Singleton {
id: root
readonly property var facts: [
"A photon takes 100,000 to 200,000 years bouncing through the Sun's dense core, then races to Earth in just 8 minutes 20 seconds.",
"A teaspoon of neutron star matter would weigh a billion metric tons here on Earth.",
"Right now, 100 trillion solar neutrinos are passing through your body every second.",
"The Sun converts 4 million metric tons of matter into pure energy every second—enough to power Earth for 500,000 years.",
"The universe still glows with leftover heat from the Big Bang—just 2.7 degrees above absolute zero.",
"There's a nebula out there that's actually colder than empty space itself.",
"We've detected black holes crashing together by measuring spacetime stretch by less than 1/10,000th the width of a proton.",
"Fast radio bursts can release more energy in 5 milliseconds than our Sun produces in 3 days.",
"Our galaxy might be crawling with billions of rogue planets drifting alone in the dark.",
"Distant galaxies can move away from us faster than light because space itself is stretching.",
"The edge of what we can see is 46.5 billion light-years away, even though the universe is only 13.8 billion years old.",
"The universe is mostly invisible: 5% regular matter, 27% dark matter, 68% dark energy.",
"A day on Venus lasts longer than its entire year around the Sun.",
"On Mercury, the time between sunrises is 176 Earth days long.",
"In about 4.5 billion years, our galaxy will smash into Andromeda.",
"Most of the gold in your jewelry was forged when neutron stars collided somewhere in space.",
"PSR J1748-2446ad, the fastest spinning star, rotates 716 times per second—its equator moves at 24% the speed of light.",
"Cosmic rays create particles that shouldn't make it to Earth's surface, but time dilation lets them sneak through.",
"Jupiter's magnetic field is so huge that if we could see it, it would look bigger than the Moon in our sky.",
"Interstellar space is so empty it's like a cube 32 kilometers wide containing just a single grain of sand.",
"Voyager 1 is 24 billion kilometers away but won't leave the Sun's gravitational influence for another 30,000 years.",
"Counting to a billion at one number per second would take over 31 years.",
"Space is so vast, even speeding at light-speed, you'd never return past the cosmic horizon.",
"Astronauts on the ISS age about 0.01 seconds less each year than people on Earth.",
"Sagittarius B2, a dust cloud near our galaxy's center, contains ethyl formate—the compound that gives raspberries their flavor and rum its smell.",
"Beyond 16 billion light-years, the cosmic event horizon marks where space expands too fast for light to ever reach us again.",
"Even at light-speed, you'd never catch up to most galaxies—space expands faster.",
"Only around 5% of galaxies are ever reachable—even at light-speed.",
"If the Sun vanished, we'd still orbit it for 8 minutes before drifting away.",
"If a planet 65 million light-years away looked at Earth now, it'd see dinosaurs.",
"Our oldest radio signals will reach the Milky Way's center in 26,000 years.",
"Every atom in your body heavier than hydrogen was forged in the nuclear furnace of a dying star.",
"The Moon moves 3.8 centimeters farther from Earth every year.",
"The universe creates 275 million new stars every single day.",
"Jupiter's Great Red Spot is a storm twice the size of Earth that has been raging for at least 350 years.",
"If you watched someone fall into a black hole, they'd appear frozen at the event horizon forever—time effectively stops from your perspective.",
"The Boötes Supervoid is a cosmic desert 1.8 billion light-years across with 60% fewer galaxies than it should have."
]
function getRandomFact() {
return facts[Math.floor(Math.random() * facts.length)]
}
}

View File

@@ -12,6 +12,8 @@ Singleton {
id: root
readonly property bool isGreeterMode: Quickshell.env("DMS_RUN_GREETER") === "1" || Quickshell.env("DMS_RUN_GREETER") === "true"
property bool isLightMode: false
property string wallpaperPath: ""
property string wallpaperLastPath: ""
@@ -71,11 +73,17 @@ Singleton {
Component.onCompleted: {
loadSettings()
if (!isGreeterMode) {
loadSettings()
}
}
function loadSettings() {
parseSettings(settingsFile.text())
if (isGreeterMode) {
parseSettings(greeterSessionFile.text())
} else {
parseSettings(settingsFile.text())
}
}
function parseSettings(content) {
@@ -142,10 +150,11 @@ Singleton {
batterySuspendTimeout = settings.batterySuspendTimeout !== undefined ? settings.batterySuspendTimeout : 0
batteryHibernateTimeout = settings.batteryHibernateTimeout !== undefined ? settings.batteryHibernateTimeout : 0
lockBeforeSuspend = settings.lockBeforeSuspend !== undefined ? settings.lockBeforeSuspend : false
// Generate system themes but don't override user's theme choice
if (typeof Theme !== "undefined") {
Theme.generateSystemThemesFromCurrentTheme()
if (!isGreeterMode) {
if (typeof Theme !== "undefined") {
Theme.generateSystemThemesFromCurrentTheme()
}
}
}
} catch (e) {
@@ -154,6 +163,7 @@ Singleton {
}
function saveSettings() {
if (isGreeterMode) return
settingsFile.setText(JSON.stringify({
"isLightMode": isLightMode,
"wallpaperPath": wallpaperPath,
@@ -620,22 +630,43 @@ Singleton {
FileView {
id: settingsFile
path: StandardPaths.writableLocation(StandardPaths.GenericStateLocation) + "/DankMaterialShell/session.json"
blockLoading: true
path: isGreeterMode ? "" : StandardPaths.writableLocation(StandardPaths.GenericStateLocation) + "/DankMaterialShell/session.json"
blockLoading: isGreeterMode
blockWrites: true
watchChanges: true
watchChanges: !isGreeterMode
onLoaded: {
parseSettings(settingsFile.text())
hasTriedDefaultSession = false
if (!isGreeterMode) {
parseSettings(settingsFile.text())
hasTriedDefaultSession = false
}
}
onLoadFailed: error => {
if (!hasTriedDefaultSession) {
hasTriedDefaultSession = true
if (!isGreeterMode && !hasTriedDefaultSettings) {
hasTriedDefaultSettings = true
defaultSessionCheckProcess.running = true
}
}
}
FileView {
id: greeterSessionFile
path: {
const greetCfgDir = Quickshell.env("DMS_GREET_CFG_DIR") || "/etc/greetd/.dms"
return greetCfgDir + "/session.json"
}
preload: isGreeterMode
blockLoading: false
blockWrites: true
watchChanges: false
printErrors: true
onLoaded: {
if (isGreeterMode) {
parseSettings(greeterSessionFile.text())
}
}
}
Process {
id: defaultSessionCheckProcess

View File

@@ -12,6 +12,8 @@ import qs.Services
Singleton {
id: root
readonly property bool isGreeterMode: Quickshell.env("DMS_RUN_GREETER") === "1" || Quickshell.env("DMS_RUN_GREETER") === "true"
enum Position {
Top,
Bottom,
@@ -19,6 +21,14 @@ Singleton {
Right
}
enum AnimationSpeed {
None,
Shortest,
Short,
Medium,
Long
}
// Theme settings
property string currentThemeName: "blue"
property string customThemeFile: ""
@@ -151,6 +161,7 @@ Singleton {
property int notificationTimeoutCritical: 0
property int notificationPopupPosition: SettingsData.Position.Top
property var screenPreferences: ({})
property int animationSpeed: SettingsData.AnimationSpeed.Short
readonly property string defaultFontFamily: "Inter Variable"
readonly property string defaultMonoFontFamily: "Fira Code"
readonly property string _homeUrl: StandardPaths.writableLocation(StandardPaths.HomeLocation)
@@ -353,6 +364,7 @@ Singleton {
surfaceBase = settings.surfaceBase !== undefined ? settings.surfaceBase : "s"
screenPreferences = settings.screenPreferences !== undefined ? settings.screenPreferences : ({})
pluginSettings = settings.pluginSettings !== undefined ? settings.pluginSettings : ({})
animationSpeed = settings.animationSpeed !== undefined ? settings.animationSpeed : SettingsData.AnimationSpeed.Short
applyStoredTheme()
detectAvailableIconThemes()
detectQtTools()
@@ -472,7 +484,8 @@ Singleton {
"notificationTimeoutCritical": notificationTimeoutCritical,
"notificationPopupPosition": notificationPopupPosition,
"screenPreferences": screenPreferences,
"pluginSettings": pluginSettings
"pluginSettings": pluginSettings,
"animationSpeed": animationSpeed
}, null, 2))
}
@@ -984,13 +997,23 @@ Singleton {
function setShowDock(enabled) {
showDock = enabled
if (enabled && dankBarPosition === SettingsData.Position.Top) {
setDockPosition(SettingsData.Position.Bottom)
return
}
if (enabled && dankBarPosition === SettingsData.Position.Top) {
setDockPosition(SettingsData.Position.Bottom)
return
if (enabled && dockPosition === dankBarPosition) {
if (dankBarPosition === SettingsData.Position.Top) {
setDockPosition(SettingsData.Position.Bottom)
return
}
if (dankBarPosition === SettingsData.Position.Bottom) {
setDockPosition(SettingsData.Position.Top)
return
}
if (dankBarPosition === SettingsData.Position.Left) {
setDockPosition(SettingsData.Position.Right)
return
}
if (dankBarPosition === SettingsData.Position.Right) {
setDockPosition(SettingsData.Position.Left)
return
}
}
saveSettings()
}
@@ -1137,14 +1160,22 @@ Singleton {
function setDankBarPosition(position) {
dankBarPosition = position
if (position === SettingsData.Position.Bottom && showDock) {
if (position === SettingsData.Position.Bottom && dockPosition === SettingsData.Position.Bottom && showDock) {
setDockPosition(SettingsData.Position.Top)
return
}
if (position === SettingsData.Position.Top && showDock) {
if (position === SettingsData.Position.Top && dockPosition === SettingsData.Position.Top && showDock) {
setDockPosition(SettingsData.Position.Bottom)
return
}
if (position === SettingsData.Position.Left && dockPosition === SettingsData.Position.Left && showDock) {
setDockPosition(SettingsData.Position.Right)
return
}
if (position === SettingsData.Position.Right && dockPosition === SettingsData.Position.Right && showDock) {
setDockPosition(SettingsData.Position.Left)
return
}
saveSettings()
}
@@ -1156,6 +1187,12 @@ Singleton {
if (position === SettingsData.Position.Top && dankBarPosition === SettingsData.Position.Top && showDock) {
setDankBarPosition(SettingsData.Position.Bottom)
}
if (position === SettingsData.Position.Left && dankBarPosition === SettingsData.Position.Left && showDock) {
setDankBarPosition(SettingsData.Position.Right)
}
if (position === SettingsData.Position.Right && dankBarPosition === SettingsData.Position.Right && showDock) {
setDankBarPosition(SettingsData.Position.Left)
}
saveSettings()
Qt.callLater(() => forceDockLayoutRefresh())
}
@@ -1260,14 +1297,21 @@ Singleton {
return pluginSettings[pluginId] || {}
}
function setAnimationSpeed(speed) {
animationSpeed = speed
saveSettings()
}
function _shq(s) {
return "'" + String(s).replace(/'/g, "'\\''") + "'"
}
Component.onCompleted: {
loadSettings()
fontCheckTimer.start()
initializeListModels()
if (!isGreeterMode) {
loadSettings()
fontCheckTimer.start()
initializeListModels()
}
}
ListModel {
@@ -1308,20 +1352,22 @@ Singleton {
FileView {
id: settingsFile
path: StandardPaths.writableLocation(StandardPaths.ConfigLocation) + "/DankMaterialShell/settings.json"
blockLoading: true
path: isGreeterMode ? "" : StandardPaths.writableLocation(StandardPaths.ConfigLocation) + "/DankMaterialShell/settings.json"
blockLoading: isGreeterMode
blockWrites: true
atomicWrites: true
watchChanges: true
watchChanges: !isGreeterMode
onLoaded: {
parseSettings(settingsFile.text())
hasTriedDefaultSettings = false
if (!isGreeterMode) {
parseSettings(settingsFile.text())
hasTriedDefaultSettings = false
}
}
onLoadFailed: error => {
if (!hasTriedDefaultSettings) {
if (!isGreeterMode && !hasTriedDefaultSettings) {
hasTriedDefaultSettings = true
defaultSettingsCheckProcess.running = true
} else {
} else if (!isGreeterMode) {
applyStoredTheme()
}
}

View File

@@ -31,9 +31,8 @@ Singleton {
readonly property string shellDir: Paths.strip(Qt.resolvedUrl(".").toString()).replace("/Common/", "")
readonly property string wallpaperPath: {
if (typeof SessionData === "undefined") return ""
if (SessionData.perMonitorWallpaper) {
// Use first monitor's wallpaper for dynamic theming
var screens = Quickshell.screens
if (screens.length > 0) {
var firstMonitorWallpaper = SessionData.getMonitorWallpaper(screens[0].name)
@@ -93,6 +92,13 @@ Singleton {
}
}
function applyGreeterTheme(themeName) {
switchTheme(themeName, false, false)
if (themeName === dynamic && dynamicColorsFileView.path) {
dynamicColorsFileView.reload()
}
}
function getMatugenColor(path, fallback) {
colorUpdateTrigger
const colorMode = (typeof SessionData !== "undefined" && SessionData.isLightMode) ? "light" : "dark"
@@ -235,11 +241,22 @@ Singleton {
property color shadowMedium: Qt.rgba(0, 0, 0, 0.08)
property color shadowStrong: Qt.rgba(0, 0, 0, 0.3)
property int shorterDuration: 100
property int shortDuration: 150
property int mediumDuration: 300
property int longDuration: 500
property int extraLongDuration: 1000
readonly property var animationDurations: [
{ shorter: 0, short: 0, medium: 0, long: 0, extraLong: 0 },
{ shorter: 50, short: 75, medium: 150, long: 250, extraLong: 500 },
{ shorter: 100, short: 150, medium: 300, long: 500, extraLong: 1000 },
{ shorter: 150, short: 225, medium: 450, long: 750, extraLong: 1500 },
{ shorter: 200, short: 300, medium: 600, long: 1000, extraLong: 2000 }
]
readonly property int currentAnimationSpeed: typeof SettingsData !== "undefined" ? SettingsData.animationSpeed : SettingsData.AnimationSpeed.Short
readonly property var currentDurations: animationDurations[currentAnimationSpeed] || animationDurations[SettingsData.AnimationSpeed.Short]
property int shorterDuration: currentDurations.shorter
property int shortDuration: currentDurations.short
property int mediumDuration: currentDurations.medium
property int longDuration: currentDurations.long
property int extraLongDuration: currentDurations.extraLong
property int standardEasing: Easing.OutCubic
property int emphasizedEasing: Easing.OutQuart
@@ -292,10 +309,13 @@ Singleton {
currentThemeCategory = "generic"
}
}
if (savePrefs && typeof SettingsData !== "undefined")
const isGreeterMode = (typeof SessionData !== "undefined" && SessionData.isGreeterMode)
if (savePrefs && typeof SettingsData !== "undefined" && !isGreeterMode)
SettingsData.setTheme(currentTheme)
generateSystemThemesFromCurrentTheme()
if (!isGreeterMode) {
generateSystemThemesFromCurrentTheme()
}
}
function setLightMode(light, savePrefs = true, enableTransition = false) {
@@ -307,11 +327,14 @@ Singleton {
return
}
const isGreeterMode = (typeof SessionData !== "undefined" && SessionData.isGreeterMode)
isLightMode = light
if (savePrefs && typeof SessionData !== "undefined")
if (savePrefs && typeof SessionData !== "undefined" && !isGreeterMode)
SessionData.setLightMode(isLightMode)
PortalService.setLightMode(isLightMode)
generateSystemThemesFromCurrentTheme()
if (!isGreeterMode) {
PortalService.setLightMode(isLightMode)
generateSystemThemesFromCurrentTheme()
}
}
function toggleLightMode(savePrefs = true) {
@@ -588,7 +611,8 @@ Singleton {
}
function generateSystemThemesFromCurrentTheme() {
if (!matugenAvailable)
const isGreeterMode = (typeof SessionData !== "undefined" && SessionData.isGreeterMode)
if (!matugenAvailable || isGreeterMode)
return
const isLight = (typeof SessionData !== "undefined" && SessionData.isLightMode)
@@ -659,8 +683,9 @@ Singleton {
command: ["which", "matugen"]
onExited: code => {
matugenAvailable = (code === 0) && !envDisableMatugen
if (!matugenAvailable) {
console.log("matugen not not available in path or disabled via DMS_DISABLE_MATUGEN")
const isGreeterMode = (typeof SessionData !== "undefined" && SessionData.isGreeterMode)
if (!matugenAvailable || isGreeterMode) {
return
}
@@ -711,10 +736,7 @@ Singleton {
onExited: exitCode => {
workerRunning = false
if (exitCode === 2) {
// Exit code 2 means wallpaper/color not found - this is expected on first run
console.log("Theme worker: wallpaper/color not found, skipping theme generation")
} else if (exitCode !== 0) {
if (exitCode !== 0 && exitCode !== 2) {
if (typeof ToastService !== "undefined") {
ToastService.showError("Theme worker failed (" + exitCode + ")")
}
@@ -803,8 +825,14 @@ Singleton {
FileView {
id: dynamicColorsFileView
path: stateDir + "/dms-colors.json"
watchChanges: currentTheme === dynamic
path: {
const greetCfgDir = Quickshell.env("DMS_GREET_CFG_DIR") || "/etc/greetd/.dms"
const colorsPath = SessionData.isGreeterMode
? greetCfgDir + "/colors.json"
: stateDir + "/dms-colors.json"
return colorsPath
}
watchChanges: currentTheme === dynamic && !SessionData.isGreeterMode
function parseAndLoadColors() {
try {
@@ -817,6 +845,7 @@ Singleton {
}
}
} catch (e) {
console.error("Theme: Failed to parse dynamic colors:", e)
if (typeof ToastService !== "undefined") {
ToastService.wallpaperErrorStatus = "error"
ToastService.showError("Dynamic colors parse error: " + e.message)