diff --git a/.config/quickshell/modules/common/Appearance.qml b/.config/quickshell/modules/common/Appearance.qml index 694c3af8e..b496f4d17 100644 --- a/.config/quickshell/modules/common/Appearance.qml +++ b/.config/quickshell/modules/common/Appearance.qml @@ -107,7 +107,7 @@ Singleton { property color colLayer1: ColorUtils.transparentize(ColorUtils.mix(m3colors.m3surfaceContainerLow, m3colors.m3background, 0.8), root.contentTransparency); property color colOnLayer1: m3colors.m3onSurfaceVariant; property color colOnLayer1Inactive: ColorUtils.mix(colOnLayer1, colLayer1, 0.45); - property color colLayer2: ColorUtils.transparentize(ColorUtils.mix(m3colors.m3surfaceContainer, m3colors.m3surfaceContainerHigh, 0.7), root.contentTransparency) + property color colLayer2: ColorUtils.transparentize(ColorUtils.mix(m3colors.m3surfaceContainer, m3colors.m3surfaceContainerHigh, 0.1), root.contentTransparency) property color colOnLayer2: m3colors.m3onSurface; property color colOnLayer2Disabled: ColorUtils.mix(colOnLayer2, m3colors.m3background, 0.4); property color colLayer3: ColorUtils.transparentize(ColorUtils.mix(m3colors.m3surfaceContainerHigh, m3colors.m3onSurface, 0.96), root.contentTransparency) diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml index 92d56b72c..c268f1d95 100644 --- a/.config/quickshell/modules/common/ConfigOptions.qml +++ b/.config/quickshell/modules/common/ConfigOptions.qml @@ -155,6 +155,10 @@ Singleton { property string dateFormat: "dddd, dd/MM" } + property QtObject windows: QtObject { + property bool showTitlebar: true // Client-side decoration for shell apps + } + property QtObject hacks: QtObject { property int arbitraryRaceConditionDelay: 20 // milliseconds } diff --git a/.config/quickshell/modules/common/widgets/GroupButton.qml b/.config/quickshell/modules/common/widgets/GroupButton.qml index bfa887b68..362ae39e9 100644 --- a/.config/quickshell/modules/common/widgets/GroupButton.qml +++ b/.config/quickshell/modules/common/widgets/GroupButton.qml @@ -16,8 +16,8 @@ Button { id: root property bool toggled property string buttonText - property real buttonRadius: Appearance?.rounding?.small ?? 4 - property real buttonRadiusPressed: buttonRadius + property real buttonRadius: Appearance?.rounding?.small ?? 8 + property real buttonRadiusPressed: Appearance?.rounding?.small ?? 6 property var downAction // When left clicking (down) property var releaseAction // When left clicking (release) property var altAction // When right clicking @@ -34,18 +34,6 @@ Button { Layout.fillHeight: (clickIndex - 1 <= parentGroup.children.indexOf(root) && parentGroup.children.indexOf(root) <= clickIndex + 1) implicitWidth: (root.down && bounce) ? clickedWidth : baseWidth implicitHeight: (root.down && bounce) ? clickedHeight : baseHeight - - Behavior on implicitWidth { - animation: Appearance.animation.clickBounce.numberAnimation.createObject(this) - } - - Behavior on implicitHeight { - animation: Appearance.animation.clickBounce.numberAnimation.createObject(this) - } - - Behavior on radius { - animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) - } property color colBackground: ColorUtils.transparentize(Appearance?.colors.colLayer1Hover, 1) || "transparent" property color colBackgroundHover: Appearance?.colors.colLayer1Hover ?? "#E5DFED" @@ -55,6 +43,8 @@ Button { property color colBackgroundToggledActive: Appearance?.colors.colPrimaryActive ?? "#D6CEE2" property real radius: root.down ? root.buttonRadiusPressed : root.buttonRadius + property real leftRadius: root.down ? root.buttonRadiusPressed : root.buttonRadius + property real rightRadius: root.down ? root.buttonRadiusPressed : root.buttonRadius property color color: root.enabled ? (root.toggled ? (root.down ? colBackgroundToggledActive : root.hovered ? colBackgroundToggledHover : @@ -71,6 +61,21 @@ Button { } } + Behavior on implicitWidth { + animation: Appearance.animation.clickBounce.numberAnimation.createObject(this) + } + + Behavior on implicitHeight { + animation: Appearance.animation.clickBounce.numberAnimation.createObject(this) + } + + Behavior on leftRadius { + animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) + } + Behavior on rightRadius { + animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) + } + MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor @@ -100,7 +105,10 @@ Button { background: Rectangle { id: buttonBackground - radius: root.radius + topLeftRadius: root.leftRadius + topRightRadius: root.rightRadius + bottomLeftRadius: root.leftRadius + bottomRightRadius: root.rightRadius implicitHeight: 50 color: root.color diff --git a/.config/quickshell/scripts/colors/random_konachan_wall.sh b/.config/quickshell/scripts/colors/random_konachan_wall.sh new file mode 100755 index 000000000..52853d090 --- /dev/null +++ b/.config/quickshell/scripts/colors/random_konachan_wall.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +mkdir -p ~/Pictures/Wallpapers +page=$((1 + RANDOM % 1000)); +response=$(curl "https://konachan.com/post.json?tags=rating%3Asafe&limit=1&page=$page") +link=$(echo "$response" | jq '.[0].file_url' -r); +ext=$(echo "$link" | awk -F. '{print $NF}') +downloadPath="$HOME/Pictures/Wallpapers/konachan_random_image.$ext" +curl "$link" -o "$downloadPath" +~/.config/quickshell/scripts/colors/switchwall.sh --image "$downloadPath" diff --git a/.config/quickshell/scripts/colors/switchwall.sh b/.config/quickshell/scripts/colors/switchwall.sh index 4136772f2..0a633e242 100755 --- a/.config/quickshell/scripts/colors/switchwall.sh +++ b/.config/quickshell/scripts/colors/switchwall.sh @@ -291,6 +291,10 @@ main() { shift fi ;; + --image) + imgpath="$2" + shift 2 + ;; --noswitch) noswitch_flag="1" imgpath=$(swww query | awk -F 'image: ' '{print $2}') diff --git a/.config/quickshell/services/FirstRunExperience.qml b/.config/quickshell/services/FirstRunExperience.qml index e28d4b49b..86ccb98b8 100644 --- a/.config/quickshell/services/FirstRunExperience.qml +++ b/.config/quickshell/services/FirstRunExperience.qml @@ -27,7 +27,7 @@ Singleton { } function handleFirstRun() { - Hyprland.dispatch(`exec '${Directories.wallpaperSwitchScriptPath}' '${root.defaultWallpaperPath}'`) + Hyprland.dispatch(`exec swww query | grep 'image' || '${Directories.wallpaperSwitchScriptPath}' '${root.defaultWallpaperPath}'`) Hyprland.dispatch(`exec qs -p '${root.welcomeQmlPath}'`) } diff --git a/.config/quickshell/services/Notifications.qml b/.config/quickshell/services/Notifications.qml index 75033292c..dc2d2206d 100644 --- a/.config/quickshell/services/Notifications.qml +++ b/.config/quickshell/services/Notifications.qml @@ -217,8 +217,10 @@ Singleton { const action = notifServerNotif.actions.find((action) => action.identifier === notifIdentifier); action.invoke() } - // else console.log("Notification not found in server: " + id) - // root.discard(id); + else { + console.log("Notification not found in server: " + id) + root.discardNotification(id); + } } function triggerListChange() { diff --git a/.config/quickshell/welcome.qml b/.config/quickshell/welcome.qml index dc8559dfd..cbc5b4a32 100644 --- a/.config/quickshell/welcome.qml +++ b/.config/quickshell/welcome.qml @@ -11,6 +11,7 @@ import QtQuick.Controls import QtQuick.Layouts import QtQuick.Window import Quickshell +import Quickshell.Io import Quickshell.Hyprland import "root:/services/" import "root:/modules/common/" @@ -25,7 +26,6 @@ ApplicationWindow { property string firstRunFileContent: "This file is just here to confirm you've been greeted :>" property real contentPadding: 5 property bool showNextTime: false - visible: true onClosing: Qt.quit() title: "illogical-impulse Welcome" @@ -38,16 +38,44 @@ ApplicationWindow { minimumWidth: 600 minimumHeight: 400 width: 800 - height: 600 + height: 650 color: Appearance.m3colors.m3background + Process { + id: konachanWallProc + property string status: "" + command: ["bash", "-c", FileUtils.trimFileProtocol(`${Directories.config}/quickshell/scripts/colors/random_konachan_wall.sh`)] + stdout: SplitParser { + onRead: data => { + console.log(`Konachan wall proc output: ${data}`); + konachanWallProc.status = data.trim(); + } + } + } + + component SelectionConnectedButton: GroupButton { + id: selectionConnectedButtonRoot + horizontalPadding: 12 + verticalPadding: 8 + bounce: false + property bool leftmost: false + property bool rightmost: false + leftRadius: (toggled || leftmost) ? (height / 2) : Appearance.rounding.unsharpenmore + rightRadius: (toggled || rightmost) ? (height / 2) : Appearance.rounding.unsharpenmore + colBackground: Appearance.colors.colSecondaryContainer + contentItem: StyledText { + color: parent.toggled ? Appearance.colors.colOnPrimary : Appearance.colors.colOnSecondaryContainer + text: selectionConnectedButtonRoot.buttonText + } + } + component Section: ColumnLayout { id: sectionRoot property string title default property alias data: sectionContent.data Layout.fillWidth: true - spacing: 10 + spacing: 8 StyledText { text: sectionRoot.title font.pixelSize: Appearance.font.pixelSize.larger @@ -58,6 +86,56 @@ ApplicationWindow { } } + component ButtonWithIcon: RippleButton { + id: buttonWithIconRoot + property string nerdIcon + property string iconText + property string mainText: "Button text" + property Component mainContentComponent: Component { + StyledText { + text: buttonWithIconRoot.mainText + font.pixelSize: Appearance.font.pixelSize.small + color: Appearance.colors.colOnSecondaryContainer + } + } + implicitHeight: 35 + horizontalPadding: 15 + buttonRadius: Appearance.rounding.small + colBackground: Appearance.colors.colLayer2 + + contentItem: RowLayout { + Item { + implicitWidth: Math.max(materialIconLoader.implicitWidth, nerdIconLoader.implicitWidth) + Loader { + id: materialIconLoader + anchors.centerIn: parent + active: !nerdIcon + sourceComponent: MaterialSymbol { + text: buttonWithIconRoot.iconText + iconSize: Appearance.font.pixelSize.larger + color: Appearance.colors.colOnSecondaryContainer + fill: 1 + } + } + Loader { + id: nerdIconLoader + anchors.centerIn: parent + active: nerdIcon + sourceComponent: StyledText { + text: buttonWithIconRoot.nerdIcon + font.pixelSize: Appearance.font.pixelSize.larger + font.family: Appearance.font.family.iconNerd + color: Appearance.colors.colOnSecondaryContainer + } + } + } + Loader { + sourceComponent: buttonWithIconRoot.mainContentComponent + Layout.alignment: Qt.AlignVCenter + } + } + } + component LightDarkPrefButton: GroupButton { id: lightDarkButtonRoot required property bool dark @@ -178,14 +256,16 @@ ApplicationWindow { fill: parent margins: contentPadding } + Item { + visible: ConfigOptions?.windows.showTitlebar Layout.fillWidth: true implicitHeight: Math.max(welcomeText.implicitHeight, windowControlsRow.implicitHeight) StyledText { id: welcomeText anchors.centerIn: parent color: Appearance.colors.colOnLayer0 - text: "Welcome" + text: "Yooooo hi there" font.pixelSize: Appearance.font.pixelSize.hugeass font.family: Appearance.font.family.title } @@ -232,69 +312,256 @@ ApplicationWindow { Layout.fillWidth: true Layout.fillHeight: true radius: Appearance.rounding.windowRounding - root.contentPadding - ColumnLayout { - id: contentColumn - anchors { - top: parent.top - bottom: parent.bottom - horizontalCenter: parent.horizontalCenter - margins: 10 - } - spacing: 20 + Flickable { + clip: true + anchors.fill: parent + contentHeight: contentColumn.implicitHeight + implicitWidth: contentColumn.implicitWidth + ColumnLayout { + id: contentColumn + anchors { + top: parent.top + bottom: parent.bottom + horizontalCenter: parent.horizontalCenter + margins: 10 + } + spacing: 20 - Section { - title: "Customize" + Section { + title: "Style & wallpaper" - ButtonGroup { + ButtonGroup { + Layout.fillWidth: true + LightDarkPrefButton { + dark: false + } + LightDarkPrefButton { + dark: true + } + } + + RowLayout { + Layout.alignment: Qt.AlignHCenter + ButtonWithIcon { + id: rndWallBtn + Layout.alignment: Qt.AlignHCenter + buttonRadius: Appearance.rounding.small + iconText: "wallpaper" + mainText: konachanWallProc.running ? "Be patient..." : "Random: Konachan" + onClicked: { + console.log(konachanWallProc.command.join(" ")) + konachanWallProc.running = true; + } + } + ButtonWithIcon { + iconText: "wallpaper" + onClicked: { + Hyprland.dispatch(`exec ${Directories.wallpaperSwitchScriptPath}`) + } + mainContentComponent: Component { + RowLayout { + spacing: 10 + StyledText { + font.pixelSize: Appearance.font.pixelSize.small + text: "Choose file" + color: Appearance.colors.colOnSecondaryContainer + } + RowLayout { + spacing: 3 + KeyboardKey { + key: "Ctrl" + } + KeyboardKey { + key: "󰖳" + } + StyledText { + Layout.alignment: Qt.AlignVCenter + text: "+" + } + KeyboardKey { + key: "T" + } + } + } + } + } + } + + StyledText { + Layout.alignment: Qt.AlignHCenter + text: "Change any time later with /dark, /light, /img in the launcher" + font.pixelSize: Appearance.font.pixelSize.smaller + color: Appearance.colors.colSubtext + } + } + + Section { + title: "Policies" + + RowLayout { + Layout.alignment: Qt.AlignHCenter + spacing: 15 + ColumnLayout { // Weeb policy + StyledText { + text: "Weeb" + color: Appearance.colors.colSubtext + } + ButtonGroup { + id: weebPolicyBtnGroup + property int selectedPolicy: ConfigOptions.policies.weeb + spacing: 2 + SelectionConnectedButton { + property int value: 0 + leftmost: true + buttonText: "No" + toggled: (weebPolicyBtnGroup.selectedPolicy === value) + onClicked: { + ConfigLoader.setConfigValueAndSave("policies.weeb", value); + } + } + SelectionConnectedButton { + property int value: 1 + buttonText: "Yes" + toggled: (weebPolicyBtnGroup.selectedPolicy === value) + onClicked: { + ConfigLoader.setConfigValueAndSave("policies.weeb", value); + } + } + SelectionConnectedButton { + property int value: 2 + rightmost: true + buttonText: "Closet" + toggled: (weebPolicyBtnGroup.selectedPolicy === value) + onClicked: { + ConfigLoader.setConfigValueAndSave("policies.weeb", value); + } + } + } + } + ColumnLayout { // AI policy + StyledText { + text: "AI" + color: Appearance.colors.colSubtext + } + ButtonGroup { + id: aiPolicyBtnGroup + property int selectedPolicy: ConfigOptions.policies.ai + spacing: 2 + SelectionConnectedButton { + property int value: 0 + leftmost: true + buttonText: "No" + toggled: (aiPolicyBtnGroup.selectedPolicy === value) + onClicked: { + ConfigLoader.setConfigValueAndSave("policies.ai", value); + } + } + SelectionConnectedButton { + property int value: 1 + buttonText: "Yes" + toggled: (aiPolicyBtnGroup.selectedPolicy === value) + onClicked: { + ConfigLoader.setConfigValueAndSave("policies.ai", value); + } + } + SelectionConnectedButton { + property int value: 2 + rightmost: true + buttonText: "Local only" + toggled: (aiPolicyBtnGroup.selectedPolicy === value) + onClicked: { + ConfigLoader.setConfigValueAndSave("policies.ai", value); + } + } + } + } + } + } + + Section { + title: "Info" + + Flow { + Layout.fillWidth: true + spacing: 10 + + ButtonWithIcon { + iconText: "keyboard_alt" + onClicked: { + Hyprland.dispatch("global quickshell:cheatsheetOpen") + } + mainContentComponent: Component { + RowLayout { + spacing: 10 + StyledText { + font.pixelSize: Appearance.font.pixelSize.small + text: "Keybinds" + color: Appearance.colors.colOnSecondaryContainer + } + RowLayout { + spacing: 3 + KeyboardKey { + key: "󰖳" + } + StyledText { + Layout.alignment: Qt.AlignVCenter + text: "+" + } + KeyboardKey { + key: "/" + } + } + } + } + } + + ButtonWithIcon { + iconText: "help" + mainText: "Usage" + onClicked: { + Qt.openUrlExternally("https://end-4.github.io/dots-hyprland-wiki/en/ii-qs/02usage/") + } + } + ButtonWithIcon { + iconText: "construction" + mainText: "Configuration" + onClicked: { + Qt.openUrlExternally("https://end-4.github.io/dots-hyprland-wiki/en/ii-qs/03config/") + } + } + } + } + + Section { + title: "Useless buttons" + + Flow { + Layout.fillWidth: true + spacing: 10 + + ButtonWithIcon { + nerdIcon: "󰊤" + mainText: "GitHub" + onClicked: { + Qt.openUrlExternally("https://github.com/end-4/dots-hyprland") + } + } + ButtonWithIcon { + iconText: "favorite" + mainText: "Funny number" + onClicked: { + Qt.openUrlExternally("https://github.com/sponsors/end-4") + } + } + } + } + + Item { Layout.fillWidth: true - LightDarkPrefButton { - dark: false - } - LightDarkPrefButton { - dark: true - } + Layout.fillHeight: true } + } - - Section { - title: "Info" - - RippleButton { - implicitHeight: 35 - horizontalPadding: 10 - // buttonRadius: Appearance.rounding.full - colBackground: Appearance.colors.colSecondaryContainer - colBackgroundHover: Appearance.colors.colSecondaryContainerHover - colRipple: Appearance.colors.colSecondaryContainerActive - - onClicked: { - Hyprland.dispatch("global quickshell:cheatsheetOpen") - } - - contentItem: RowLayout { - KeyboardKey { - key: "󰖳" - } - StyledText { - Layout.alignment: Qt.AlignVCenter - text: "+" - } - KeyboardKey { - key: "/" - } - StyledText { - text: "Open keybind cheatsheet" - color: Appearance.colors.colOnSecondaryContainer - } - } - } - } - - Item { - Layout.fillWidth: true - Layout.fillHeight: true - } - } } } diff --git a/README.md b/README.md index d65c5ce9d..e381b1251 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,13 @@ - For a more comprehensive list of dependencies, see [scriptdata/dependencies.conf](https://github.com/end-4/dots-hyprland/blob/main/scriptdata/dependencies.conf) +
+ Logo ideas welcome + + - See [#1436](https://github.com/end-4/dots-hyprland/issues/1436) + +
+

• screenshots •

diff --git a/arch-packages/illogical-impulse-fonts-themes/PKGBUILD b/arch-packages/illogical-impulse-fonts-themes/PKGBUILD index ed1a95070..12a7209be 100644 --- a/arch-packages/illogical-impulse-fonts-themes/PKGBUILD +++ b/arch-packages/illogical-impulse-fonts-themes/PKGBUILD @@ -14,9 +14,10 @@ depends=( kitty matugen-bin starship - ttf-readex-pro + ttf-gabarito-git ttf-jetbrains-mono-nerd ttf-material-symbols-variable-git + ttf-readex-pro ttf-rubik-vf - ttf-gabarito-git + ttf-twemoji )