1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-06 21:45:38 -05:00

meta: integrate wallpaper, FileBrowser, StateLayer

- A lot of this is implements patterns implemented by soramannew's
  caelestia-shell
This commit is contained in:
bbedward
2025-07-23 23:20:11 -04:00
parent a0735db7a4
commit ee2cbd708d
33 changed files with 1494 additions and 915 deletions

View File

@@ -1,5 +1,6 @@
import QtQuick
import QtQuick.Effects
import Quickshell
import qs.Common
import qs.Widgets
@@ -12,11 +13,11 @@ Column {
width: parent.width
spacing: Theme.spacingM
Text {
StyledText {
text: "Profile Image"
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
}
// Profile Image Preview with circular crop
@@ -33,34 +34,32 @@ Column {
width: 54
height: 54
// This rectangle provides the themed ring via its border.
Rectangle {
anchors.fill: parent
radius: width / 2
color: "transparent"
border.color: Theme.primary
border.width: 1 // The ring is 1px thick.
border.width: 1
visible: parent.hasImage
}
// Hidden Image loader. Its only purpose is to load the texture.
Image {
id: avatarImageSource
source: {
if (profileImageInput.text === "")
if (Prefs.profileImage === "")
return "";
if (profileImageInput.text.startsWith("/"))
return "file://" + profileImageInput.text;
if (Prefs.profileImage.startsWith("/"))
return "file://" + Prefs.profileImage;
return profileImageInput.text;
return Prefs.profileImage;
}
smooth: true
asynchronous: true
mipmap: true
cache: true
visible: false // This item is never shown directly.
visible: false
}
MultiEffect {
@@ -92,7 +91,6 @@ Column {
}
// Fallback for when there is no image.
Rectangle {
anchors.fill: parent
radius: width / 2
@@ -108,60 +106,136 @@ Column {
}
// Error icon for when the image fails to load.
DankIcon {
anchors.centerIn: parent
name: "warning"
size: Theme.iconSize + 8
color: Theme.primaryText
visible: profileImageInput.text !== "" && avatarImageSource.status === Image.Error
visible: Prefs.profileImage !== "" && avatarImageSource.status === Image.Error
}
}
// Input field
Column {
width: parent.width - 80 - Theme.spacingM
width: parent.width - 54 - Theme.spacingM
spacing: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
Rectangle {
StyledText {
text: Prefs.profileImage ? Prefs.profileImage.split('/').pop() : "No profile image selected"
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
elide: Text.ElideMiddle
width: parent.width
height: 48
radius: Theme.cornerRadius
color: Theme.surfaceVariant
border.color: profileImageInput.activeFocus ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.3)
border.width: profileImageInput.activeFocus ? 2 : 1
DankTextField {
id: profileImageInput
anchors.fill: parent
textColor: Theme.surfaceText
font.pixelSize: Theme.fontSizeMedium
text: Prefs.profileImage
placeholderText: "Enter image path or URL..."
backgroundColor: "transparent"
normalBorderColor: "transparent"
focusedBorderColor: "transparent"
onEditingFinished: {
Prefs.setProfileImage(text);
}
}
}
Text {
text: "Local filesystem path or URL to an image file."
StyledText {
text: Prefs.profileImage ? Prefs.profileImage : ""
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
wrapMode: Text.WordWrap
elide: Text.ElideMiddle
width: parent.width
visible: Prefs.profileImage !== ""
}
}
}
Row {
width: parent.width
spacing: Theme.spacingS
StyledRect {
width: 100
height: 32
radius: Theme.cornerRadius
color: Theme.primary
Row {
anchors.centerIn: parent
spacing: Theme.spacingXS
DankIcon {
name: "folder_open"
size: Theme.iconSizeSmall
color: Theme.primaryText
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: "Browse..."
color: Theme.primaryText
font.pixelSize: Theme.fontSizeSmall
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
profileBrowserLoader.active = true;
profileBrowser.visible = true;
}
}
}
StyledRect {
width: 80
height: 32
radius: Theme.cornerRadius
color: Theme.surfaceVariant
opacity: Prefs.profileImage !== "" ? 1.0 : 0.5
Row {
anchors.centerIn: parent
spacing: Theme.spacingXS
DankIcon {
name: "clear"
size: Theme.iconSizeSmall
color: Theme.surfaceVariantText
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: "Clear"
color: Theme.surfaceVariantText
font.pixelSize: Theme.fontSizeSmall
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
anchors.fill: parent
enabled: Prefs.profileImage !== ""
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: {
Prefs.setProfileImage("");
}
}
}
}
}
LazyLoader {
id: profileBrowserLoader
active: false
FileBrowser {
id: profileBrowser
browserTitle: "Select Profile Image"
browserIcon: "person"
browserType: "profile"
fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp"]
onFileSelected: (path) => {
Prefs.setProfileImage(path);
visible = false;
}
}
}
property alias profileBrowser: profileBrowserLoader.item
}

View File

@@ -0,0 +1,235 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Effects
import Quickshell
import qs.Common
import qs.Widgets
Column {
id: wallpaperTab
width: parent.width
spacing: Theme.spacingM
// Current Wallpaper Section
Column {
width: parent.width
spacing: Theme.spacingS
StyledText {
text: "Current Wallpaper"
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
}
Row {
width: parent.width
spacing: Theme.spacingM
// Wallpaper Preview
StyledRect {
width: 120
height: 67
radius: Theme.cornerRadius
color: Theme.surfaceVariant
border.color: Theme.outline
border.width: 1
Image {
anchors.fill: parent
anchors.margins: 1
source: Prefs.wallpaperPath ? "file://" + Prefs.wallpaperPath : ""
fillMode: Image.PreserveAspectCrop
visible: Prefs.wallpaperPath !== ""
layer.enabled: true
layer.effect: MultiEffect {
maskEnabled: true
maskSource: mask
maskThresholdMin: 0.5
maskSpreadAtMin: 1.0
}
}
Rectangle {
id: mask
anchors.fill: parent
anchors.margins: 1
radius: Theme.cornerRadius - 1
color: "black"
visible: false
layer.enabled: true
}
DankIcon {
anchors.centerIn: parent
name: "image"
size: Theme.iconSizeLarge
color: Theme.surfaceVariantText
visible: Prefs.wallpaperPath === ""
}
}
Column {
width: parent.width - 120 - Theme.spacingM
spacing: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
StyledText {
text: Prefs.wallpaperPath ? Prefs.wallpaperPath.split('/').pop() : "No wallpaper selected"
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
elide: Text.ElideMiddle
width: parent.width
}
StyledText {
text: Prefs.wallpaperPath ? Prefs.wallpaperPath : ""
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
elide: Text.ElideMiddle
width: parent.width
visible: Prefs.wallpaperPath !== ""
}
}
}
Row {
width: parent.width
spacing: Theme.spacingS
StyledRect {
width: 100
height: 32
radius: Theme.cornerRadius
color: Theme.primary
Row {
anchors.centerIn: parent
spacing: Theme.spacingXS
DankIcon {
name: "folder_open"
size: Theme.iconSizeSmall
color: Theme.primaryText
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: "Browse..."
color: Theme.primaryText
font.pixelSize: Theme.fontSizeSmall
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
wallpaperBrowserLoader.active = true;
wallpaperBrowser.visible = true;
}
}
}
StyledRect {
width: 80
height: 32
radius: Theme.cornerRadius
color: Theme.surfaceVariant
opacity: Prefs.wallpaperPath !== "" ? 1.0 : 0.5
Row {
anchors.centerIn: parent
spacing: Theme.spacingXS
DankIcon {
name: "clear"
size: Theme.iconSizeSmall
color: Theme.surfaceVariantText
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: "Clear"
color: Theme.surfaceVariantText
font.pixelSize: Theme.fontSizeSmall
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
anchors.fill: parent
enabled: Prefs.wallpaperPath !== ""
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: {
Prefs.setWallpaperPath("");
}
}
}
}
}
// Dynamic Theming Section
Column {
width: parent.width
spacing: Theme.spacingS
Row {
width: parent.width
spacing: Theme.spacingM
Column {
width: parent.width - toggle.width - Theme.spacingM
spacing: Theme.spacingXS
StyledText {
text: "Dynamic Theming"
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
}
StyledText {
text: "Automatically extract colors from wallpaper"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
wrapMode: Text.WordWrap
width: parent.width
}
}
DankToggle {
id: toggle
anchors.verticalCenter: parent.verticalCenter
checked: Prefs.wallpaperDynamicTheming
onCheckedChanged: {
if (activeFocus) {
Prefs.setWallpaperDynamicTheming(checked);
}
}
}
}
}
LazyLoader {
id: wallpaperBrowserLoader
active: false
FileBrowser {
id: wallpaperBrowser
browserTitle: "Select Wallpaper"
browserIcon: "wallpaper"
browserType: "wallpaper"
fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp"]
onFileSelected: (path) => {
Prefs.setWallpaperPath(path);
visible = false;
}
}
}
property alias wallpaperBrowser: wallpaperBrowserLoader.item
}