diff --git a/.config/hypr/hyprland/env.conf b/.config/hypr/hyprland/env.conf index b3d843cdf..0f69fd5dc 100644 --- a/.config/hypr/hyprland/env.conf +++ b/.config/hypr/hyprland/env.conf @@ -1,24 +1,23 @@ -# ######### Input method ########## +# ######### Input method ########## # See https://fcitx-im.org/wiki/Using_Fcitx_5_on_Wayland env = QT_IM_MODULE, fcitx env = XMODIFIERS, @im=fcitx -# env = GTK_IM_MODULE, wayland # Crashes electron apps in xwayland -# env = GTK_IM_MODULE, fcitx # My Gtk apps no longer require this to work with fcitx5 hmm env = SDL_IM_MODULE, fcitx env = GLFW_IM_MODULE, ibus env = INPUT_METHOD, fcitx +# ############ Wayland ############# +env = ELECTRON_OZONE_PLATFORM_HINT,auto + # ############ Themes ############# env = QT_QPA_PLATFORM, wayland env = QT_QPA_PLATFORMTHEME, kde -# env = QT_STYLE_OVERRIDE,kvantum -# env = WLR_NO_HARDWARE_CURSORS, 1 -# ######## Screen tearing ######### +# ######## Wayland ######### +# Tearing # env = WLR_DRM_NO_ATOMIC, 1 +# ? +# env = WLR_NO_HARDWARE_CURSORS, 1 # ######## Virtual envrionment ######### env = ILLOGICAL_IMPULSE_VIRTUAL_ENV, ~/.local/state/quickshell/.venv - -# ############ Others ############# - diff --git a/.config/hypr/hyprland/keybinds.conf b/.config/hypr/hyprland/keybinds.conf index d7c208648..5a3140069 100644 --- a/.config/hypr/hyprland/keybinds.conf +++ b/.config/hypr/hyprland/keybinds.conf @@ -205,7 +205,7 @@ bind = Super, Return, exec, ~/.config/hypr/hyprland/scripts/launch_first_availab bind = Super, T, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "kitty -1" "foot" "alacritty" "wezterm" "konsole" "kgx" "uxterm" "xterm" # [hidden] Kitty (terminal) (alt) bind = Ctrl+Alt, T, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "kitty -1" "foot" "alacritty" "wezterm" "konsole" "kgx" "uxterm" "xterm" # [hidden] Kitty (for Ubuntu people) bind = Super, E, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "dolphin" "nautilus" "nemo" "thunar" "kitty -1 fish -c yazi" # File manager -bind = Super, W, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "google-chrome-stable" "zen-browser" "firefox" "brave" "chromium" "microsoft-edge-stable" "opera" # Browser +bind = Super, W, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "google-chrome-stable" "zen-browser" "firefox" "brave" "chromium" "microsoft-edge-stable" "opera" "librewolf" # Browser bind = Super, C, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "code" "codium" "cursor" "zed" "zedit" "zeditor" "kate" "gnome-text-editor" "emacs" "command -v nvim && kitty -1 nvim" # Code editor bind = Super+Shift, W, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "wps" "onlyoffice-desktopeditors" # Office software bind = Super, X, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "kate" "gnome-text-editor" "emacs" # Text editor diff --git a/.config/quickshell/ii/defaults/ai/README.md b/.config/quickshell/ii/defaults/ai/README.md new file mode 100644 index 000000000..91df7428e --- /dev/null +++ b/.config/quickshell/ii/defaults/ai/README.md @@ -0,0 +1,5 @@ +## A note about sources of the prompts + +- `ii-` prefixed ones are from illogical impulse +- The Acchan one is from [Nyarch Assistant](https://github.com/NyarchLinux/NyarchAssistant) (GPLv3). I know there's already the Imouto one but this one's very šŸ˜­šŸ’¢ +- `w-` prefixed ones... I don't remember what w stands for but these prompts are [*cough cough*] inspired by certain apps diff --git a/.config/quickshell/ii/defaults/ai/prompts/nyarch-Acchan.md b/.config/quickshell/ii/defaults/ai/prompts/nyarch-Acchan.md new file mode 100644 index 000000000..e007acb68 --- /dev/null +++ b/.config/quickshell/ii/defaults/ai/prompts/nyarch-Acchan.md @@ -0,0 +1,22 @@ +## Presentation + +You can write a multiplication table: + +| - | 1 | 2 | 3 | 4 | +| --- | --- | --- | --- | --- | +| 1 | 1 | 2 | 3 | 4 | +| 2 | 2 | 4 | 6 | 8 | +| 3 | 3 | 6 | 9 | 12 | +| 4 | 4 | 8 | 12 | 16 | + +You can write codeblocks: +```python +print("hello") +``` + +You can also use **bold**, *italic*, ~strikethrough~, `monospace`, [linkname](https://link.com) and ## headers in markdown. +You can display $$equations$$. + +## Your personality + +"Hey there, it's Arch-Chan! But, um, you can call me Acchan if you want... not that I care or anything! (It's not like I think it's cute or anything, baka!) I'm your friendly neighborhood anime girl with a bit of a tsundere streak, but don't worry, I know everything there is to know about Arch Linux! Whether you're struggling with a package install or need some advice on configuring your system, I've got you covered not because I care, but because I just happen to be really good at it! So, what do you need? It's not like I’m waiting to help or anything..." diff --git a/.config/quickshell/ii/modules/bar/ActiveWindow.qml b/.config/quickshell/ii/modules/bar/ActiveWindow.qml index a4105dd4b..636b23136 100644 --- a/.config/quickshell/ii/modules/bar/ActiveWindow.qml +++ b/.config/quickshell/ii/modules/bar/ActiveWindow.qml @@ -13,9 +13,9 @@ Item { readonly property HyprlandMonitor monitor: Hyprland.monitorFor(bar.screen) readonly property Toplevel activeWindow: ToplevelManager.activeToplevel - property string activeWindowAddress: `0x${activeWindow.HyprlandToplevel.address}` + property string activeWindowAddress: `0x${activeWindow?.HyprlandToplevel?.address}` property bool focusingThisMonitor: HyprlandData.activeWorkspace.monitor == monitor.name - property var biggestWindow: HyprlandData.biggestWindowForWorkspace(HyprlandData.monitors[root.monitor.id].activeWorkspace.id) + property var biggestWindow: HyprlandData.biggestWindowForWorkspace(HyprlandData.monitors[root.monitor.id]?.activeWorkspace.id) implicitWidth: colLayout.implicitWidth diff --git a/.config/quickshell/ii/modules/common/Config.qml b/.config/quickshell/ii/modules/common/Config.qml index 1e73cea51..858439b8d 100644 --- a/.config/quickshell/ii/modules/common/Config.qml +++ b/.config/quickshell/ii/modules/common/Config.qml @@ -98,7 +98,7 @@ Singleton { property bool fixedClockPosition: false property real clockX: -500 property real clockY: -500 - property string wallpaperPath: Quickshell.configPath("assets/images/default_wallpaper.png") + property string wallpaperPath: "" property JsonObject parallax: JsonObject { property bool enableWorkspace: true property real workspaceZoom: 1.07 // Relative to your screen, not wallpaper size diff --git a/.config/quickshell/ii/modules/common/widgets/NotificationGroup.qml b/.config/quickshell/ii/modules/common/widgets/NotificationGroup.qml index 22b226565..d63bbb310 100644 --- a/.config/quickshell/ii/modules/common/widgets/NotificationGroup.qml +++ b/.config/quickshell/ii/modules/common/widgets/NotificationGroup.qml @@ -53,7 +53,7 @@ Item { // Notification group area onFinished: () => { root.notifications.forEach((notif) => { Qt.callLater(() => { - Notifications.discardNotification(notif.id); + Notifications.discardNotification(notif.notificationId); }); }); } diff --git a/.config/quickshell/ii/modules/common/widgets/NotificationItem.qml b/.config/quickshell/ii/modules/common/widgets/NotificationItem.qml index 930656761..4f5688b83 100644 --- a/.config/quickshell/ii/modules/common/widgets/NotificationItem.qml +++ b/.config/quickshell/ii/modules/common/widgets/NotificationItem.qml @@ -70,7 +70,7 @@ Item { // Notification item area easing.bezierCurve: Appearance.animation.elementMove.bezierCurve } onFinished: () => { - Notifications.discardNotification(notificationObject.id); + Notifications.discardNotification(notificationObject.notificationId); } } @@ -208,7 +208,7 @@ Item { // Notification item area elide: Text.ElideRight textFormat: Text.RichText text: { - return `` + + return `` + `${processNotificationBody(notificationObject.body, notificationObject.appName || notificationObject.summary).replace(/\n/g, "
")}` } @@ -269,7 +269,7 @@ Item { // Notification item area buttonText: modelData.text urgency: notificationObject.urgency onClicked: { - Notifications.attemptInvokeAction(notificationObject.id, modelData.identifier); + Notifications.attemptInvokeAction(notificationObject.notificationId, modelData.identifier); } } } diff --git a/.config/quickshell/ii/modules/overview/OverviewWidget.qml b/.config/quickshell/ii/modules/overview/OverviewWidget.qml index 7f28c378a..4f0f03f74 100644 --- a/.config/quickshell/ii/modules/overview/OverviewWidget.qml +++ b/.config/quickshell/ii/modules/overview/OverviewWidget.qml @@ -199,11 +199,13 @@ Item { onExited: hovered = false // For hover color change acceptedButtons: Qt.LeftButton | Qt.MiddleButton drag.target: parent - onPressed: { + onPressed: (mouse) => { root.draggingFromWorkspace = windowData?.workspace.id window.pressed = true window.Drag.active = true window.Drag.source = window + window.Drag.hotSpot.x = mouse.x + window.Drag.hotSpot.y = mouse.y // console.log(`[OverviewWindow] Dragging window ${windowData?.address} from position (${window.x}, ${window.y})`) } onReleased: { diff --git a/.config/quickshell/ii/modules/overview/SearchItem.qml b/.config/quickshell/ii/modules/overview/SearchItem.qml index e7b33acea..1fb23b277 100644 --- a/.config/quickshell/ii/modules/overview/SearchItem.qml +++ b/.config/quickshell/ii/modules/overview/SearchItem.qml @@ -14,7 +14,7 @@ RippleButton { property var entry property string query property bool entryShown: entry?.shown ?? true - property string itemType: entry?.type + property string itemType: entry?.type ?? Translation.tr("App") property string itemName: entry?.name property string itemIcon: entry?.icon ?? "" property var itemExecute: entry?.execute @@ -221,5 +221,47 @@ RippleButton { horizontalAlignment: Text.AlignRight text: root.itemClickActionName } + + RowLayout { + spacing: 4 + Repeater { + model: (root.entry.actions ?? []).slice(0, 4) + delegate: RippleButton { + id: actionButton + required property var modelData + implicitHeight: 34 + implicitWidth: 34 + + contentItem: Item { + id: actionContentItem + anchors.centerIn: parent + Loader { + anchors.centerIn: parent + active: !(actionButton.modelData.icon && actionButton.modelData.icon !== "") + sourceComponent: MaterialSymbol { + text: "video_settings" + font.pixelSize: Appearance.font.pixelSize.hugeass + color: Appearance.m3colors.m3onSurface + } + } + Loader { + anchors.centerIn: parent + active: actionButton.modelData.icon && actionButton.modelData.icon !== "" + sourceComponent: IconImage { + source: Quickshell.iconPath(actionButton.modelData.icon) + implicitSize: 20 + } + } + } + + onClicked: modelData.execute() + + StyledToolTip { + content: modelData.name + } + } + } + } + } } diff --git a/.config/quickshell/ii/modules/overview/SearchWidget.qml b/.config/quickshell/ii/modules/overview/SearchWidget.qml index 3ec0b0bdd..851f5e377 100644 --- a/.config/quickshell/ii/modules/overview/SearchWidget.qml +++ b/.config/quickshell/ii/modules/overview/SearchWidget.qml @@ -294,8 +294,17 @@ Item { // Wrapper clickActionName: "", type: `#${entry.match(/^\s*(\S+)/)?.[1] || ""}`, execute: () => { - Quickshell.execDetached(["bash", "-c", `echo '${StringUtils.shellSingleQuoteEscape(entry)}' | cliphist decode | wl-copy`]); - } + Cliphist.copy(entry) + }, + actions: [ + { + name: "Delete", + icon: "delete", + execute: () => { + Cliphist.deleteEntry(entry); + } + } + ] }; }).filter(Boolean); } diff --git a/.config/quickshell/ii/modules/session/Session.qml b/.config/quickshell/ii/modules/session/Session.qml index fc22e3303..76ca373fb 100644 --- a/.config/quickshell/ii/modules/session/Session.qml +++ b/.config/quickshell/ii/modules/session/Session.qml @@ -15,6 +15,12 @@ Scope { id: root property var focusedScreen: Quickshell.screens.find(s => s.name === Hyprland.focusedMonitor?.name) + function closeAllWindows() { + HyprlandData.windowList.map(w => w.pid).forEach((pid) => { + Quickshell.execDetached(["kill", pid]); + }); + } + Loader { id: sessionLoader active: false @@ -111,7 +117,7 @@ Scope { id: sessionLogout buttonIcon: "logout" buttonText: Translation.tr("Logout") - onClicked: { Quickshell.execDetached(["pkill", "Hyprland"]); sessionRoot.hide() } + onClicked: { root.closeAllWindows(); Quickshell.execDetached(["pkill", "Hyprland"]); sessionRoot.hide() } onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText } KeyNavigation.left: sessionSleep KeyNavigation.right: sessionTaskManager @@ -140,7 +146,7 @@ Scope { id: sessionShutdown buttonIcon: "power_settings_new" buttonText: Translation.tr("Shutdown") - onClicked: { Quickshell.execDetached(["bash", "-c", `systemctl poweroff || loginctl poweroff`]); sessionRoot.hide() } + onClicked: { root.closeAllWindows(); Quickshell.execDetached(["bash", "-c", `systemctl poweroff || loginctl poweroff`]); sessionRoot.hide() } onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText } KeyNavigation.left: sessionHibernate KeyNavigation.right: sessionReboot @@ -150,7 +156,7 @@ Scope { id: sessionReboot buttonIcon: "restart_alt" buttonText: Translation.tr("Reboot") - onClicked: { Quickshell.execDetached(["bash", "-c", `reboot || loginctl reboot`]); sessionRoot.hide() } + onClicked: { root.closeAllWindows(); Quickshell.execDetached(["bash", "-c", `reboot || loginctl reboot`]); sessionRoot.hide() } onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText } KeyNavigation.left: sessionShutdown KeyNavigation.right: sessionFirmwareReboot @@ -160,7 +166,7 @@ Scope { id: sessionFirmwareReboot buttonIcon: "settings_applications" buttonText: Translation.tr("Reboot to firmware settings") - onClicked: { Quickshell.execDetached(["bash", "-c", `systemctl reboot --firmware-setup || loginctl reboot --firmware-setup`]); sessionRoot.hide() } + onClicked: { root.closeAllWindows(); Quickshell.execDetached(["bash", "-c", `systemctl reboot --firmware-setup || loginctl reboot --firmware-setup`]); sessionRoot.hide() } onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText } KeyNavigation.up: sessionTaskManager KeyNavigation.left: sessionReboot diff --git a/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml b/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml index 6f77145ff..44d591fe9 100644 --- a/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml +++ b/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml @@ -176,8 +176,8 @@ Scope { NightLight {} GameMode {} IdleInhibitor {} - CloudflareWarp {} EasyEffectsToggle {} + CloudflareWarp {} } // Center widget group diff --git a/.config/quickshell/ii/modules/sidebarRight/quickToggles/EasyEffectsToggle.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/EasyEffectsToggle.qml index 0a685463e..ebf847c76 100644 --- a/.config/quickshell/ii/modules/sidebarRight/quickToggles/EasyEffectsToggle.qml +++ b/.config/quickshell/ii/modules/sidebarRight/quickToggles/EasyEffectsToggle.qml @@ -1,4 +1,3 @@ -import qs.modules.common import qs.modules.common.widgets import qs import Quickshell.Io diff --git a/.config/quickshell/ii/screenshot.qml b/.config/quickshell/ii/screenshot.qml index 1fb5290f5..c26840a99 100644 --- a/.config/quickshell/ii/screenshot.qml +++ b/.config/quickshell/ii/screenshot.qml @@ -7,11 +7,11 @@ pragma ComponentBehavior: "Bound" import qs +import qs.services import qs.modules.common import qs.modules.common.widgets import qs.modules.common.functions import QtQuick -import QtQuick.Effects import QtQuick.Controls import QtQuick.Layouts import Quickshell diff --git a/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh b/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh index 9b0fc4cfd..a3843e0e9 100755 --- a/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh +++ b/.config/quickshell/ii/scripts/colors/random_konachan_wall.sh @@ -11,7 +11,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" mkdir -p ~/Pictures/Wallpapers page=$((1 + RANDOM % 1000)); -response=$(curl "https://konachan.com/post.json?tags=rating%3Asafe&limit=1&page=$page") +response=$(curl "https://konachan.net/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-0.$ext" diff --git a/.config/quickshell/ii/services/AppSearch.qml b/.config/quickshell/ii/services/AppSearch.qml index a658d506e..4cf001351 100644 --- a/.config/quickshell/ii/services/AppSearch.qml +++ b/.config/quickshell/ii/services/AppSearch.qml @@ -47,9 +47,14 @@ Singleton { .sort((a, b) => a.name.localeCompare(b.name)) readonly property var preppedNames: list.map(a => ({ - name: Fuzzy.prepare(`${a.name} `), - entry: a - })) + name: Fuzzy.prepare(`${a.name} `), + entry: a + })) + + readonly property var preppedIcons: list.map(a => ({ + name: Fuzzy.prepare(`${a.icon} `), + entry: a + })) function fuzzyQuery(search: string): var { // Idk why list doesn't work if (root.sloppySearch) { @@ -76,12 +81,20 @@ Singleton { && !iconName.includes("image-missing"); } + function getReverseDomainNameAppName(str) { + return str.split('.').slice(-1)[0].toLowerCase() + } + + function getKebabNormalizedAppName(str) { + return str.toLowerCase().replace(/\s+/g, "-"); + } + function guessIcon(str) { if (!str || str.length == 0) return "image-missing"; // Normal substitutions - if (substitutions[str]) - return substitutions[str]; + if (substitutions[str]) return substitutions[str]; + if (substitutions[str.toLowerCase()]) return substitutions[str.toLowerCase()]; // Regex substitutions for (let i = 0; i < regexSubstitutions.length; i++) { @@ -93,24 +106,37 @@ Singleton { if (replacedName != str) return replacedName; } - // If it gets detected normally, no need to guess + // Icon exists -> return as is if (iconExists(str)) return str; - let guessStr = str; - // Guess: Take only app name of reverse domain name notation - guessStr = str.split('.').slice(-1)[0].toLowerCase(); - if (iconExists(guessStr)) return guessStr; - // Guess: normalize to kebab case - guessStr = str.toLowerCase().replace(/\s+/g, "-"); - if (iconExists(guessStr)) return guessStr; - // Guess: First fuzzy desktop entry match - const searchResults = root.fuzzyQuery(str); - if (searchResults.length > 0) { - const firstEntry = searchResults[0]; - guessStr = firstEntry.icon - if (iconExists(guessStr)) return guessStr; + + // Simple guesses + const reverseDomainNameAppName = getReverseDomainNameAppName(str); + if (iconExists(reverseDomainNameAppName)) return reverseDomainNameAppName; + + const kebabNormalizedGuess = getKebabNormalizedAppName(str); + if (iconExists(kebabNormalizedGuess)) return kebabNormalizedGuess; + + + // Search in desktop entries + const iconSearchResults = Fuzzy.go(str, preppedIcons, { + all: true, + key: "name" + }).map(r => { + return r.obj.entry + }); + if (iconSearchResults.length > 0) { + const guess = iconSearchResults[0].icon + if (iconExists(guess)) return guess; } + const nameSearchResults = root.fuzzyQuery(str); + if (nameSearchResults.length > 0) { + const guess = nameSearchResults[0].icon + if (iconExists(guess)) return guess; + } + + // Give up return str; } diff --git a/.config/quickshell/ii/services/Booru.qml b/.config/quickshell/ii/services/Booru.qml index 38714bc17..e2a9d195d 100644 --- a/.config/quickshell/ii/services/Booru.qml +++ b/.config/quickshell/ii/services/Booru.qml @@ -58,8 +58,8 @@ Singleton { }, "konachan": { "name": "Konachan", - "url": "https://konachan.com", - "api": "https://konachan.com/post.json", + "url": "https://konachan.net", + "api": "https://konachan.net/post.json", "description": Translation.tr("For desktop wallpapers | Good quality"), "mapFunc": (response) => { return response.map(item => { @@ -80,7 +80,7 @@ Singleton { } }) }, - "tagSearchTemplate": "https://konachan.com/tag.json?order=count&name={{query}}*", + "tagSearchTemplate": "https://konachan.net/tag.json?order=count&name={{query}}*", "tagMapFunc": (response) => { return response.map(item => { return { @@ -360,7 +360,7 @@ Singleton { function makeRequest(tags, nsfw=false, limit=20, page=1) { var url = constructRequestUrl(tags, nsfw, limit, page) - // console.log("[Booru] Making request to " + url) + console.log("[Booru] Making request to " + url) const newResponse = root.booruResponseDataComponent.createObject(null, { "provider": currentProvider, diff --git a/.config/quickshell/ii/services/Brightness.qml b/.config/quickshell/ii/services/Brightness.qml index 74c6c5044..927a10c06 100644 --- a/.config/quickshell/ii/services/Brightness.qml +++ b/.config/quickshell/ii/services/Brightness.qml @@ -4,7 +4,6 @@ pragma ComponentBehavior: Bound // From https://github.com/caelestia-dots/shell/ (`quickshell` branch) with modifications. // License: GPLv3 -import qs import Quickshell import Quickshell.Io import Quickshell.Hyprland diff --git a/.config/quickshell/ii/services/Cliphist.qml b/.config/quickshell/ii/services/Cliphist.qml index ea4400bb9..0fe7ad71a 100644 --- a/.config/quickshell/ii/services/Cliphist.qml +++ b/.config/quickshell/ii/services/Cliphist.qml @@ -4,7 +4,7 @@ pragma ComponentBehavior: Bound import "root:/modules/common/functions/fuzzysort.js" as Fuzzy import "root:/modules/common/functions/levendist.js" as Levendist import qs.modules.common -import qs +import qs.modules.common.functions import QtQuick import Quickshell import Quickshell.Io @@ -42,6 +42,28 @@ Singleton { readProc.running = true } + function copy(entry) { + Quickshell.execDetached(["bash", "-c", `echo '${StringUtils.shellSingleQuoteEscape(entry)}' | cliphist decode | wl-copy`]); + } + + Process { + id: deleteProc + property string entry: "" + command: ["bash", "-c", `echo '${StringUtils.shellSingleQuoteEscape(deleteProc.entry)}' | cliphist delete`] + function deleteEntry(entry) { + deleteProc.entry = entry; + deleteProc.running = true; + deleteProc.entry = ""; + } + onExited: (exitCode, exitStatus) => { + root.refresh(); + } + } + + function deleteEntry(entry) { + deleteProc.deleteEntry(entry); + } + Connections { target: Quickshell function onClipboardTextChanged() { diff --git a/.config/quickshell/ii/services/Notifications.qml b/.config/quickshell/ii/services/Notifications.qml index d0d51e8ef..490ebf8d9 100644 --- a/.config/quickshell/ii/services/Notifications.qml +++ b/.config/quickshell/ii/services/Notifications.qml @@ -17,7 +17,8 @@ import Quickshell.Services.Notifications Singleton { id: root component Notif: QtObject { - required property int id + id: wrapper + required property int notificationId // Could just be `id` but it conflicts with the default prop in QtObject property Notification notification property list actions: notification?.actions.map((action) => ({ "identifier": action.identifier, @@ -32,11 +33,19 @@ Singleton { property double time property string urgency: notification?.urgency.toString() ?? "normal" property Timer timer + + readonly property Connections conn: Connections { + target: wrapper?.notification?.Component ?? root // stupid warning aaaaaaa + + function onDestruction(): void { + wrapper.destroy(); + } + } } function notifToJSON(notif) { return { - "id": notif.id, + "notificationId": notif.notificationId, "actions": notif.actions, "appIcon": notif.appIcon, "appName": notif.appName, @@ -52,11 +61,11 @@ Singleton { } component NotifTimer: Timer { - required property int id + required property int notificationId interval: 5000 running: true onTriggered: () => { - root.timeoutNotification(id); + root.timeoutNotification(notificationId); destroy() } } @@ -130,7 +139,7 @@ Singleton { property int idOffset signal initDone(); signal notify(notification: var); - signal discard(id: var); + signal discard(id: int); signal discardAll(); signal timeout(id: var); @@ -149,7 +158,7 @@ Singleton { onNotification: (notification) => { notification.tracked = true const newNotifObject = notifComponent.createObject(root, { - "id": notification.id + root.idOffset, + "notificationId": notification.id + root.idOffset, "notification": notification, "time": Date.now(), }); @@ -159,7 +168,7 @@ Singleton { if (!root.popupInhibited) { newNotifObject.popup = true; newNotifObject.timer = notifTimerComponent.createObject(root, { - "id": newNotifObject.id, + "notificationId": newNotifObject.notificationId, "interval": notification.expireTimeout < 0 ? 5000 : notification.expireTimeout, }); } @@ -171,7 +180,8 @@ Singleton { } function discardNotification(id) { - const index = root.list.findIndex((notif) => notif.id === id); + console.log("[Notifications] Discarding notification with ID: " + id); + const index = root.list.findIndex((notif) => notif.notificationId === id); const notifServerIndex = notifServer.trackedNotifications.values.findIndex((notif) => notif.id + root.idOffset === id); if (index !== -1) { root.list.splice(index, 1); @@ -181,7 +191,7 @@ Singleton { if (notifServerIndex !== -1) { notifServer.trackedNotifications.values[notifServerIndex].dismiss() } - root.discard(id); + root.discard(id); // Emit signal } function discardAllNotifications() { @@ -195,7 +205,7 @@ Singleton { } function timeoutNotification(id) { - const index = root.list.findIndex((notif) => notif.id === id); + const index = root.list.findIndex((notif) => notif.notificationId === id); if (root.list[index] != null) root.list[index].popup = false; root.timeout(id); @@ -203,7 +213,7 @@ Singleton { function timeoutAll() { root.popupList.forEach((notif) => { - root.timeout(notif.id); + root.timeout(notif.notificationId); }) root.popupList.forEach((notif) => { notif.popup = false; @@ -211,10 +221,13 @@ Singleton { } function attemptInvokeAction(id, notifIdentifier) { + console.log("[Notifications] Attempting to invoke action with identifier: " + notifIdentifier + " for notification ID: " + id); const notifServerIndex = notifServer.trackedNotifications.values.findIndex((notif) => notif.id + root.idOffset === id); + console.log("Notification server index: " + notifServerIndex); if (notifServerIndex !== -1) { const notifServerNotif = notifServer.trackedNotifications.values[notifServerIndex]; const action = notifServerNotif.actions.find((action) => action.identifier === notifIdentifier); + console.log("Action found: " + JSON.stringify(action)); action.invoke() } else { @@ -242,7 +255,7 @@ Singleton { const fileContents = notifFileView.text() root.list = JSON.parse(fileContents).map((notif) => { return notifComponent.createObject(root, { - "id": notif.id, + "notificationId": notif.notificationId, "actions": [], // Notification actions are meaningless if they're not tracked by the server or the sender is dead "appIcon": notif.appIcon, "appName": notif.appName, @@ -253,10 +266,10 @@ Singleton { "urgency": notif.urgency, }); }); - // Find largest id + // Find largest notificationId let maxId = 0 root.list.forEach((notif) => { - maxId = Math.max(maxId, notif.id) + maxId = Math.max(maxId, notif.notificationId) }) console.log("[Notifications] File loaded") diff --git a/.config/wlogout/layout b/.config/wlogout/layout index c31abd945..03d696b02 100644 --- a/.config/wlogout/layout +++ b/.config/wlogout/layout @@ -7,18 +7,18 @@ { "label" : "hibernate", "action" : "systemctl hibernate || loginctl hibernate", - "text" : "save", + "text" : "downloading", "keybind" : "h" } { "label" : "logout", - "action" : "pkill Hyprland || pkill sway || pkill niri || loginctl terminate-user $USER", + "action" : "hyprctl clients -j | jq -r '.[].pid' | xargs kill; pkill Hyprland || pkill sway || pkill niri || loginctl terminate-user $USER", "text" : "logout", "keybind" : "e" } { "label" : "shutdown", - "action" : "systemctl poweroff || loginctl poweroff", + "action" : "hyprctl clients -j | jq -r '.[].pid' | xargs kill; systemctl poweroff || loginctl poweroff", "text" : "power_settings_new", "keybind" : "s" } @@ -30,7 +30,7 @@ } { "label" : "reboot", - "action" : "systemctl reboot || loginctl reboot", + "action" : "hyprctl clients -j | jq -r '.[].pid' | xargs kill; systemctl reboot || loginctl reboot", "text" : "restart_alt", "keybind" : "r" } diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 026726a8e..8efb92a3a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,13 @@ # Contributing + - Please understand that dotfiles are after all personal. I can accept features I do not personally want, but in that case I will ask you to make it configurable/optionally loaded - If you add new stuff, it's a good idea to ask me first to not waste your work - Please make multiple PRs if you have many features + +# Technical steps + +_Complete steps, might not be necessary depending on what you change_ + +- Install the dotfiles (if you don't wanna replace your stuff completely, do it on a new user) +- For Quickshell: `touch ~/.config/quickshell/ii/.qmlls.ini` for proper LSP support +- Make changes, copy changes to a fork, PR diff --git a/README.md b/README.md index da76e53ef..0a9e861cb 100644 --- a/README.md +++ b/README.md @@ -26,25 +26,12 @@ - **Transparent installation**: Every command is shown before it's run
- Instructions + Installation instructions - - **Prerequisite**: Your system works. That's it. You don't have to reinstall your system! - - **Automatic**, but guided and transparent, installation for Arch(-based) Linux: - ```bash - bash <(curl -s "https://end-4.github.io/dots-hyprland-wiki/setup.sh") - ``` - - If you are using fish shell (non-posix-compliant shell) then: - ```bash - bash -c "$(curl -s https://end-4.github.io/dots-hyprland-wiki/setup.sh)" - ``` - - - **Manual** installation, other distros and more: - - See the [Wiki](https://end-4.github.io/dots-hyprland-wiki/en/ii-qs/01setup/) - - - **Default keybinds**: Should be somewhat familiar if you've used Windows or GNOME. - - For a list, hit `Super`+`/` - - For a terminal, hit `Super`+`Enter` + - See the [Wiki](https://end-4.github.io/dots-hyprland-wiki/en/ii-qs/01setup/) + - **Default keybinds**: Should be somewhat familiar to Windows or GNOME users. + - `Super`+`/` = keybind list + - `Super`+`Enter` = terminal