diff --git a/.config/hypr/hyprland/rules.conf b/.config/hypr/hyprland/rules.conf index 0589edb85..e4283b4cb 100644 --- a/.config/hypr/hyprland/rules.conf +++ b/.config/hypr/hyprland/rules.conf @@ -74,6 +74,9 @@ windowrulev2 = immediate, title:.*\.exe windowrulev2 = immediate, title:.*minecraft.* windowrulev2 = immediate, class:^(steam_app).* +# Fix Jetbrain IDEs focus/rerendering problem +windowrulev2=noinitialfocus,class:^jetbrains-.*$,floating:1,title:^$|^\s$|^win\d+$ + # No shadow for tiled windows (matches windows that are not floating). windowrulev2 = noshadow, floating:0 diff --git a/.config/quickshell/ii/GlobalStates.qml b/.config/quickshell/ii/GlobalStates.qml index 077a810bc..caf94ab16 100644 --- a/.config/quickshell/ii/GlobalStates.qml +++ b/.config/quickshell/ii/GlobalStates.qml @@ -1,5 +1,6 @@ -import qs.modules.common import qs +import qs.modules.common +import qs.services import QtQuick import Quickshell import Quickshell.Hyprland @@ -44,6 +45,13 @@ Singleton { } } + onSidebarRightOpenChanged: { + if (GlobalStates.sidebarRightOpen) { + Notifications.timeoutAll(); + Notifications.markAllRead(); + } + } + property real screenZoom: 1 onScreenZoomChanged: { Quickshell.execDetached(["hyprctl", "keyword", "cursor:zoom_factor", root.screenZoom.toString()]); diff --git a/.config/quickshell/ii/ReloadPopup.qml b/.config/quickshell/ii/ReloadPopup.qml index 4b0ecd884..4d858ee3e 100644 --- a/.config/quickshell/ii/ReloadPopup.qml +++ b/.config/quickshell/ii/ReloadPopup.qml @@ -58,7 +58,7 @@ Scope { MouseArea { id: mouseArea anchors.fill: parent - onClicked: { + onPressed: { popupLoader.active = false } diff --git a/.config/quickshell/ii/modules/background/cookieClock/SecondHand.qml b/.config/quickshell/ii/modules/background/cookieClock/SecondHand.qml index c05003020..a4643a259 100644 --- a/.config/quickshell/ii/modules/background/cookieClock/SecondHand.qml +++ b/.config/quickshell/ii/modules/background/cookieClock/SecondHand.qml @@ -19,7 +19,10 @@ Item { Behavior on rotation { enabled: Config.options.background.clock.cookie.constantlyRotate // Animating every second is expensive... - animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) + animation: NumberAnimation { + duration: 1000 // 1 second + easing.type: Easing.InOutQuad + } } Rectangle { diff --git a/.config/quickshell/ii/modules/bar/BarContent.qml b/.config/quickshell/ii/modules/bar/BarContent.qml index 4f538e1cc..b69fd6646 100644 --- a/.config/quickshell/ii/modules/bar/BarContent.qml +++ b/.config/quickshell/ii/modules/bar/BarContent.qml @@ -295,6 +295,48 @@ Item { // Bar content region Layout.rightMargin: indicatorsRowLayout.realSpacing color: rightSidebarButton.colText } + Revealer { + reveal: Notifications.silent || Notifications.unread > 0 + Layout.fillHeight: true + Layout.rightMargin: reveal ? indicatorsRowLayout.realSpacing : 0 + implicitHeight: reveal ? notificationIcon.implicitHeight : 0 + implicitWidth: reveal ? notificationIcon.implicitWidth : 0 + Behavior on Layout.rightMargin { + animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) + } + Rectangle { + id: notifPing + visible: !Notifications.silent && Notifications.unread > 0 + property bool showUnreadCount: Config.options.bar.indicators.notifications.showUnreadCount + anchors { + right: parent.right + top: parent.top + rightMargin: showUnreadCount ? 0 : 1 + topMargin: showUnreadCount ? 0 : 3 + } + radius: Appearance.rounding.full + color: Appearance.colors.colOnLayer0 + z: 1 + + implicitHeight: showUnreadCount ? Math.max(notificationCounterText.implicitWidth, notificationCounterText.implicitHeight) : 8 + implicitWidth: implicitHeight + + StyledText { + id: notificationCounterText + visible: notifPing.showUnreadCount + anchors.centerIn: parent + font.pixelSize: Appearance.font.pixelSize.smallest + color: Appearance.colors.colLayer0 + text: Notifications.unread + } + } + MaterialSymbol { + id: notificationIcon + text: Notifications.silent ? "notifications_paused" : "notifications" + iconSize: Appearance.font.pixelSize.larger + color: rightSidebarButton.colText + } + } MaterialSymbol { Layout.rightMargin: indicatorsRowLayout.realSpacing text: Network.materialSymbol @@ -302,6 +344,7 @@ Item { // Bar content region color: rightSidebarButton.colText } MaterialSymbol { + visible: BluetoothStatus.available text: BluetoothStatus.connected ? "bluetooth_connected" : BluetoothStatus.enabled ? "bluetooth" : "bluetooth_disabled" iconSize: Appearance.font.pixelSize.larger color: rightSidebarButton.colText diff --git a/.config/quickshell/ii/modules/bar/SysTray.qml b/.config/quickshell/ii/modules/bar/SysTray.qml index 2a6259a97..c23bb6c79 100644 --- a/.config/quickshell/ii/modules/bar/SysTray.qml +++ b/.config/quickshell/ii/modules/bar/SysTray.qml @@ -75,7 +75,7 @@ Item { toggled: root.trayOverflowOpen property bool containsMouse: hovered - onClicked: root.trayOverflowOpen = !root.trayOverflowOpen + downAction: () => root.trayOverflowOpen = !root.trayOverflowOpen Layout.fillHeight: !root.vertical Layout.fillWidth: root.vertical diff --git a/.config/quickshell/ii/modules/bar/SysTrayMenu.qml b/.config/quickshell/ii/modules/bar/SysTrayMenu.qml index 6caffb41c..d9569e608 100644 --- a/.config/quickshell/ii/modules/bar/SysTrayMenu.qml +++ b/.config/quickshell/ii/modules/bar/SysTrayMenu.qml @@ -48,7 +48,7 @@ PopupWindow { MouseArea { anchors.fill: parent acceptedButtons: Qt.BackButton | Qt.RightButton - onClicked: event => { + onPressed: event => { if ((event.button === Qt.BackButton || event.button === Qt.RightButton) && stackView.depth > 1) stackView.pop(); } @@ -152,7 +152,7 @@ PopupWindow { implicitWidth: contentItem.implicitWidth + horizontalPadding * 2 implicitHeight: 36 - onClicked: stackView.pop() + downAction: () => stackView.pop() contentItem: RowLayout { anchors { diff --git a/.config/quickshell/ii/modules/bar/weather/WeatherBar.qml b/.config/quickshell/ii/modules/bar/weather/WeatherBar.qml index b39228ab6..aed2a7ff8 100644 --- a/.config/quickshell/ii/modules/bar/weather/WeatherBar.qml +++ b/.config/quickshell/ii/modules/bar/weather/WeatherBar.qml @@ -15,7 +15,7 @@ MouseArea { hoverEnabled: true - onClicked: { + onPressed: { Weather.getData(); Quickshell.execDetached(["notify-send", Translation.tr("Weather"), diff --git a/.config/quickshell/ii/modules/common/Appearance.qml b/.config/quickshell/ii/modules/common/Appearance.qml index d6822785a..818417360 100644 --- a/.config/quickshell/ii/modules/common/Appearance.qml +++ b/.config/quickshell/ii/modules/common/Appearance.qml @@ -18,7 +18,9 @@ Singleton { // Transparency. The quadratic functions were derived from analysis of hand-picked transparency values. ColorQuantizer { id: wallColorQuant - source: Qt.resolvedUrl(Config.options.background.wallpaperPath) + property string wallpaperPath: Config.options.background.wallpaperPath + property bool wallpaperIsVideo: wallpaperPath.endsWith(".mp4") || wallpaperPath.endsWith(".webm") || wallpaperPath.endsWith(".mkv") || wallpaperPath.endsWith(".avi") || wallpaperPath.endsWith(".mov") + source: Qt.resolvedUrl(wallpaperIsVideo ? Config.options.background.thumbnailPath : Config.options.background.wallpaperPath) depth: 0 // 2^0 = 1 color rescaleSize: 10 } @@ -303,7 +305,7 @@ Singleton { } property QtObject elementResize: QtObject { - property int duration: 400 + property int duration: 300 property int type: Easing.BezierSpline property list bezierCurve: animationCurves.emphasized property int velocity: 650 diff --git a/.config/quickshell/ii/modules/common/Config.qml b/.config/quickshell/ii/modules/common/Config.qml index f20dba034..c1aea922e 100644 --- a/.config/quickshell/ii/modules/common/Config.qml +++ b/.config/quickshell/ii/modules/common/Config.qml @@ -137,7 +137,7 @@ Singleton { property string secondHandStyle: "dot" // Options: "dot", "line" , "hide" property string dateStyle: "bubble" // Options: "border", "rect", "bubble" , "hide" property bool timeIndicators: true - property bool hourMarks: true + property bool hourMarks: false property bool dateInClock: true property bool constantlyRotate: false } @@ -212,6 +212,11 @@ Singleton { property bool useUSCS: false // Instead of metric (SI) units property int fetchInterval: 10 // minutes } + property JsonObject indicators: JsonObject { + property JsonObject notifications: JsonObject { + property bool showUnreadCount: false + } + } } property JsonObject battery: JsonObject { @@ -341,8 +346,12 @@ Singleton { property JsonObject sidebar: JsonObject { property bool keepRightSidebarLoaded: true property JsonObject translator: JsonObject { + property bool enable: false property int delay: 300 // Delay before sending request. Reduces (potential) rate limits and lag. } + property JsonObject ai: JsonObject { + property bool textFadeIn: true + } property JsonObject booru: JsonObject { property bool allowNsfw: false property string defaultProvider: "yandere" diff --git a/.config/quickshell/ii/modules/common/widgets/AddressBar.qml b/.config/quickshell/ii/modules/common/widgets/AddressBar.qml index bf1cf2305..5648beb7a 100644 --- a/.config/quickshell/ii/modules/common/widgets/AddressBar.qml +++ b/.config/quickshell/ii/modules/common/widgets/AddressBar.qml @@ -35,7 +35,7 @@ Rectangle { RippleButton { id: parentDirButton - onClicked: root.navigateToDirectory(FileUtils.parentDirectory(root.directory)) + downAction: () => root.navigateToDirectory(FileUtils.parentDirectory(root.directory)) contentItem: MaterialSymbol { text: "drive_folder_upload" iconSize: Appearance.font.pixelSize.larger @@ -105,7 +105,7 @@ Rectangle { RippleButton { id: dirEditButton toggled: !root.showBreadcrumb - onClicked: root.showBreadcrumb = !root.showBreadcrumb + downAction: () => root.showBreadcrumb = !root.showBreadcrumb contentItem: MaterialSymbol { text: "edit" iconSize: Appearance.font.pixelSize.larger diff --git a/.config/quickshell/ii/modules/common/widgets/ContentSection.qml b/.config/quickshell/ii/modules/common/widgets/ContentSection.qml index 8af81fbee..0ff800c06 100644 --- a/.config/quickshell/ii/modules/common/widgets/ContentSection.qml +++ b/.config/quickshell/ii/modules/common/widgets/ContentSection.qml @@ -23,6 +23,7 @@ ColumnLayout { text: root.title font.pixelSize: Appearance.font.pixelSize.larger font.weight: Font.Medium + color: Appearance.colors.colOnSecondaryContainer } } diff --git a/.config/quickshell/ii/modules/common/widgets/CookieWrappedMaterialSymbol.qml b/.config/quickshell/ii/modules/common/widgets/CookieWrappedMaterialSymbol.qml new file mode 100644 index 000000000..996388a3c --- /dev/null +++ b/.config/quickshell/ii/modules/common/widgets/CookieWrappedMaterialSymbol.qml @@ -0,0 +1,25 @@ +import QtQuick +import qs.modules.common +import qs.modules.common.widgets + +MaterialCookie { + id: root + property alias text: symbol.text + property alias iconSize: symbol.iconSize + property alias font: symbol.font + property alias colSymbol: symbol.color + property real padding: 6 + + color: Appearance.colors.colSecondaryContainer + colSymbol: Appearance.colors.colOnSecondaryContainer + + sides: 5 + + implicitSize: Math.max(symbol.implicitWidth, symbol.implicitHeight) + padding * 2 + + MaterialSymbol { + id: symbol + anchors.centerIn: parent + } + +} diff --git a/.config/quickshell/ii/modules/common/widgets/GroupButton.qml b/.config/quickshell/ii/modules/common/widgets/GroupButton.qml index 4a524e1d5..d1b07c74e 100644 --- a/.config/quickshell/ii/modules/common/widgets/GroupButton.qml +++ b/.config/quickshell/ii/modules/common/widgets/GroupButton.qml @@ -32,7 +32,7 @@ Button { implicitWidth: (root.down && bounce) ? clickedWidth : baseWidth implicitHeight: (root.down && bounce) ? clickedHeight : baseHeight - property color colBackground: ColorUtils.transparentize(Appearance?.colors.colLayer1Hover, 1) || "transparent" + property color colBackground: ColorUtils.transparentize(colBackgroundHover, 1) || "transparent" property color colBackgroundHover: Appearance?.colors.colLayer1Hover ?? "#E5DFED" property color colBackgroundActive: Appearance?.colors.colLayer1Active ?? "#D6CEE2" property color colBackgroundToggled: Appearance?.colors.colPrimary ?? "#65558F" diff --git a/.config/quickshell/ii/modules/common/widgets/NavigationRailExpandButton.qml b/.config/quickshell/ii/modules/common/widgets/NavigationRailExpandButton.qml index 57e15f044..1e562f6ff 100644 --- a/.config/quickshell/ii/modules/common/widgets/NavigationRailExpandButton.qml +++ b/.config/quickshell/ii/modules/common/widgets/NavigationRailExpandButton.qml @@ -9,7 +9,7 @@ RippleButton { implicitWidth: 40 implicitHeight: 40 Layout.leftMargin: 8 - onClicked: { + downAction: () => { parent.expanded = !parent.expanded; } buttonRadius: Appearance.rounding.full diff --git a/.config/quickshell/ii/modules/common/widgets/NotificationAppIcon.qml b/.config/quickshell/ii/modules/common/widgets/NotificationAppIcon.qml index 278691b8b..9155bd879 100644 --- a/.config/quickshell/ii/modules/common/widgets/NotificationAppIcon.qml +++ b/.config/quickshell/ii/modules/common/widgets/NotificationAppIcon.qml @@ -6,25 +6,25 @@ import Quickshell import Quickshell.Widgets import Quickshell.Services.Notifications -Rectangle { // App icon +MaterialCookie { // App icon id: root property var appIcon: "" property var summary: "" property var urgency: NotificationUrgency.Normal + property bool isUrgent: urgency === NotificationUrgency.Critical property var image: "" - property real scale: 1 - property real size: 38 * scale property real materialIconScale: 0.57 property real appIconScale: 0.8 property real smallAppIconScale: 0.49 - property real materialIconSize: size * materialIconScale - property real appIconSize: size * appIconScale - property real smallAppIconSize: size * smallAppIconScale + property real materialIconSize: implicitSize * materialIconScale + property real appIconSize: implicitSize * appIconScale + property real smallAppIconSize: implicitSize * smallAppIconScale - implicitWidth: size - implicitHeight: size - radius: Appearance.rounding.full - color: Appearance.colors.colSecondaryContainer + implicitSize: 38 * scale + sides: isUrgent ? 10 : 0 + amplitude: implicitSize / 24 + + color: isUrgent ? Appearance.colors.colPrimary : Appearance.colors.colSecondaryContainer Loader { id: materialSymbolLoader active: root.appIcon == "" @@ -34,12 +34,10 @@ Rectangle { // App icon const defaultIcon = NotificationUtils.findSuitableMaterialSymbol("") const guessedIcon = NotificationUtils.findSuitableMaterialSymbol(root.summary) return (root.urgency == NotificationUrgency.Critical && guessedIcon === defaultIcon) ? - "release_alert" : guessedIcon + "priority_high" : guessedIcon } anchors.fill: parent - color: (root.urgency == NotificationUrgency.Critical) ? - ColorUtils.mix(Appearance.m3colors.m3onSecondary, Appearance.m3colors.m3onSecondaryContainer, 0.1) : - Appearance.m3colors.m3onSecondaryContainer + color: isUrgent ? Appearance.colors.colOnPrimary : Appearance.colors.colOnSecondaryContainer iconSize: root.materialIconSize horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter diff --git a/.config/quickshell/ii/modules/common/widgets/NotificationGroup.qml b/.config/quickshell/ii/modules/common/widgets/NotificationGroup.qml index e0736bb10..b05ea76d4 100644 --- a/.config/quickshell/ii/modules/common/widgets/NotificationGroup.qml +++ b/.config/quickshell/ii/modules/common/widgets/NotificationGroup.qml @@ -6,6 +6,7 @@ import "./notification_utils.js" as NotificationUtils import QtQuick import QtQuick.Layouts import Quickshell +import Quickshell.Services.Notifications /** * A group of notifications from the same app. @@ -154,6 +155,8 @@ MouseArea { // Notification group area image: root?.multipleNotifications ? "" : notificationGroup?.notifications[0]?.image ?? "" appIcon: notificationGroup?.appIcon summary: notificationGroup?.notifications[root.notificationCount - 1]?.summary + urgency: root.notifications.some(n => n.urgency === NotificationUrgency.Critical.toString()) ? + NotificationUrgency.Critical : NotificationUrgency.Normal } ColumnLayout { // Content diff --git a/.config/quickshell/ii/modules/common/widgets/PrimaryTabButton.qml b/.config/quickshell/ii/modules/common/widgets/PrimaryTabButton.qml index 6c687321c..bedcc2d92 100644 --- a/.config/quickshell/ii/modules/common/widgets/PrimaryTabButton.qml +++ b/.config/quickshell/ii/modules/common/widgets/PrimaryTabButton.qml @@ -32,7 +32,8 @@ TabButton { MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor - onPressed: (event) => { + onPressed: (event) => { + button.click() // Because the MouseArea already consumed the event const {x,y} = event const stateY = buttonBackground.y; rippleAnim.x = x; @@ -46,7 +47,6 @@ TabButton { rippleAnim.restart(); } onReleased: (event) => { - button.click() // Because the MouseArea already consumed the event rippleFadeAnim.restart(); } } diff --git a/.config/quickshell/ii/modules/common/widgets/SecondaryTabButton.qml b/.config/quickshell/ii/modules/common/widgets/SecondaryTabButton.qml index 774da7d51..347774cff 100644 --- a/.config/quickshell/ii/modules/common/widgets/SecondaryTabButton.qml +++ b/.config/quickshell/ii/modules/common/widgets/SecondaryTabButton.qml @@ -30,7 +30,8 @@ TabButton { MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor - onPressed: (event) => { + onPressed: (event) => { + root.click() // Because the MouseArea already consumed the event const {x,y} = event const stateY = buttonBackground.y; rippleAnim.x = x; @@ -44,7 +45,6 @@ TabButton { rippleAnim.restart(); } onReleased: (event) => { - root.click() // Because the MouseArea already consumed the event rippleFadeAnim.restart(); } } diff --git a/.config/quickshell/ii/modules/mediaControls/PlayerControl.qml b/.config/quickshell/ii/modules/mediaControls/PlayerControl.qml index cc248151f..83bc10a22 100644 --- a/.config/quickshell/ii/modules/mediaControls/PlayerControl.qml +++ b/.config/quickshell/ii/modules/mediaControls/PlayerControl.qml @@ -234,7 +234,7 @@ Item { // Player instance } TrackChangeButton { iconName: "skip_previous" - onClicked: root.player?.previous() + downAction: () => root.player?.previous() } Item { id: progressBarContainer @@ -277,7 +277,7 @@ Item { // Player instance } TrackChangeButton { iconName: "skip_next" - onClicked: root.player?.next() + downAction: () => root.player?.next() } } @@ -289,7 +289,7 @@ Item { // Player instance property real size: 44 implicitWidth: size implicitHeight: size - onClicked: root.player.togglePlaying(); + downAction: () => root.player.togglePlaying(); buttonRadius: root.player?.isPlaying ? Appearance?.rounding.normal : size / 2 colBackground: root.player?.isPlaying ? blendedColors.colPrimary : blendedColors.colSecondaryContainer diff --git a/.config/quickshell/ii/modules/onScreenKeyboard/OnScreenKeyboard.qml b/.config/quickshell/ii/modules/onScreenKeyboard/OnScreenKeyboard.qml index d8290abb7..3407c217f 100644 --- a/.config/quickshell/ii/modules/onScreenKeyboard/OnScreenKeyboard.qml +++ b/.config/quickshell/ii/modules/onScreenKeyboard/OnScreenKeyboard.qml @@ -18,7 +18,7 @@ Scope { // Scope baseWidth: 40 baseHeight: 40 clickedWidth: baseWidth - clickedHeight: baseHeight + 20 + clickedHeight: baseHeight + 10 buttonRadius: Appearance.rounding.normal } @@ -84,7 +84,7 @@ Scope { // Scope VerticalButtonGroup { OskControlButton { // Pin button toggled: root.pinned - onClicked: root.pinned = !root.pinned + downAction: () => root.pinned = !root.pinned contentItem: MaterialSymbol { text: "keep" horizontalAlignment: Text.AlignHCenter diff --git a/.config/quickshell/ii/modules/overview/OverviewWidget.qml b/.config/quickshell/ii/modules/overview/OverviewWidget.qml index 0e850493a..b7e8f61d6 100644 --- a/.config/quickshell/ii/modules/overview/OverviewWidget.qml +++ b/.config/quickshell/ii/modules/overview/OverviewWidget.qml @@ -111,7 +111,7 @@ Item { id: workspaceArea anchors.fill: parent acceptedButtons: Qt.LeftButton - onClicked: { + onPressed: { if (root.draggingTargetWorkspace === -1) { GlobalStates.overviewOpen = false Hyprland.dispatch(`workspace ${workspaceValue}`) diff --git a/.config/quickshell/ii/modules/settings/GeneralConfig.qml b/.config/quickshell/ii/modules/settings/GeneralConfig.qml index 2dcc39a2e..74ed1cdf2 100644 --- a/.config/quickshell/ii/modules/settings/GeneralConfig.qml +++ b/.config/quickshell/ii/modules/settings/GeneralConfig.qml @@ -144,41 +144,13 @@ ContentPage { title: Translation.tr("Policies") ConfigRow { - ColumnLayout { - // Weeb policy - ContentSubsectionLabel { - text: Translation.tr("Weeb") - } - ConfigSelectionArray { - currentValue: Config.options.policies.weeb - onSelected: newValue => { - Config.options.policies.weeb = newValue; - } - options: [ - { - displayName: Translation.tr("No"), - icon: "close", - value: 0 - }, - { - displayName: Translation.tr("Yes"), - icon: "check", - value: 1 - }, - { - displayName: Translation.tr("Closet"), - icon: "ev_shadow", - value: 2 - } - ] - } - } + // AI policy ColumnLayout { - // AI policy ContentSubsectionLabel { text: Translation.tr("AI") } + ConfigSelectionArray { currentValue: Config.options.policies.ai onSelected: newValue => { @@ -203,6 +175,38 @@ ContentPage { ] } } + + // Weeb policy + ColumnLayout { + + ContentSubsectionLabel { + text: Translation.tr("Weeb") + } + + ConfigSelectionArray { + currentValue: Config.options.policies.weeb + onSelected: newValue => { + Config.options.policies.weeb = newValue; + } + options: [ + { + displayName: Translation.tr("No"), + icon: "close", + value: 0 + }, + { + displayName: Translation.tr("Yes"), + icon: "check", + value: 1 + }, + { + displayName: Translation.tr("Closet"), + icon: "ev_shadow", + value: 2 + } + ] + } + } } } diff --git a/.config/quickshell/ii/modules/settings/InterfaceConfig.qml b/.config/quickshell/ii/modules/settings/InterfaceConfig.qml index 9e08b1d04..a4e51add5 100644 --- a/.config/quickshell/ii/modules/settings/InterfaceConfig.qml +++ b/.config/quickshell/ii/modules/settings/InterfaceConfig.qml @@ -64,8 +64,8 @@ ContentPage { icon: "add_triangle" text: Translation.tr("Sides") value: Config.options.background.clock.cookie.sides - from: 1 - to: 36 + from: 0 + to: 40 stepSize: 1 onValueChanged: { Config.options.background.clock.cookie.sides = value; @@ -569,6 +569,15 @@ ContentPage { } } + ConfigSwitch { + buttonIcon: "translate" + text: Translation.tr('Enable translator') + checked: Config.options.sidebar.translator.enable + onCheckedChanged: { + Config.options.sidebar.translator.enable = checked; + } + } + ContentSubsection { title: Translation.tr("Corner open") tooltip: Translation.tr("Allows you to open sidebars by clicking or hovering screen corners regardless of bar position") diff --git a/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml b/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml index 29411b7ae..78a0b816c 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml @@ -336,10 +336,10 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) property int lastResponseLength: 0 onContentHeightChanged: { - if (atYEnd) positionViewAtEnd(); + if (atYEnd) Qt.callLater(positionViewAtEnd); } onCountChanged: { // Auto-scroll when new messages are added - if (atYEnd) positionViewAtEnd(); + if (atYEnd) Qt.callLater(positionViewAtEnd); } add: null // Prevent function calls from being janky @@ -374,10 +374,9 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) anchors.centerIn: parent spacing: 5 - MaterialSymbol { + CookieWrappedMaterialSymbol { Layout.alignment: Qt.AlignHCenter iconSize: 60 - color: Appearance.m3colors.m3outline text: "neurology" } StyledText { @@ -757,8 +756,8 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) delegate: ApiCommandButton { property string commandRepresentation: `${root.commandPrefix}${modelData.name}` buttonText: commandRepresentation - onClicked: { - if(modelData.sendDirectly) { + downAction: () => { + if (modelData.sendDirectly) { root.handleInput(commandRepresentation) } else { messageInputField.text = commandRepresentation + (modelData.dontAddSpace ? "" : " ") @@ -778,4 +777,4 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) } -} \ No newline at end of file +} diff --git a/.config/quickshell/ii/modules/sidebarLeft/Anime.qml b/.config/quickshell/ii/modules/sidebarLeft/Anime.qml index 19b930958..9306a9d09 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/Anime.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/Anime.qml @@ -198,10 +198,9 @@ Item { anchors.centerIn: parent spacing: 5 - MaterialSymbol { + CookieWrappedMaterialSymbol { Layout.alignment: Qt.AlignHCenter iconSize: 60 - color: Appearance.m3colors.m3outline text: "bookmark_heart" } StyledText { @@ -525,9 +524,10 @@ Item { anchors.centerIn: parent MouseArea { + anchors.fill: parent hoverEnabled: true PointingHandInteraction {} - onClicked: { + onPressed: { nsfwSwitch.checked = !nsfwSwitch.checked } } @@ -566,8 +566,8 @@ Item { buttonText: commandRepresentation colBackground: Appearance.colors.colLayer2 - onClicked: { - if(modelData.sendDirectly) { + downAction: () => { + if (modelData.sendDirectly) { root.handleInput(commandRepresentation) } else { tagInputField.text = commandRepresentation + " " diff --git a/.config/quickshell/ii/modules/sidebarLeft/ApiCommandButton.qml b/.config/quickshell/ii/modules/sidebarLeft/ApiCommandButton.qml index efbde1506..34567ee0d 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/ApiCommandButton.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/ApiCommandButton.qml @@ -10,7 +10,7 @@ GroupButton { verticalPadding: 6 baseWidth: contentItem.implicitWidth + horizontalPadding * 2 - clickedWidth: baseWidth + 20 + clickedWidth: baseWidth + 14 baseHeight: contentItem.implicitHeight + verticalPadding * 2 buttonRadius: down ? Appearance.rounding.verysmall : Appearance.rounding.small diff --git a/.config/quickshell/ii/modules/sidebarLeft/SidebarLeftContent.qml b/.config/quickshell/ii/modules/sidebarLeft/SidebarLeftContent.qml index fc60618e0..341e73e64 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/SidebarLeftContent.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/SidebarLeftContent.qml @@ -12,12 +12,17 @@ Item { id: root required property var scopeRoot anchors.fill: parent + property bool aiChatEnabled: Config.options.policies.ai !== 0 + property bool translatorEnabled: Config.options.sidebar.translator.enable + property bool animeEnabled: Config.options.policies.weeb !== 0 + property bool animeCloset: Config.options.policies.weeb === 2 property var tabButtonList: [ - ...(Config.options.policies.ai !== 0 ? [{"icon": "neurology", "name": Translation.tr("Intelligence")}] : []), - {"icon": "translate", "name": Translation.tr("Translator")}, - ...(Config.options.policies.weeb === 1 ? [{"icon": "bookmark_heart", "name": Translation.tr("Anime")}] : []) + ...(root.aiChatEnabled ? [{"icon": "neurology", "name": Translation.tr("Intelligence")}] : []), + ...(root.translatorEnabled ? [{"icon": "translate", "name": Translation.tr("Translator")}] : []), + ...((root.animeEnabled && !root.animeCloset) ? [{"icon": "bookmark_heart", "name": Translation.tr("Anime")}] : []) ] property int selectedTab: 0 + property int tabCount: swipeView.count function focusActiveItem() { swipeView.currentItem.forceActiveFocus() @@ -26,7 +31,7 @@ Item { Keys.onPressed: (event) => { if (event.modifiers === Qt.ControlModifier) { if (event.key === Qt.Key_PageDown) { - root.selectedTab = Math.min(root.selectedTab + 1, root.tabButtonList.length - 1) + root.selectedTab = Math.min(root.selectedTab + 1, root.tabCount - 1) event.accepted = true; } else if (event.key === Qt.Key_PageUp) { @@ -34,11 +39,11 @@ Item { event.accepted = true; } else if (event.key === Qt.Key_Tab) { - root.selectedTab = (root.selectedTab + 1) % root.tabButtonList.length; + root.selectedTab = (root.selectedTab + 1) % root.tabCount; event.accepted = true; } else if (event.key === Qt.Key_Backtab) { - root.selectedTab = (root.selectedTab - 1 + root.tabButtonList.length) % root.tabButtonList.length; + root.selectedTab = (root.selectedTab - 1 + root.tabCount) % root.tabCount; event.accepted = true; } } @@ -52,6 +57,7 @@ Item { PrimaryTabBar { // Tab strip id: tabBar + visible: root.tabButtonList.length > 1 tabButtonList: root.tabButtonList externalTrackedTab: root.selectedTab function onCurrentIndexChanged(currentIndex) { @@ -83,9 +89,9 @@ Item { } contentChildren: [ - ...(Config.options.policies.ai !== 0 ? [aiChat.createObject()] : []), - translator.createObject(), - ...(Config.options.policies.weeb === 0 ? [] : [anime.createObject()]) + ...((root.aiChatEnabled || (!root.translatorEnabled && !root.animeEnabled)) ? [aiChat.createObject()] : []), + ...(root.translatorEnabled ? [translator.createObject()] : []), + ...(root.animeEnabled ? [anime.createObject()] : []) ] } diff --git a/.config/quickshell/ii/modules/sidebarLeft/aiChat/AiMessage.qml b/.config/quickshell/ii/modules/sidebarLeft/aiChat/AiMessage.qml index 2072a67ae..a85986575 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/aiChat/AiMessage.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/aiChat/AiMessage.qml @@ -78,156 +78,165 @@ Rectangle { anchors.top: parent.top anchors.margins: messagePadding spacing: root.contentSpacing - - RowLayout { // Header - spacing: 15 + + Rectangle { Layout.fillWidth: true + implicitWidth: headerRowLayout.implicitWidth + 4 * 2 + implicitHeight: headerRowLayout.implicitHeight + 4 * 2 + color: Appearance.colors.colSecondaryContainer + radius: Appearance.rounding.small + + RowLayout { // Header + id: headerRowLayout + anchors { + fill: parent + margins: 4 + } + spacing: 18 - Rectangle { // Name - id: nameWrapper - color: Appearance.colors.colSecondaryContainer - // color: "transparent" - radius: Appearance.rounding.small - implicitHeight: Math.max(nameRowLayout.implicitHeight + 5 * 2, 30) - Layout.fillWidth: true - Layout.alignment: Qt.AlignVCenter + Item { // Name + id: nameWrapper + implicitHeight: Math.max(nameRowLayout.implicitHeight + 5 * 2, 30) + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter - RowLayout { - id: nameRowLayout - anchors.verticalCenter: parent.verticalCenter - anchors.left: parent.left - anchors.right: parent.right - anchors.leftMargin: 10 - anchors.rightMargin: 10 - spacing: 7 + RowLayout { + id: nameRowLayout + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.right: parent.right + anchors.leftMargin: 10 + anchors.rightMargin: 10 + spacing: 7 - Item { - Layout.alignment: Qt.AlignVCenter - Layout.fillHeight: true - implicitWidth: messageData?.role == 'assistant' ? modelIcon.width : roleIcon.implicitWidth - implicitHeight: messageData?.role == 'assistant' ? modelIcon.height : roleIcon.implicitHeight + Item { + Layout.alignment: Qt.AlignVCenter + Layout.fillHeight: true + implicitWidth: messageData?.role == 'assistant' ? modelIcon.width : roleIcon.implicitWidth + implicitHeight: messageData?.role == 'assistant' ? modelIcon.height : roleIcon.implicitHeight - CustomIcon { - id: modelIcon - anchors.centerIn: parent - visible: messageData?.role == 'assistant' && Ai.models[messageData?.model].icon - width: Appearance.font.pixelSize.large - height: Appearance.font.pixelSize.large - source: messageData?.role == 'assistant' ? Ai.models[messageData?.model].icon : - messageData?.role == 'user' ? 'linux-symbolic' : 'desktop-symbolic' + CustomIcon { + id: modelIcon + anchors.centerIn: parent + visible: messageData?.role == 'assistant' && Ai.models[messageData?.model].icon + width: Appearance.font.pixelSize.large + height: Appearance.font.pixelSize.large + source: messageData?.role == 'assistant' ? Ai.models[messageData?.model].icon : + messageData?.role == 'user' ? 'linux-symbolic' : 'desktop-symbolic' - colorize: true + colorize: true + color: Appearance.m3colors.m3onSecondaryContainer + } + + MaterialSymbol { + id: roleIcon + anchors.centerIn: parent + visible: !modelIcon.visible + iconSize: Appearance.font.pixelSize.larger + color: Appearance.m3colors.m3onSecondaryContainer + text: messageData?.role == 'user' ? 'person' : + messageData?.role == 'interface' ? 'settings' : + messageData?.role == 'assistant' ? 'neurology' : + 'computer' + } + } + + StyledText { + id: providerName + Layout.alignment: Qt.AlignVCenter + Layout.fillWidth: true + elide: Text.ElideRight + font.pixelSize: Appearance.font.pixelSize.normal color: Appearance.m3colors.m3onSecondaryContainer - } - - MaterialSymbol { - id: roleIcon - anchors.centerIn: parent - visible: !modelIcon.visible - iconSize: Appearance.font.pixelSize.larger - color: Appearance.m3colors.m3onSecondaryContainer - text: messageData?.role == 'user' ? 'person' : - messageData?.role == 'interface' ? 'settings' : - messageData?.role == 'assistant' ? 'neurology' : - 'computer' + text: messageData?.role == 'assistant' ? Ai.models[messageData?.model].name : + (messageData?.role == 'user' && SystemInfo.username) ? SystemInfo.username : + Translation.tr("Interface") } } + } - StyledText { - id: providerName - Layout.alignment: Qt.AlignVCenter - Layout.fillWidth: true - elide: Text.ElideRight - font.pixelSize: Appearance.font.pixelSize.normal - color: Appearance.m3colors.m3onSecondaryContainer - text: messageData?.role == 'assistant' ? Ai.models[messageData?.model].name : - (messageData?.role == 'user' && SystemInfo.username) ? SystemInfo.username : - Translation.tr("Interface") + Button { // Not visible to model + id: modelVisibilityIndicator + visible: messageData?.role == 'interface' + implicitWidth: 16 + implicitHeight: 30 + Layout.alignment: Qt.AlignVCenter + + background: Item + + MaterialSymbol { + id: notVisibleToModelText + anchors.centerIn: parent + iconSize: Appearance.font.pixelSize.small + color: Appearance.colors.colSubtext + text: "visibility_off" + } + StyledToolTip { + text: Translation.tr("Not visible to model") } } - } - Button { // Not visible to model - id: modelVisibilityIndicator - visible: messageData?.role == 'interface' - implicitWidth: 16 - implicitHeight: 30 - Layout.alignment: Qt.AlignVCenter + ButtonGroup { + spacing: 5 - background: Item + AiMessageControlButton { + id: copyButton + buttonIcon: activated ? "inventory" : "content_copy" - MaterialSymbol { - id: notVisibleToModelText - anchors.centerIn: parent - iconSize: Appearance.font.pixelSize.small - color: Appearance.colors.colSubtext - text: "visibility_off" - } - StyledToolTip { - text: Translation.tr("Not visible to model") - } - } + onClicked: { + Quickshell.clipboardText = root.messageData?.content + copyButton.activated = true + copyIconTimer.restart() + } - ButtonGroup { - spacing: 5 - - AiMessageControlButton { - id: copyButton - buttonIcon: activated ? "inventory" : "content_copy" - - onClicked: { - Quickshell.clipboardText = root.messageData?.content - copyButton.activated = true - copyIconTimer.restart() - } - - Timer { - id: copyIconTimer - interval: 1500 - repeat: false - onTriggered: { - copyButton.activated = false + Timer { + id: copyIconTimer + interval: 1500 + repeat: false + onTriggered: { + copyButton.activated = false + } + } + + StyledToolTip { + text: Translation.tr("Copy") } } - - StyledToolTip { - text: Translation.tr("Copy") - } - } - AiMessageControlButton { - id: editButton - activated: root.editing - enabled: root.messageData?.done ?? false - buttonIcon: "edit" - onClicked: { - root.editing = !root.editing - if (!root.editing) { // Save changes - root.saveMessage() + AiMessageControlButton { + id: editButton + activated: root.editing + enabled: root.messageData?.done ?? false + buttonIcon: "edit" + onClicked: { + root.editing = !root.editing + if (!root.editing) { // Save changes + root.saveMessage() + } + } + StyledToolTip { + text: root.editing ? Translation.tr("Save") : Translation.tr("Edit") } } - StyledToolTip { - text: root.editing ? Translation.tr("Save") : Translation.tr("Edit") + AiMessageControlButton { + id: toggleMarkdownButton + activated: !root.renderMarkdown + buttonIcon: "code" + onClicked: { + root.renderMarkdown = !root.renderMarkdown + } + StyledToolTip { + text: Translation.tr("View Markdown source") + } } - } - AiMessageControlButton { - id: toggleMarkdownButton - activated: !root.renderMarkdown - buttonIcon: "code" - onClicked: { - root.renderMarkdown = !root.renderMarkdown - } - StyledToolTip { - text: Translation.tr("View Markdown source") - } - } - AiMessageControlButton { - id: deleteButton - buttonIcon: "close" - onClicked: { - Ai.removeMessage(root.messageIndex) - } - StyledToolTip { - text: Translation.tr("Delete") + AiMessageControlButton { + id: deleteButton + buttonIcon: "close" + onClicked: { + Ai.removeMessage(root.messageIndex) + } + StyledToolTip { + text: Translation.tr("Delete") + } } } } @@ -262,6 +271,8 @@ Rectangle { property bool thinking: root.messageData?.thinking ?? true property bool done: root.messageData?.done ?? false property bool completed: thisBlock.completed ?? false + + property bool forceDisableChunkSplitting: root.messageData.content.includes("```") source: thisBlock.type === "code" ? "MessageCodeBlock.qml" : thisBlock.type === "think" ? "MessageThinkBlock.qml" : diff --git a/.config/quickshell/ii/modules/sidebarLeft/aiChat/AiMessageControlButton.qml b/.config/quickshell/ii/modules/sidebarLeft/aiChat/AiMessageControlButton.qml index 64fc77239..2c8067f60 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/aiChat/AiMessageControlButton.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/aiChat/AiMessageControlButton.qml @@ -8,8 +8,9 @@ GroupButton { property string buttonIcon property bool activated: false toggled: activated - baseWidth: height + colBackgroundHover: Appearance.colors.colSecondaryContainerHover + colBackgroundActive: Appearance.colors.colSecondaryContainerActive contentItem: MaterialSymbol { horizontalAlignment: Text.AlignHCenter diff --git a/.config/quickshell/ii/modules/sidebarLeft/aiChat/MessageTextBlock.qml b/.config/quickshell/ii/modules/sidebarLeft/aiChat/MessageTextBlock.qml index d0d9d640d..a245b6979 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/aiChat/MessageTextBlock.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/aiChat/MessageTextBlock.qml @@ -8,6 +8,7 @@ import qs.modules.common.functions import QtQuick import QtQuick.Controls import QtQuick.Layouts +import Quickshell import Quickshell.Hyprland ColumnLayout { @@ -22,6 +23,9 @@ ColumnLayout { property list renderedLatexHashes: [] property string renderedSegmentContent: "" + property string shownText: "" + property bool forceDisableChunkSplitting: parent?.forceDisableChunkSplitting ?? false + property bool fadeChunkSplitting: !forceDisableChunkSplitting && !editing && !/\n\|/.test(shownText) && Config.options.sidebar.ai.textFadeIn Layout.fillWidth: true @@ -73,7 +77,7 @@ ColumnLayout { renderLatex() } else { // console.log("Editing mode enabled", segmentContent) - textArea.text = segmentContent + root.shownText = segmentContent } } @@ -88,7 +92,7 @@ ColumnLayout { onRenderedSegmentContentChanged: { // console.log("Rendered segment content changed: " + renderedSegmentContent); if (renderedSegmentContent) { - textArea.text = renderedSegmentContent; + root.shownText = renderedSegmentContent; } } @@ -104,39 +108,85 @@ ColumnLayout { } } - TextArea { - id: textArea - - Layout.fillWidth: true - readOnly: !editing - selectByMouse: enableMouseSelection || editing - renderType: Text.NativeRendering - font.family: Appearance.font.family.reading - font.hintingPreference: Font.PreferNoHinting // Prevent weird bold text - font.pixelSize: Appearance.font.pixelSize.small - selectedTextColor: Appearance.m3colors.m3onSecondaryContainer - selectionColor: Appearance.colors.colSecondaryContainer - wrapMode: TextEdit.Wrap - color: messageData.thinking ? Appearance.colors.colSubtext : Appearance.colors.colOnLayer1 - textFormat: renderMarkdown ? TextEdit.MarkdownText : TextEdit.PlainText - text: Translation.tr("Waiting for response...") - - onTextChanged: { - if (!root.editing) return - segmentContent = text + spacing: 0 + Repeater { + id: textLinesRepeater + property list textLineOpacities: [] + model: ScriptModel { + // Split by either double newlines or single newlines in a list + values: root.fadeChunkSplitting ? root.shownText.split(/\n\n(?= {0,2})|\n(?= {0,2}[-\*])/g).filter(line => line.trim() !== "") : [root.shownText] + onValuesChanged: { + while (textLinesRepeater.textLineOpacities.length < values.length) { + textLinesRepeater.textLineOpacities.push(root.messageData.done ? 1 : 0); + } + } } + delegate: TextArea { + id: textArea + required property int index + required property string modelData - onLinkActivated: (link) => { - Qt.openUrlExternally(link) - GlobalStates.sidebarLeftOpen = false - } + // Fade in animation + visible: opacity > 0 + opacity: fadeChunkSplitting ? (textLinesRepeater.textLineOpacities[index] ?? (root.messageData.done ? 1 : 0)) : 1 + Connections { + target: root.messageData + function onDoneChanged() { + if (root.messageData.done) { + textLinesRepeater.textLineOpacities[textArea.index] = 1 + } + } + } + Connections { + target: textLinesRepeater.model + function onValuesChanged() { + if (textLinesRepeater.model.values.length > textArea.index + 1) { + textLinesRepeater.textLineOpacities[textArea.index] = 1 + } + } + } + Behavior on opacity { + animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) + } - MouseArea { // Pointing hand for links - anchors.fill: parent - acceptedButtons: Qt.NoButton // Only for hover - hoverEnabled: true - cursorShape: parent.hoveredLink !== "" ? Qt.PointingHandCursor : - (enableMouseSelection || editing) ? Qt.IBeamCursor : Qt.ArrowCursor + Layout.fillWidth: true + readOnly: !editing + selectByMouse: enableMouseSelection || editing + renderType: Text.NativeRendering + font.family: Appearance.font.family.reading + font.hintingPreference: Font.PreferNoHinting // Prevent weird bold text + font.pixelSize: Appearance.font.pixelSize.small + selectedTextColor: Appearance.m3colors.m3onSecondaryContainer + selectionColor: Appearance.colors.colSecondaryContainer + wrapMode: TextEdit.Wrap + color: messageData.thinking ? Appearance.colors.colSubtext : Appearance.colors.colOnLayer1 + textFormat: renderMarkdown ? TextEdit.MarkdownText : TextEdit.PlainText + text: modelData + + onTextChanged: { + if (!root.editing) return + segmentContent = text + } + + onLinkActivated: (link) => { + Qt.openUrlExternally(link) + GlobalStates.sidebarLeftOpen = false + } + + MouseArea { // Pointing hand for links + anchors.fill: parent + acceptedButtons: Qt.NoButton // Only for hover + hoverEnabled: true + cursorShape: parent.hoveredLink !== "" ? Qt.PointingHandCursor : + (enableMouseSelection || editing) ? Qt.IBeamCursor : Qt.ArrowCursor + } + + // Rectangle { + // anchors.fill: parent + // color: "#22786378" + // border.width: 1 + // border.color: "#7E7E7E" + // } } } } diff --git a/.config/quickshell/ii/modules/sidebarRight/BottomWidgetGroup.qml b/.config/quickshell/ii/modules/sidebarRight/BottomWidgetGroup.qml index cd5385c75..a620c0cbb 100644 --- a/.config/quickshell/ii/modules/sidebarRight/BottomWidgetGroup.qml +++ b/.config/quickshell/ii/modules/sidebarRight/BottomWidgetGroup.qml @@ -83,7 +83,7 @@ Rectangle { Layout.margins: 10 Layout.rightMargin: 0 forceCircle: true - onClicked: { + downAction: () => { root.setCollapsed(false) } contentItem: MaterialSymbol { @@ -146,7 +146,7 @@ Rectangle { toggled: root.selectedTab == index buttonText: modelData.name buttonIcon: modelData.icon - onClicked: { + onPressed: { root.selectedTab = index Persistent.states.sidebar.bottomGroup.tab = index } @@ -158,7 +158,7 @@ Rectangle { anchors.left: parent.left anchors.top: parent.top forceCircle: true - onClicked: { + downAction: () => { root.setCollapsed(true) } contentItem: MaterialSymbol { diff --git a/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml b/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml index cdc861ce6..fcba76710 100644 --- a/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml +++ b/.config/quickshell/ii/modules/sidebarRight/SidebarRight.qml @@ -70,7 +70,6 @@ Scope { function toggle(): void { GlobalStates.sidebarRightOpen = !GlobalStates.sidebarRightOpen; - if(GlobalStates.sidebarRightOpen) Notifications.timeoutAll(); } function close(): void { @@ -79,7 +78,6 @@ Scope { function open(): void { GlobalStates.sidebarRightOpen = true; - Notifications.timeoutAll(); } } @@ -89,7 +87,6 @@ Scope { onPressed: { GlobalStates.sidebarRightOpen = !GlobalStates.sidebarRightOpen; - if(GlobalStates.sidebarRightOpen) Notifications.timeoutAll(); } } GlobalShortcut { @@ -98,7 +95,6 @@ Scope { onPressed: { GlobalStates.sidebarRightOpen = true; - Notifications.timeoutAll(); } } GlobalShortcut { diff --git a/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarWidget.qml b/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarWidget.qml index 3af804e3e..393407a92 100644 --- a/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarWidget.qml +++ b/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarWidget.qml @@ -50,7 +50,7 @@ Item { clip: true buttonText: `${monthShift != 0 ? "• " : ""}${viewingDate.toLocaleDateString(Qt.locale(), "MMMM yyyy")}` tooltipText: (monthShift === 0) ? "" : Translation.tr("Jump to current month") - onClicked: { + downAction: () => { monthShift = 0; } } @@ -60,7 +60,7 @@ Item { } CalendarHeaderButton { forceCircle: true - onClicked: { + downAction: () => { monthShift--; } contentItem: MaterialSymbol { @@ -72,7 +72,7 @@ Item { } CalendarHeaderButton { forceCircle: true - onClicked: { + downAction: () => { monthShift++; } contentItem: MaterialSymbol { diff --git a/.config/quickshell/ii/modules/sidebarRight/quickToggles/BluetoothToggle.qml b/.config/quickshell/ii/modules/sidebarRight/quickToggles/BluetoothToggle.qml index af8a5cfc8..8dc558eec 100644 --- a/.config/quickshell/ii/modules/sidebarRight/quickToggles/BluetoothToggle.qml +++ b/.config/quickshell/ii/modules/sidebarRight/quickToggles/BluetoothToggle.qml @@ -11,6 +11,7 @@ import Quickshell.Hyprland QuickToggleButton { id: root + visible: BluetoothStatus.available toggled: BluetoothStatus.enabled buttonIcon: BluetoothStatus.connected ? "bluetooth_connected" : BluetoothStatus.enabled ? "bluetooth" : "bluetooth_disabled" onClicked: { diff --git a/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixer.qml b/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixer.qml index 13bebf94b..1544bee39 100644 --- a/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixer.qml +++ b/.config/quickshell/ii/modules/sidebarRight/volumeMixer/VolumeMixer.qml @@ -109,12 +109,12 @@ Item { AudioDeviceSelectorButton { Layout.fillWidth: true input: false - onClicked: root.showDeviceSelectorDialog(input) + downAction: () => root.showDeviceSelectorDialog(input) } AudioDeviceSelectorButton { Layout.fillWidth: true input: true - onClicked: root.showDeviceSelectorDialog(input) + downAction: () => root.showDeviceSelectorDialog(input) } } } diff --git a/.config/quickshell/ii/modules/verticalBar/VerticalBarContent.qml b/.config/quickshell/ii/modules/verticalBar/VerticalBarContent.qml index 39dc14ba3..09c29b431 100644 --- a/.config/quickshell/ii/modules/verticalBar/VerticalBarContent.qml +++ b/.config/quickshell/ii/modules/verticalBar/VerticalBarContent.qml @@ -280,6 +280,7 @@ Item { // Bar content region color: rightSidebarButton.colText } MaterialSymbol { + visible: BluetoothStatus.available text: BluetoothStatus.connected ? "bluetooth_connected" : BluetoothStatus.enabled ? "bluetooth" : "bluetooth_disabled" iconSize: Appearance.font.pixelSize.larger color: rightSidebarButton.colText diff --git a/.config/quickshell/ii/services/BluetoothStatus.qml b/.config/quickshell/ii/services/BluetoothStatus.qml index 73978d634..e6815af78 100644 --- a/.config/quickshell/ii/services/BluetoothStatus.qml +++ b/.config/quickshell/ii/services/BluetoothStatus.qml @@ -12,6 +12,7 @@ import QtQuick Singleton { id: root + readonly property bool available: Bluetooth.adapters.values.length > 0 readonly property bool enabled: Bluetooth.defaultAdapter?.enabled ?? false readonly property BluetoothDevice firstActiveDevice: Bluetooth.defaultAdapter?.devices.values.find(device => device.connected) ?? null readonly property int activeDeviceCount: Bluetooth.defaultAdapter?.devices.values.filter(device => device.connected).length ?? 0 diff --git a/.config/quickshell/ii/services/MaterialThemeLoader.qml b/.config/quickshell/ii/services/MaterialThemeLoader.qml index cd85323e5..cd81ca07e 100644 --- a/.config/quickshell/ii/services/MaterialThemeLoader.qml +++ b/.config/quickshell/ii/services/MaterialThemeLoader.qml @@ -40,7 +40,7 @@ Singleton { id: resetFilePathNextWallpaperChange enabled: false target: Config.options.background - onWallpaperPathChanged: { + function onWallpaperPathChanged() { root.filePath = "" root.filePath = Directories.generatedMaterialThemePath resetFilePathNextWallpaperChange.enabled = false diff --git a/.config/quickshell/ii/services/Notifications.qml b/.config/quickshell/ii/services/Notifications.qml index 00a87c3a7..16d8b760f 100644 --- a/.config/quickshell/ii/services/Notifications.qml +++ b/.config/quickshell/ii/services/Notifications.qml @@ -69,6 +69,7 @@ Singleton { } property bool silent: false + property int unread: 0 property var filePath: Directories.notificationsPath property list list: [] property var popupList: list.filter((notif) => notif.popup); @@ -173,12 +174,17 @@ Singleton { } } + root.unread++; root.notify(newNotifObject); // console.log(notifToString(newNotifObject)); notifFileView.setText(stringifyList(root.list)); } } + function markAllRead() { + root.unread = 0; + } + function discardNotification(id) { console.log("[Notifications] Discarding notification with ID: " + id); const index = root.list.findIndex((notif) => notif.notificationId === id); diff --git a/.config/quickshell/ii/settings.qml b/.config/quickshell/ii/settings.qml index 64728412c..2b5978ec9 100644 --- a/.config/quickshell/ii/settings.qml +++ b/.config/quickshell/ii/settings.qml @@ -172,7 +172,7 @@ ApplicationWindow { iconText: "edit" buttonText: Translation.tr("Config file") expanded: navRail.expanded - onClicked: { + downAction: () => { Qt.openUrlExternally(`${Directories.config}/illogical-impulse/config.json`); } @@ -190,7 +190,7 @@ ApplicationWindow { required property var index required property var modelData toggled: root.currentPage === index - onClicked: root.currentPage = index; + onPressed: root.currentPage = index; expanded: navRail.expanded buttonIcon: modelData.icon buttonIconRotation: modelData.iconRotation || 0 diff --git a/dist-arch/install-deps.sh b/dist-arch/install-deps.sh index 487bb79ff..fabdb3cc1 100644 --- a/dist-arch/install-deps.sh +++ b/dist-arch/install-deps.sh @@ -63,7 +63,7 @@ install-local-pkgbuild() { x pushd $location source ./PKGBUILD - x yay -S $installflags --asdeps "${depends[@]}" + x yay -S --sudoloop $installflags --asdeps "${depends[@]}" x makepkg -Asi --noconfirm x popd