mirror of
https://github.com/end-4/dots-hyprland.git
synced 2026-06-06 07:19:27 -05:00
Merge branch 'end-4:main' into clean-testing
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import qs.modules.common
|
||||
import qs
|
||||
import qs.modules.common
|
||||
import qs.services
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Hyprland
|
||||
@@ -27,20 +28,10 @@ Singleton {
|
||||
property bool superReleaseMightTrigger: true
|
||||
property bool workspaceShowNumbers: false
|
||||
|
||||
Connections {
|
||||
target: Config
|
||||
function onReadyChanged() {
|
||||
if (Config.options.lock.launchOnStartup && Config.ready && Persistent.ready && Persistent.isNewHyprlandInstance) {
|
||||
GlobalStates.screenLocked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Connections {
|
||||
target: Persistent
|
||||
function onReadyChanged() {
|
||||
if (Config.options.lock.launchOnStartup && Config.ready && Persistent.ready && Persistent.isNewHyprlandInstance) {
|
||||
GlobalStates.screenLocked = true;
|
||||
}
|
||||
onSidebarRightOpenChanged: {
|
||||
if (GlobalStates.sidebarRightOpen) {
|
||||
Notifications.timeoutAll();
|
||||
Notifications.markAllRead();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ Scope {
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
onPressed: {
|
||||
popupLoader.active = false
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ ApplicationWindow {
|
||||
title: Translation.tr("Shell conflicts killer")
|
||||
|
||||
Component.onCompleted: {
|
||||
Config.ready // Just read to force init
|
||||
Config.readWriteDelay = 0;
|
||||
MaterialThemeLoader.reapplyTheme();
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import qs.modules.common.functions
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import Quickshell.Io
|
||||
|
||||
import "./dateIndicator"
|
||||
import "./minuteMarks"
|
||||
@@ -35,12 +36,60 @@ Item {
|
||||
implicitWidth: implicitSize
|
||||
implicitHeight: implicitSize
|
||||
|
||||
function applyStyle(sides, dialStyle, hourHandStyle, minuteHandStyle, secondHandStyle, dateStyle) {
|
||||
Config.options.background.clock.cookie.sides = sides
|
||||
Config.options.background.clock.cookie.dialNumberStyle = dialStyle
|
||||
Config.options.background.clock.cookie.hourHandStyle = hourHandStyle
|
||||
Config.options.background.clock.cookie.minuteHandStyle = minuteHandStyle
|
||||
Config.options.background.clock.cookie.secondHandStyle = secondHandStyle
|
||||
Config.options.background.clock.cookie.dateStyle = dateStyle
|
||||
}
|
||||
|
||||
function setClockPreset(category) {
|
||||
if (!Config.options.background.clock.cookie.aiStyling) return;
|
||||
if (category === "") return;
|
||||
print("[Cookie clock] Setting clock preset for category: " + category)
|
||||
// "abstract", "anime", "city", "minimalist", "landscape", "plants", "person", "space"
|
||||
if (category == "abstract") {
|
||||
applyStyle(10, "dots", "fill", "medium", "dot", "bubble")
|
||||
} else if (category == "anime") {
|
||||
applyStyle(12, "dots", "fill", "bold", "dot", "bubble")
|
||||
} else if (category == "city" || category == "space") {
|
||||
applyStyle(23, "full", "hollow", "medium", "classic", "bubble")
|
||||
} else if (category == "minimalist") {
|
||||
applyStyle(6, "none", "fill", "bold", "dot", "hide")
|
||||
} else if (category == "landscape") {
|
||||
applyStyle(14, "full", "hollow", "medium", "classic", "bubble")
|
||||
} else if (category == "plants") {
|
||||
applyStyle(9, "dots", "fill", "bold", "dot", "border")
|
||||
} else if (category == "person") {
|
||||
applyStyle(14, "full", "classic", "classic", "classic", "rect")
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Config
|
||||
function onReadyChanged() {
|
||||
categoryFileView.path = Directories.generatedWallpaperCategoryPath
|
||||
}
|
||||
}
|
||||
|
||||
FileView {
|
||||
id: categoryFileView
|
||||
path: ""
|
||||
watchChanges: true
|
||||
onFileChanged: reload()
|
||||
onLoaded: {
|
||||
root.setClockPreset(categoryFileView.text().trim())
|
||||
}
|
||||
}
|
||||
|
||||
DropShadow {
|
||||
source: cookie
|
||||
anchors.fill: source
|
||||
horizontalOffset: 0
|
||||
verticalOffset: 2
|
||||
radius: 12
|
||||
verticalOffset: 1
|
||||
radius: 8
|
||||
samples: radius * 2 + 1
|
||||
color: root.colShadow
|
||||
transparentBorder: true
|
||||
@@ -54,102 +103,102 @@ Item {
|
||||
sides: Config.options.background.clock.cookie.sides
|
||||
color: root.colBackground
|
||||
constantlyRotate: Config.options.background.clock.cookie.constantlyRotate
|
||||
}
|
||||
|
||||
// Hour/minutes numbers/dots/lines
|
||||
MinuteMarks {
|
||||
anchors.fill: parent
|
||||
color: root.colOnBackground
|
||||
}
|
||||
|
||||
// Stupid extra hour marks in the middle
|
||||
FadeLoader {
|
||||
id: hourMarksLoader
|
||||
anchors.centerIn: parent
|
||||
shown: Config.options.background.clock.cookie.hourMarks
|
||||
sourceComponent: HourMarks {
|
||||
implicitSize: 135 * (1.75 - 0.75 * hourMarksLoader.opacity)
|
||||
color: root.colOnBackground
|
||||
colOnBackground: ColorUtils.mix(root.colBackgroundInfo, root.colOnBackground, 0.5)
|
||||
}
|
||||
}
|
||||
|
||||
// Number column in the middle
|
||||
FadeLoader {
|
||||
id: timeColumnLoader
|
||||
anchors.centerIn: parent
|
||||
shown: Config.options.background.clock.cookie.timeIndicators
|
||||
scale: 1.4 - 0.4 * timeColumnLoader.shown
|
||||
Behavior on scale {
|
||||
animation: Appearance.animation.elementResize.numberAnimation.createObject(this)
|
||||
}
|
||||
|
||||
sourceComponent: TimeColumn {
|
||||
color: root.colBackgroundInfo
|
||||
}
|
||||
}
|
||||
|
||||
// Hour hand
|
||||
FadeLoader {
|
||||
anchors.fill: parent
|
||||
z: 1
|
||||
shown: Config.options.background.clock.cookie.hourHandStyle !== "hide"
|
||||
sourceComponent: HourHand {
|
||||
clockHour: root.clockHour
|
||||
clockMinute: root.clockMinute
|
||||
style: Config.options.background.clock.cookie.hourHandStyle
|
||||
color: root.colHourHand
|
||||
}
|
||||
}
|
||||
|
||||
// Minute hand
|
||||
FadeLoader {
|
||||
anchors.fill: parent
|
||||
z: 2
|
||||
shown: Config.options.background.clock.cookie.minuteHandStyle !== "hide"
|
||||
sourceComponent: MinuteHand {
|
||||
|
||||
// Hour/minutes numbers/dots/lines
|
||||
MinuteMarks {
|
||||
anchors.fill: parent
|
||||
clockMinute: root.clockMinute
|
||||
style: Config.options.background.clock.cookie.minuteHandStyle
|
||||
color: root.colMinuteHand
|
||||
color: root.colOnBackground
|
||||
}
|
||||
}
|
||||
|
||||
// Second hand
|
||||
FadeLoader {
|
||||
id: secondHandLoader
|
||||
z: (Config.options.background.clock.cookie.secondHandStyle === "line") ? 2 : 3
|
||||
shown: Config.options.time.secondPrecision && Config.options.background.clock.cookie.secondHandStyle !== "hide"
|
||||
anchors.fill: parent
|
||||
sourceComponent: SecondHand {
|
||||
id: secondHand
|
||||
clockSecond: root.clockSecond
|
||||
style: Config.options.background.clock.cookie.secondHandStyle
|
||||
color: root.colSecondHand
|
||||
// Stupid extra hour marks in the middle
|
||||
FadeLoader {
|
||||
id: hourMarksLoader
|
||||
anchors.centerIn: parent
|
||||
shown: Config.options.background.clock.cookie.hourMarks
|
||||
sourceComponent: HourMarks {
|
||||
implicitSize: 135 * (1.75 - 0.75 * hourMarksLoader.opacity)
|
||||
color: root.colOnBackground
|
||||
colOnBackground: ColorUtils.mix(root.colBackgroundInfo, root.colOnBackground, 0.5)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Center dot
|
||||
FadeLoader {
|
||||
z: 4
|
||||
anchors.centerIn: parent
|
||||
shown: Config.options.background.clock.cookie.minuteHandStyle !== "bold"
|
||||
sourceComponent: Rectangle {
|
||||
color: Config.options.background.clock.cookie.minuteHandStyle === "medium" ? root.colBackground : root.colMinuteHand
|
||||
implicitWidth: 6
|
||||
implicitHeight: implicitWidth
|
||||
radius: width / 2
|
||||
// Number column in the middle
|
||||
FadeLoader {
|
||||
id: timeColumnLoader
|
||||
anchors.centerIn: parent
|
||||
shown: Config.options.background.clock.cookie.timeIndicators
|
||||
scale: 1.4 - 0.4 * timeColumnLoader.shown
|
||||
Behavior on scale {
|
||||
animation: Appearance.animation.elementResize.numberAnimation.createObject(this)
|
||||
}
|
||||
|
||||
sourceComponent: TimeColumn {
|
||||
color: root.colBackgroundInfo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Date
|
||||
FadeLoader {
|
||||
anchors.fill: parent
|
||||
shown: Config.options.background.clock.cookie.dateStyle !== "hide"
|
||||
// Hour hand
|
||||
FadeLoader {
|
||||
anchors.fill: parent
|
||||
z: 1
|
||||
shown: Config.options.background.clock.cookie.hourHandStyle !== "hide"
|
||||
sourceComponent: HourHand {
|
||||
clockHour: root.clockHour
|
||||
clockMinute: root.clockMinute
|
||||
style: Config.options.background.clock.cookie.hourHandStyle
|
||||
color: root.colHourHand
|
||||
}
|
||||
}
|
||||
|
||||
sourceComponent: DateIndicator {
|
||||
color: root.colBackgroundInfo
|
||||
style: Config.options.background.clock.cookie.dateStyle
|
||||
// Minute hand
|
||||
FadeLoader {
|
||||
anchors.fill: parent
|
||||
z: 2
|
||||
shown: Config.options.background.clock.cookie.minuteHandStyle !== "hide"
|
||||
sourceComponent: MinuteHand {
|
||||
anchors.fill: parent
|
||||
clockMinute: root.clockMinute
|
||||
style: Config.options.background.clock.cookie.minuteHandStyle
|
||||
color: root.colMinuteHand
|
||||
}
|
||||
}
|
||||
|
||||
// Second hand
|
||||
FadeLoader {
|
||||
id: secondHandLoader
|
||||
z: (Config.options.background.clock.cookie.secondHandStyle === "line") ? 2 : 3
|
||||
shown: Config.options.time.secondPrecision && Config.options.background.clock.cookie.secondHandStyle !== "hide"
|
||||
anchors.fill: parent
|
||||
sourceComponent: SecondHand {
|
||||
id: secondHand
|
||||
clockSecond: root.clockSecond
|
||||
style: Config.options.background.clock.cookie.secondHandStyle
|
||||
color: root.colSecondHand
|
||||
}
|
||||
}
|
||||
|
||||
// Center dot
|
||||
FadeLoader {
|
||||
z: 4
|
||||
anchors.centerIn: parent
|
||||
shown: Config.options.background.clock.cookie.minuteHandStyle !== "bold"
|
||||
sourceComponent: Rectangle {
|
||||
color: Config.options.background.clock.cookie.minuteHandStyle === "medium" ? root.colBackground : root.colMinuteHand
|
||||
implicitWidth: 6
|
||||
implicitHeight: implicitWidth
|
||||
radius: width / 2
|
||||
}
|
||||
}
|
||||
|
||||
// Date
|
||||
FadeLoader {
|
||||
anchors.fill: parent
|
||||
shown: Config.options.background.clock.cookie.dateStyle !== "hide"
|
||||
|
||||
sourceComponent: DateIndicator {
|
||||
color: root.colBackgroundInfo
|
||||
style: Config.options.background.clock.cookie.dateStyle
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -7,27 +7,31 @@ import qs.modules.common.widgets
|
||||
import QtQuick
|
||||
|
||||
Item {
|
||||
property int bubbleIndex: 0
|
||||
property bool isMonth: false
|
||||
property real targetSize: 0
|
||||
property alias text: bubbleText.text
|
||||
|
||||
text: Qt.locale().toString(DateTime.clock.date, isMonth ? "MM" : "d")
|
||||
|
||||
MaterialCookie {
|
||||
z: 5
|
||||
sides: bubbleIndex === 0 ? 4 : 1
|
||||
sides: isMonth ? 1 : 4
|
||||
anchors.centerIn: parent
|
||||
color: bubbleIndex === 0.0 ? Appearance.colors.colTertiaryContainer : Appearance.colors.colPrimaryContainer
|
||||
color: isMonth ? Appearance.colors.colPrimaryContainer : Appearance.colors.colTertiaryContainer
|
||||
implicitSize: targetSize
|
||||
constantlyRotate: Config.options.background.clock.cookie.constantlyRotate
|
||||
}
|
||||
|
||||
StyledText {
|
||||
id: bubbleText
|
||||
z: 6
|
||||
anchors.centerIn: parent
|
||||
text: bubbleIndex === 0.0 ? DateTime.date.substring(5, 7) : DateTime.date.substring(8, 10)
|
||||
color: bubbleIndex === 0.0 ? Appearance.colors.colTertiary : Appearance.colors.colPrimary
|
||||
opacity: root.style === "bubble" ? 1.0 : 0
|
||||
color: isMonth ? Appearance.colors.colPrimary : Appearance.colors.colTertiary
|
||||
opacity: root.style === "bubble" ? 1 : 0
|
||||
font {
|
||||
family: Appearance.font.family.expressive
|
||||
pixelSize: 30
|
||||
weight: 1000
|
||||
weight: Font.Black
|
||||
}
|
||||
Behavior on opacity {
|
||||
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
|
||||
|
||||
+2
-2
@@ -53,7 +53,7 @@ Item {
|
||||
sourceComponent: BubbleDate {
|
||||
implicitWidth: dayBubbleLoader.targetSize
|
||||
implicitHeight: dayBubbleLoader.targetSize
|
||||
bubbleIndex: 0
|
||||
isMonth: false
|
||||
targetSize: dayBubbleLoader.targetSize
|
||||
}
|
||||
}
|
||||
@@ -71,7 +71,7 @@ Item {
|
||||
sourceComponent: BubbleDate {
|
||||
implicitWidth: monthBubbleLoader.targetSize
|
||||
implicitHeight: monthBubbleLoader.targetSize
|
||||
bubbleIndex: 1
|
||||
isMonth: true
|
||||
targetSize: monthBubbleLoader.targetSize
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,6 +295,19 @@ 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 ? notificationUnreadCount.implicitHeight : 0
|
||||
implicitWidth: reveal ? notificationUnreadCount.implicitWidth : 0
|
||||
Behavior on Layout.rightMargin {
|
||||
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
|
||||
}
|
||||
NotificationUnreadCount {
|
||||
id: notificationUnreadCount
|
||||
}
|
||||
}
|
||||
MaterialSymbol {
|
||||
Layout.rightMargin: indicatorsRowLayout.realSpacing
|
||||
text: Network.materialSymbol
|
||||
@@ -302,6 +315,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
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import QtQuick
|
||||
import qs
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
|
||||
MaterialSymbol {
|
||||
id: root
|
||||
readonly property bool showUnreadCount: Config.options.bar.indicators.notifications.showUnreadCount
|
||||
text: Notifications.silent ? "notifications_paused" : "notifications"
|
||||
iconSize: Appearance.font.pixelSize.larger
|
||||
color: rightSidebarButton.colText
|
||||
|
||||
Rectangle {
|
||||
id: notifPing
|
||||
visible: !Notifications.silent && Notifications.unread > 0
|
||||
anchors {
|
||||
right: parent.right
|
||||
top: parent.top
|
||||
rightMargin: root.showUnreadCount ? 0 : 1
|
||||
topMargin: root.showUnreadCount ? 0 : 3
|
||||
}
|
||||
radius: Appearance.rounding.full
|
||||
color: Appearance.colors.colOnLayer0
|
||||
z: 1
|
||||
|
||||
implicitHeight: root.showUnreadCount ? Math.max(notificationCounterText.implicitWidth, notificationCounterText.implicitHeight) : 8
|
||||
implicitWidth: implicitHeight
|
||||
|
||||
StyledText {
|
||||
id: notificationCounterText
|
||||
visible: root.showUnreadCount
|
||||
anchors.centerIn: parent
|
||||
font.pixelSize: Appearance.font.pixelSize.smallest
|
||||
color: Appearance.colors.colLayer0
|
||||
text: Notifications.unread
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -15,7 +15,7 @@ MouseArea {
|
||||
|
||||
hoverEnabled: true
|
||||
|
||||
onClicked: {
|
||||
onPressed: {
|
||||
Weather.getData();
|
||||
Quickshell.execDetached(["notify-send",
|
||||
Translation.tr("Weather"),
|
||||
|
||||
@@ -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<real> bezierCurve: animationCurves.emphasized
|
||||
property int velocity: 650
|
||||
|
||||
@@ -9,6 +9,7 @@ Singleton {
|
||||
property string filePath: Directories.shellConfigPath
|
||||
property alias options: configOptionsJsonAdapter
|
||||
property bool ready: false
|
||||
property int readWriteDelay: 50 // milliseconds
|
||||
|
||||
function setNestedValue(nestedKey, value) {
|
||||
let keys = nestedKey.split(".");
|
||||
@@ -40,11 +41,30 @@ Singleton {
|
||||
obj[keys[keys.length - 1]] = convertedValue;
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: fileReloadTimer
|
||||
interval: root.readWriteDelay
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
configFileView.reload()
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: fileWriteTimer
|
||||
interval: root.readWriteDelay
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
configFileView.writeAdapter()
|
||||
}
|
||||
}
|
||||
|
||||
FileView {
|
||||
id: configFileView
|
||||
path: root.filePath
|
||||
watchChanges: true
|
||||
onFileChanged: reload()
|
||||
onAdapterUpdated: writeAdapter()
|
||||
onFileChanged: fileReloadTimer.restart()
|
||||
onAdapterUpdated: fileWriteTimer.restart()
|
||||
onLoaded: root.ready = true
|
||||
onLoadFailed: error => {
|
||||
if (error == FileViewError.FileNotFound) {
|
||||
@@ -130,14 +150,15 @@ Singleton {
|
||||
property string style: "cookie" // Options: "cookie", "digital"
|
||||
property real scale: 1
|
||||
property JsonObject cookie: JsonObject {
|
||||
property bool aiStyling: false
|
||||
property int sides: 14
|
||||
property string dialNumberStyle: "full" // Options: "dots" , "numbers", "full" , "none"
|
||||
property string hourHandStyle: "fill" // Options: "classic", "fill", "hollow", "hide"
|
||||
property string minuteHandStyle: "medium" // Options "classic", "thin", "medium", "bold", "hide"
|
||||
property string secondHandStyle: "dot" // Options: "dot", "line" , "hide"
|
||||
property string secondHandStyle: "dot" // Options: "dot", "line", "classic", "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 +233,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 {
|
||||
@@ -274,6 +300,7 @@ Singleton {
|
||||
}
|
||||
|
||||
property JsonObject lock: JsonObject {
|
||||
property bool useHyprlock: false
|
||||
property bool launchOnStartup: false
|
||||
property JsonObject blur: JsonObject {
|
||||
property bool enable: false
|
||||
@@ -341,8 +368,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"
|
||||
@@ -401,7 +432,7 @@ Singleton {
|
||||
}
|
||||
property JsonObject triggerCondition: JsonObject {
|
||||
property list<string> networkNameKeywords: ["airport", "cafe", "college", "company", "eduroam", "free", "guest", "public", "school", "university"]
|
||||
property list<string> fileKeywords: ["anime", "ecchi", "hentai", "yande.re", "konachan", "breast", "nipples", "pussy", "nsfw", "spoiler", "girl"]
|
||||
property list<string> fileKeywords: ["anime", "booru", "ecchi", "hentai", "yande.re", "konachan", "breast", "nipples", "pussy", "nsfw", "spoiler", "girl"]
|
||||
property list<string> linkKeywords: ["hentai", "porn", "sukebei", "hitomi.la", "rule34", "gelbooru", "fanbox", "dlsite"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ Singleton {
|
||||
property string todoPath: FileUtils.trimFileProtocol(`${Directories.state}/user/todo.json`)
|
||||
property string notificationsPath: FileUtils.trimFileProtocol(`${Directories.cache}/notifications/notifications.json`)
|
||||
property string generatedMaterialThemePath: FileUtils.trimFileProtocol(`${Directories.state}/user/generated/colors.json`)
|
||||
property string generatedWallpaperCategoryPath: FileUtils.trimFileProtocol(`${Directories.state}/user/generated/wallpaper/category.txt`)
|
||||
property string cliphistDecode: FileUtils.trimFileProtocol(`/tmp/quickshell/media/cliphist`)
|
||||
property string screenshotTemp: "/tmp/quickshell/media/screenshot"
|
||||
property string wallpaperSwitchScriptPath: FileUtils.trimFileProtocol(`${Directories.scriptPath}/colors/switchwall.sh`)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -23,6 +23,7 @@ ColumnLayout {
|
||||
text: root.title
|
||||
font.pixelSize: Appearance.font.pixelSize.larger
|
||||
font.weight: Font.Medium
|
||||
color: Appearance.colors.colOnSecondaryContainer
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
@@ -9,7 +9,7 @@ RippleButton {
|
||||
implicitWidth: 40
|
||||
implicitHeight: 40
|
||||
Layout.leftMargin: 8
|
||||
onClicked: {
|
||||
downAction: () => {
|
||||
parent.expanded = !parent.expanded;
|
||||
}
|
||||
buttonRadius: Appearance.rounding.full
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,6 +112,10 @@ Scope {
|
||||
description: "Locks the screen"
|
||||
|
||||
onPressed: {
|
||||
if (Config.options.lock.useHyprlock) {
|
||||
Quickshell.execDetached(["hyprlock"])
|
||||
return;
|
||||
}
|
||||
GlobalStates.screenLocked = true;
|
||||
}
|
||||
}
|
||||
@@ -125,4 +129,23 @@ Scope {
|
||||
lockContext.shouldReFocus();
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Config
|
||||
function onReadyChanged() {
|
||||
print("lock after config")
|
||||
if (Config.options.lock.launchOnStartup && Config.ready && Persistent.ready && Persistent.isNewHyprlandInstance) {
|
||||
Hyprland.dispatch("global quickshell:lock")
|
||||
}
|
||||
}
|
||||
}
|
||||
Connections {
|
||||
target: Persistent
|
||||
function onReadyChanged() {
|
||||
print("lock after persistent")
|
||||
if (Config.options.lock.launchOnStartup && Config.ready && Persistent.ready && Persistent.isNewHyprlandInstance) {
|
||||
Hyprland.dispatch("global quickshell:lock")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}`)
|
||||
|
||||
@@ -7,6 +7,19 @@ import qs.modules.common.widgets
|
||||
|
||||
ContentPage {
|
||||
forceWidth: true
|
||||
|
||||
ContentSection {
|
||||
icon: "notifications"
|
||||
title: Translation.tr("Notifications")
|
||||
ConfigSwitch {
|
||||
buttonIcon: "counter_2"
|
||||
text: Translation.tr("Unread indicator: show count")
|
||||
checked: Config.options.bar.indicators.notifications.showUnreadCount
|
||||
onCheckedChanged: {
|
||||
Config.options.bar.indicators.notifications.showUnreadCount = checked;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContentSection {
|
||||
icon: "spoke"
|
||||
@@ -130,57 +143,24 @@ ContentPage {
|
||||
}
|
||||
|
||||
ContentSection {
|
||||
icon: "workspaces"
|
||||
title: Translation.tr("Workspaces")
|
||||
icon: "shelf_auto_hide"
|
||||
title: Translation.tr("Tray")
|
||||
|
||||
ConfigSwitch {
|
||||
buttonIcon: "counter_1"
|
||||
text: Translation.tr('Always show numbers')
|
||||
checked: Config.options.bar.workspaces.alwaysShowNumbers
|
||||
buttonIcon: "keep"
|
||||
text: Translation.tr('Make icons pinned by default')
|
||||
checked: Config.options.bar.tray.invertPinnedItems
|
||||
onCheckedChanged: {
|
||||
Config.options.bar.workspaces.alwaysShowNumbers = checked;
|
||||
Config.options.bar.tray.invertPinnedItems = checked;
|
||||
}
|
||||
}
|
||||
|
||||
ConfigSwitch {
|
||||
buttonIcon: "award_star"
|
||||
text: Translation.tr('Show app icons')
|
||||
checked: Config.options.bar.workspaces.showAppIcons
|
||||
onCheckedChanged: {
|
||||
Config.options.bar.workspaces.showAppIcons = checked;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ConfigSwitch {
|
||||
buttonIcon: "colors"
|
||||
text: Translation.tr('Tint app icons')
|
||||
checked: Config.options.bar.workspaces.monochromeIcons
|
||||
text: Translation.tr('Tint icons')
|
||||
checked: Config.options.bar.tray.monochromeIcons
|
||||
onCheckedChanged: {
|
||||
Config.options.bar.workspaces.monochromeIcons = checked;
|
||||
}
|
||||
}
|
||||
|
||||
ConfigSpinBox {
|
||||
icon: "view_column"
|
||||
text: Translation.tr("Workspaces shown")
|
||||
value: Config.options.bar.workspaces.shown
|
||||
from: 1
|
||||
to: 30
|
||||
stepSize: 1
|
||||
onValueChanged: {
|
||||
Config.options.bar.workspaces.shown = value;
|
||||
}
|
||||
}
|
||||
|
||||
ConfigSpinBox {
|
||||
icon: "touch_long"
|
||||
text: Translation.tr("Number show delay when pressing Super (ms)")
|
||||
value: Config.options.bar.workspaces.showNumberDelay
|
||||
from: 0
|
||||
to: 1000
|
||||
stepSize: 50
|
||||
onValueChanged: {
|
||||
Config.options.bar.workspaces.showNumberDelay = value;
|
||||
Config.options.bar.tray.monochromeIcons = checked;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -248,29 +228,6 @@ ContentPage {
|
||||
}
|
||||
}
|
||||
|
||||
ContentSection {
|
||||
icon: "shelf_auto_hide"
|
||||
title: Translation.tr("Tray")
|
||||
|
||||
ConfigSwitch {
|
||||
buttonIcon: "keep"
|
||||
text: Translation.tr('Make icons pinned by default')
|
||||
checked: Config.options.bar.tray.invertPinnedItems
|
||||
onCheckedChanged: {
|
||||
Config.options.bar.tray.invertPinnedItems = checked;
|
||||
}
|
||||
}
|
||||
|
||||
ConfigSwitch {
|
||||
buttonIcon: "colors"
|
||||
text: Translation.tr('Tint icons')
|
||||
checked: Config.options.bar.tray.monochromeIcons
|
||||
onCheckedChanged: {
|
||||
Config.options.bar.tray.monochromeIcons = checked;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContentSection {
|
||||
icon: "cloud"
|
||||
title: Translation.tr("Weather")
|
||||
@@ -283,4 +240,60 @@ ContentPage {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContentSection {
|
||||
icon: "workspaces"
|
||||
title: Translation.tr("Workspaces")
|
||||
|
||||
ConfigSwitch {
|
||||
buttonIcon: "counter_1"
|
||||
text: Translation.tr('Always show numbers')
|
||||
checked: Config.options.bar.workspaces.alwaysShowNumbers
|
||||
onCheckedChanged: {
|
||||
Config.options.bar.workspaces.alwaysShowNumbers = checked;
|
||||
}
|
||||
}
|
||||
|
||||
ConfigSwitch {
|
||||
buttonIcon: "award_star"
|
||||
text: Translation.tr('Show app icons')
|
||||
checked: Config.options.bar.workspaces.showAppIcons
|
||||
onCheckedChanged: {
|
||||
Config.options.bar.workspaces.showAppIcons = checked;
|
||||
}
|
||||
}
|
||||
|
||||
ConfigSwitch {
|
||||
buttonIcon: "colors"
|
||||
text: Translation.tr('Tint app icons')
|
||||
checked: Config.options.bar.workspaces.monochromeIcons
|
||||
onCheckedChanged: {
|
||||
Config.options.bar.workspaces.monochromeIcons = checked;
|
||||
}
|
||||
}
|
||||
|
||||
ConfigSpinBox {
|
||||
icon: "view_column"
|
||||
text: Translation.tr("Workspaces shown")
|
||||
value: Config.options.bar.workspaces.shown
|
||||
from: 1
|
||||
to: 30
|
||||
stepSize: 1
|
||||
onValueChanged: {
|
||||
Config.options.bar.workspaces.shown = value;
|
||||
}
|
||||
}
|
||||
|
||||
ConfigSpinBox {
|
||||
icon: "touch_long"
|
||||
text: Translation.tr("Number show delay when pressing Super (ms)")
|
||||
value: Config.options.bar.workspaces.showNumberDelay
|
||||
from: 0
|
||||
to: 1000
|
||||
stepSize: 50
|
||||
onValueChanged: {
|
||||
Config.options.bar.workspaces.showNumberDelay = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,13 +59,25 @@ ContentPage {
|
||||
ContentSubsection {
|
||||
visible: Config.options.background.clock.style === "cookie"
|
||||
title: Translation.tr("Cookie clock settings")
|
||||
|
||||
ConfigSwitch {
|
||||
buttonIcon: "wand_stars"
|
||||
text: Translation.tr("Auto styling with Gemini")
|
||||
checked: Config.options.background.clock.cookie.aiStyling
|
||||
onCheckedChanged: {
|
||||
Config.options.background.clock.cookie.aiStyling = checked;
|
||||
}
|
||||
StyledToolTip {
|
||||
text: Translation.tr("Uses Gemini to categorize the wallpaper then picks a preset based on it.\nYou'll need to set Gemini API key on the left sidebar first.\nImages are downscaled for performance, but just to be safe,\ndo not select wallpapers with sensitive information.")
|
||||
}
|
||||
}
|
||||
|
||||
ConfigSpinBox {
|
||||
visible: Config.options.background.clock.style === "cookie"
|
||||
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;
|
||||
@@ -73,7 +85,6 @@ ContentPage {
|
||||
}
|
||||
|
||||
ConfigSwitch {
|
||||
visible: Config.options.background.clock.style === "cookie"
|
||||
buttonIcon: "autoplay"
|
||||
text: Translation.tr("Constantly rotate")
|
||||
checked: Config.options.background.clock.cookie.constantlyRotate
|
||||
@@ -86,7 +97,6 @@ ContentPage {
|
||||
}
|
||||
|
||||
ConfigRow {
|
||||
visible: Config.options.background.clock.style === "cookie"
|
||||
|
||||
ConfigSwitch {
|
||||
enabled: Config.options.background.clock.style === "cookie" && Config.options.background.clock.cookie.dialNumberStyle === "dots" || Config.options.background.clock.cookie.dialNumberStyle === "full"
|
||||
@@ -452,6 +462,18 @@ ContentPage {
|
||||
icon: "lock"
|
||||
title: Translation.tr("Lock screen")
|
||||
|
||||
ConfigSwitch {
|
||||
buttonIcon: "water_drop"
|
||||
text: Translation.tr('Use Hyprlock (instead of Quickshell)')
|
||||
checked: Config.options.lock.useHyprlock
|
||||
onCheckedChanged: {
|
||||
Config.options.lock.useHyprlock = checked;
|
||||
}
|
||||
StyledToolTip {
|
||||
text: Translation.tr("If you want to somehow use fingerprint unlock...")
|
||||
}
|
||||
}
|
||||
|
||||
ConfigSwitch {
|
||||
buttonIcon: "account_circle"
|
||||
text: Translation.tr('Launch on startup')
|
||||
@@ -569,6 +591,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")
|
||||
|
||||
@@ -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\\)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
@@ -514,24 +513,22 @@ Item {
|
||||
text: "•"
|
||||
}
|
||||
|
||||
Item { // NSFW toggle
|
||||
MouseArea { // NSFW toggle
|
||||
visible: width > 0
|
||||
implicitWidth: switchesRow.implicitWidth
|
||||
Layout.fillHeight: true
|
||||
|
||||
hoverEnabled: true
|
||||
PointingHandInteraction {}
|
||||
onPressed: {
|
||||
nsfwSwitch.checked = !nsfwSwitch.checked
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: switchesRow
|
||||
spacing: 5
|
||||
anchors.centerIn: parent
|
||||
|
||||
MouseArea {
|
||||
hoverEnabled: true
|
||||
PointingHandInteraction {}
|
||||
onClicked: {
|
||||
nsfwSwitch.checked = !nsfwSwitch.checked
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
Layout.fillHeight: true
|
||||
Layout.leftMargin: 10
|
||||
@@ -552,6 +549,7 @@ Item {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Item { Layout.fillWidth: true }
|
||||
@@ -566,8 +564,8 @@ Item {
|
||||
buttonText: commandRepresentation
|
||||
colBackground: Appearance.colors.colLayer2
|
||||
|
||||
onClicked: {
|
||||
if(modelData.sendDirectly) {
|
||||
downAction: () => {
|
||||
if (modelData.sendDirectly) {
|
||||
root.handleInput(commandRepresentation)
|
||||
} else {
|
||||
tagInputField.text = commandRepresentation + " "
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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()] : [])
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -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" :
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<string> 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<real> 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"
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -10,7 +10,7 @@ import Quickshell.Io
|
||||
import Quickshell.Hyprland
|
||||
|
||||
QuickToggleButton {
|
||||
toggled: Network.wifiEnabled
|
||||
toggled: Network.wifiStatus !== "disabled"
|
||||
buttonIcon: Network.materialSymbol
|
||||
onClicked: Network.toggleWifi()
|
||||
altAction: () => {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,6 +273,20 @@ Item { // Bar content region
|
||||
Layout.bottomMargin: indicatorsColumnLayout.realSpacing
|
||||
color: rightSidebarButton.colText
|
||||
}
|
||||
Revealer {
|
||||
vertical: true
|
||||
reveal: Notifications.silent || Notifications.unread > 0
|
||||
Layout.fillWidth: true
|
||||
Layout.bottomMargin: reveal ? indicatorsColumnLayout.realSpacing : 0
|
||||
implicitHeight: reveal ? notificationUnreadCount.implicitHeight : 0
|
||||
implicitWidth: reveal ? notificationUnreadCount.implicitWidth : 0
|
||||
Behavior on Layout.bottomMargin {
|
||||
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
|
||||
}
|
||||
Bar.NotificationUnreadCount {
|
||||
id: notificationUnreadCount
|
||||
}
|
||||
}
|
||||
MaterialSymbol {
|
||||
Layout.bottomMargin: indicatorsColumnLayout.realSpacing
|
||||
text: Network.materialSymbol
|
||||
@@ -280,6 +294,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
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if [[ -z "$1" ]]; then
|
||||
echo "Usage: $0 <image_path>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SOURCE_IMG_PATH="$1"
|
||||
WALLPAPER_NAME="$(basename "$SOURCE_IMG_PATH")"
|
||||
RESIZED_IMG_PATH="/tmp/quickshell/ai/wallpaper.jpg"
|
||||
magick "$SOURCE_IMG_PATH" -resize 200x -quality 50 "$RESIZED_IMG_PATH"
|
||||
API_KEY=$(secret-tool lookup 'application' 'illogical-impulse' | jq -r '.apiKeys.gemini')
|
||||
|
||||
if [[ "$(base64 --version 2>&1)" = *"FreeBSD"* ]]; then
|
||||
B64FLAGS="--input"
|
||||
else
|
||||
B64FLAGS="-w0"
|
||||
fi
|
||||
|
||||
payload='{
|
||||
"contents": [{
|
||||
"parts":[
|
||||
{
|
||||
"inline_data": {
|
||||
"mime_type":"image/jpeg",
|
||||
"data": "'"$(base64 $B64FLAGS $RESIZED_IMG_PATH)"'"
|
||||
}
|
||||
},
|
||||
{"text": "Categorize the wallpaper. Its file name is '"$WALLPAPER_NAME"'"}
|
||||
]
|
||||
}],
|
||||
"generationConfig": {
|
||||
"responseMimeType": "text/x.enum",
|
||||
"responseSchema": {
|
||||
"type": "string",
|
||||
"enum": [ "abstract", "anime", "city", "minimalist", "landscape", "plants", "person", "space" ]
|
||||
},
|
||||
"temperature": 0,
|
||||
}
|
||||
}'
|
||||
# echo "$payload" | jq
|
||||
response=$(curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent" \
|
||||
-H "x-goog-api-key: $API_KEY" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-X POST \
|
||||
-d "$payload" 2> /dev/null)
|
||||
|
||||
echo "$response" | jq -r '.candidates[0].content.parts[0].text'
|
||||
@@ -171,6 +171,13 @@ switch() {
|
||||
type_flag="$3"
|
||||
color_flag="$4"
|
||||
color="$5"
|
||||
|
||||
# Start Gemini auto-categorization if enabled
|
||||
aiStylingEnabled=$(jq -r '.background.clock.cookie.aiStyling' "$SHELL_CONFIG_FILE")
|
||||
if [[ "$aiStylingEnabled" == "true" ]]; then
|
||||
"$SCRIPT_DIR/../ai/gemini-categorize-wallpaper.sh" "$imgpath" > "$STATE_DIR/user/generated/wallpaper/category.txt" &
|
||||
fi
|
||||
|
||||
read scale screenx screeny screensizey < <(hyprctl monitors -j | jq '.[] | select(.focused) | .scale, .x, .y, .height' | xargs)
|
||||
cursorposx=$(hyprctl cursorpos -j | jq '.x' 2>/dev/null) || cursorposx=960
|
||||
cursorposx=$(bc <<< "scale=0; ($cursorposx - $screenx) * $scale / 1")
|
||||
|
||||
@@ -294,7 +294,8 @@ def get_dominant_color(image_path, x, y, w, h, screen_width=None, screen_height=
|
||||
_, labels, centers = cv2.kmeans(region, K, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
|
||||
counts = np.bincount(labels.flatten())
|
||||
dominant = centers[np.argmax(counts)]
|
||||
return [int(x) for x in dominant]
|
||||
# Reverse from BGR to RGB
|
||||
return [int(x) for x in reversed(dominant)]
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Find least busy region in an image and output a JSON. Made for determining a suitable position for a wallpaper widget.")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -21,6 +21,9 @@ Singleton {
|
||||
entry: a
|
||||
}))
|
||||
function fuzzyQuery(search: string): var {
|
||||
if (search.trim() === "") {
|
||||
return entries;
|
||||
}
|
||||
if (root.sloppySearch) {
|
||||
const results = entries.slice(0, 100).map(str => ({
|
||||
entry: str,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -16,24 +16,35 @@ Singleton {
|
||||
|
||||
property bool wifi: true
|
||||
property bool ethernet: false
|
||||
|
||||
|
||||
property bool wifiEnabled: false
|
||||
property bool wifiScanning: false
|
||||
property bool wifiConnecting: connectProc.running
|
||||
property WifiAccessPoint wifiConnectTarget
|
||||
readonly property list<WifiAccessPoint> wifiNetworks: []
|
||||
readonly property WifiAccessPoint active: wifiNetworks.find(n => n.active) ?? null
|
||||
property string wifiStatus: "disconnected"
|
||||
|
||||
property string networkName: ""
|
||||
property int networkStrength
|
||||
property string materialSymbol: ethernet ? "lan" :
|
||||
wifiEnabled ? (
|
||||
Network.networkStrength > 80 ? "signal_wifi_4_bar" :
|
||||
Network.networkStrength > 60 ? "network_wifi_3_bar" :
|
||||
Network.networkStrength > 40 ? "network_wifi_2_bar" :
|
||||
Network.networkStrength > 20 ? "network_wifi_1_bar" :
|
||||
"signal_wifi_0_bar"
|
||||
) : "signal_wifi_off"
|
||||
property string materialSymbol: root.ethernet
|
||||
? "lan"
|
||||
: root.wifiEnabled
|
||||
? (
|
||||
Network.networkStrength > 83 ? "signal_wifi_4_bar" :
|
||||
Network.networkStrength > 67 ? "network_wifi" :
|
||||
Network.networkStrength > 50 ? "network_wifi_3_bar" :
|
||||
Network.networkStrength > 33 ? "network_wifi_2_bar" :
|
||||
Network.networkStrength > 17 ? "network_wifi_1_bar" :
|
||||
"signal_wifi_0_bar"
|
||||
)
|
||||
: (root.wifiStatus === "connecting")
|
||||
? "signal_wifi_statusbar_not_connected"
|
||||
: (root.wifiStatus === "disconnected")
|
||||
? "wifi_find"
|
||||
: (root.wifiStatus === "disabled")
|
||||
? "signal_wifi_off"
|
||||
: "signal_wifi_bad"
|
||||
|
||||
// Control
|
||||
function enableWifi(enabled = true): void {
|
||||
@@ -153,7 +164,7 @@ Singleton {
|
||||
Process {
|
||||
id: updateConnectionType
|
||||
property string buffer
|
||||
command: ["sh", "-c", "nmcli -t -f NAME,TYPE,DEVICE c show --active"]
|
||||
command: ["sh", "-c", "nmcli -t -f TYPE,STATE d status && nmcli -t -f CONNECTIVITY g"]
|
||||
running: true
|
||||
function startCheck() {
|
||||
buffer = "";
|
||||
@@ -166,14 +177,35 @@ Singleton {
|
||||
}
|
||||
onExited: (exitCode, exitStatus) => {
|
||||
const lines = updateConnectionType.buffer.trim().split('\n');
|
||||
const connectivity = lines.pop() // none, limited, full
|
||||
let hasEthernet = false;
|
||||
let hasWifi = false;
|
||||
let wifiStatus = "disconnected";
|
||||
lines.forEach(line => {
|
||||
if (line.includes("ethernet"))
|
||||
if (line.includes("ethernet") && line.includes("connected"))
|
||||
hasEthernet = true;
|
||||
else if (line.includes("wireless"))
|
||||
hasWifi = true;
|
||||
else if (line.includes("wifi:")) {
|
||||
if (line.includes("disconnected")) {
|
||||
wifiStatus = "disconnected"
|
||||
}
|
||||
else if (line.includes("connected")) {
|
||||
hasWifi = true;
|
||||
wifiStatus = "connected"
|
||||
|
||||
if (connectivity === "limited") {
|
||||
hasWifi = false;
|
||||
wifiStatus = "limited"
|
||||
}
|
||||
}
|
||||
else if (line.includes("connecting")) {
|
||||
wifiStatus = "connecting"
|
||||
}
|
||||
else if (line.includes("unavailable")) {
|
||||
wifiStatus = "disabled"
|
||||
}
|
||||
}
|
||||
});
|
||||
root.wifiStatus = wifiStatus;
|
||||
root.ethernet = hasEthernet;
|
||||
root.wifi = hasWifi;
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ Singleton {
|
||||
}
|
||||
|
||||
property bool silent: false
|
||||
property int unread: 0
|
||||
property var filePath: Directories.notificationsPath
|
||||
property list<Notif> 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);
|
||||
|
||||
@@ -69,6 +69,7 @@ ApplicationWindow {
|
||||
|
||||
Component.onCompleted: {
|
||||
MaterialThemeLoader.reapplyTheme()
|
||||
Config.readWriteDelay = 0 // Settings app always only sets one var at a time so delay isn't needed
|
||||
}
|
||||
|
||||
minimumWidth: 750
|
||||
@@ -172,7 +173,7 @@ ApplicationWindow {
|
||||
iconText: "edit"
|
||||
buttonText: Translation.tr("Config file")
|
||||
expanded: navRail.expanded
|
||||
onClicked: {
|
||||
downAction: () => {
|
||||
Qt.openUrlExternally(`${Directories.config}/illogical-impulse/config.json`);
|
||||
}
|
||||
|
||||
@@ -190,7 +191,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
|
||||
|
||||
@@ -33,6 +33,7 @@ ApplicationWindow {
|
||||
|
||||
Component.onCompleted: {
|
||||
MaterialThemeLoader.reapplyTheme();
|
||||
Config.readWriteDelay = 0 // Welcome app always only sets one var at a time so delay isn't needed
|
||||
}
|
||||
|
||||
minimumWidth: 600
|
||||
|
||||
@@ -38,10 +38,8 @@
|
||||
"Unfinished": "לא הושלם",
|
||||
"Add": "הוסף",
|
||||
"Nothing here!": "אין תזכורות",
|
||||
"Center title": "כותרת במרכז",
|
||||
"Elements": "אלמנטים",
|
||||
"Color picker": "בוחר צבעים",
|
||||
"Title bar": "שורת כותרת",
|
||||
"Sleep": "שינה",
|
||||
"Transparency": "שקיפות",
|
||||
"Bluetooth": "בלוטות׳",
|
||||
@@ -61,19 +59,15 @@
|
||||
"Wind": "רוח",
|
||||
"Humidity": "לחות",
|
||||
"Select Language": "בחר שפה",
|
||||
"Wallpaper": "טפט",
|
||||
"Copy code": "העתק קוד",
|
||||
"Allow NSFW": "הצג NSFW",
|
||||
"Colors & Wallpaper": "צבעים וטפט",
|
||||
"Shutdown": "כיבוי",
|
||||
"Decorations & Effects": "קישוטים ואפקטים",
|
||||
"Translation goes here...": "תרגום יגיע לכאן...",
|
||||
"Polling interval (ms)": "מרווח סקר (מילישניות)",
|
||||
"System prompt": "פרומפט מערכת",
|
||||
"Base URL": "כתובת בסיס",
|
||||
"Always show numbers": "הצג מספרים תמיד",
|
||||
"Wallpaper parallax": "אפקט parallax לטפט",
|
||||
"Plain rectangle": "מלבן פשוט",
|
||||
"illogical-impulse Welcome": "ברוך הבא ל-illogical-impulse",
|
||||
"Local only": "מקומי בלבד",
|
||||
"Dark/Light toggle": "מצב כהה/בהיר",
|
||||
@@ -82,10 +76,8 @@
|
||||
"Show app icons": "הצג אייקוני אפליקציות",
|
||||
"Useless buttons": "כפתורים מיותרים",
|
||||
"Scale (%)": "קנה מידה (%)",
|
||||
"Show background": "הצג רקע",
|
||||
"Intelligence": "בינה מלאכותית",
|
||||
"Enable": "אפשר",
|
||||
"Borderless": "ללא גבולות",
|
||||
"Random: Konachan": "אקראי: Konachan",
|
||||
"Yes": "כן",
|
||||
"Documentation": "תיעוד",
|
||||
@@ -94,7 +86,6 @@
|
||||
"Report a Bug": "דווח על באג",
|
||||
"Sunset": "שקיעה",
|
||||
"Weeb": "אנימה",
|
||||
"Shell windows": "חלונות",
|
||||
"Workspaces shown": "מספר שטחי עבודה מוצגים",
|
||||
"Screenshot tool": "כלי צילום מסך",
|
||||
"Enter text to translate...": "הכנס טקסט לתרגום",
|
||||
@@ -103,7 +94,6 @@
|
||||
"Scroll to change brightness": "גלול לשינוי בהירות",
|
||||
"Privacy Policy": "מדיניות פרטיות",
|
||||
"12h AM/PM": "12 שעות (AM/PM)",
|
||||
"Material palette": "פלטת צבעים",
|
||||
"No audio source": "אין מקור שמע",
|
||||
"Download": "הורד",
|
||||
"Prefixes": "קידומות",
|
||||
@@ -140,14 +130,11 @@
|
||||
"Donate": "תרום",
|
||||
"Resources": "משאבים",
|
||||
"Float": "צף",
|
||||
"Fake screen rounding": "עיגול מסך מזויף",
|
||||
"Hibernate": "שינה עמוקה",
|
||||
"Visibility": "ראות",
|
||||
"Delete": "מחק",
|
||||
"Style": "סגנון",
|
||||
"Page %1": "עמוד %1",
|
||||
"Keyboard toggle": "מקלדת וירטואלית",
|
||||
"Buttons": "כפתורים",
|
||||
"24h": "24 שעות",
|
||||
"Time": "שעה",
|
||||
"Clipboard": "לוח העתקה",
|
||||
@@ -165,7 +152,6 @@
|
||||
"Not visible to model": "לא נראה למודל",
|
||||
"Local Ollama model | %1": "מודל Ollama מקומי | %1",
|
||||
"Open file link": "פתח קישור לקובץ",
|
||||
"Waiting for response...": "ממתין לתשובה...",
|
||||
"Cheat sheet": "דף עזר",
|
||||
"Allow NSFW content": "אפשר תוכן NSFW",
|
||||
"%1 characters": "%1 תווים",
|
||||
@@ -180,8 +166,6 @@
|
||||
"Color generation": "יצירת צבעים",
|
||||
"Temperature must be between 0 and 2": "ערך הטמפרטורה חייב להיות בין 0 ל-2",
|
||||
"Earbang protection": "הגנת אוזניים",
|
||||
"Alternatively use /dark, /light, /img in the launcher": "באופן חלופי השתמש /dark, /light, /img במנוע",
|
||||
"Change any time later with /dark, /light, /img in the launcher": "שנה בכל זמן עם /dark, /light, /img במנוע",
|
||||
"Current model: %1\nSet it with %2model MODEL": "מודל נוכחי: %1\nשנה עם %2model",
|
||||
"Waifus only | Excellent quality, limited quantity": "וואייפוס בלבד | איכות מעולה, כמות מוגבלת",
|
||||
"Save to Downloads": "שמור בהורדות",
|
||||
@@ -195,7 +179,6 @@
|
||||
"Prevents abrupt increments and restricts volume limit": "מונע עליות חדות ומגביל עוצמת קול",
|
||||
"Preferred wallpaper zoom (%)": "זום טפט מועדף (%)",
|
||||
"Depends on workspace": "תלוי במקום העבודה",
|
||||
"Note: turning off can hurt readability": "הערה: כיבוי עלול לפגוע בקריאות",
|
||||
"Pick wallpaper image on your system": "בחר טפט מהמחשב",
|
||||
"Invalid API provider. Supported: \n-": "ספק API לא חוקי. נתמכים: \n-",
|
||||
"The hentai one | Great quantity, a lot of NSFW, quality varies wildly": "הנטאי | כמות רבה, NSFW, איכות משתנה",
|
||||
@@ -218,9 +201,7 @@
|
||||
"Refreshing (manually triggered)": "מרענן (הופעל ידנית)",
|
||||
"Kill conflicting programs?": "להפסיק תוכנות מתנגשות?",
|
||||
"System uptime:": "משך זמן פעילות המערכת:",
|
||||
"Place at the bottom/right": "הצב בתחתית/ימין",
|
||||
"Monochrome": "מונוכרום",
|
||||
"Bar layout": "פריסת סרגל",
|
||||
"Issues": "בעיות",
|
||||
"Online | Google's model\nNewer model that's slower than its predecessor but should deliver higher quality answers": "מקוון | מודל של גוגל\nמודל חדש יותר, איטי יותר מקודמו אך אמור לספק תשובות איכותיות יותר",
|
||||
"Temperature set to %1": "הטמפרטורה הוגדרה ל-%1",
|
||||
@@ -230,7 +211,6 @@
|
||||
"Set the tool to use for the model.": "הגדר את הכלי לשימוש עבור המודל.",
|
||||
"Cannot find a GPS service. Using the fallback method instead.": "לא נמצא שירות GPS. משתמש בשיטה חלופית.",
|
||||
"API key:\n\n```txt\n%1\n```": "מפתח API:\n\n```txt\n%1\n```",
|
||||
"Friday": "יום שישי",
|
||||
"Large images | God tier quality, no NSFW.": "תמונות גדולות | איכות גבוהה מאוד, ללא NSFW.",
|
||||
"Language": "שפה",
|
||||
"Weather Service": "שירות מזג אוויר",
|
||||
@@ -243,7 +223,6 @@
|
||||
"The current system prompt is\n\n---\n\n%1": "הפרומפט הנוכחי של המערכת הוא\n\n---\n\n%1",
|
||||
"Save chat": "שמור שיחה",
|
||||
"Conflicts with the shell's notification implementation": "מתנגש עם מימוש ההתראות של ה-shell",
|
||||
"Saturday": "יום שבת",
|
||||
"Critically low battery": "סוללה נמוכה מאוד",
|
||||
"Shell conflicts killer": "מנטרל התנגשויות shell",
|
||||
"Number show delay when pressing Super (ms)": "השהיית הצגת מספרים בלחיצת Super (מילישניות)",
|
||||
@@ -252,7 +231,6 @@
|
||||
"☕ Break: %1 minutes": "☕ הפסקה: %1 דקות",
|
||||
". Notes for Zerochan:\n- You must enter a color\n- Set your zerochan username in `sidebar.booru.zerochan.username` config option. You [might be banned for not doing so](https://www.zerochan.net/api#:~:text=The%20request%20may%20still%20be%20completed%20successfully%20without%20this%20custom%20header%2C%20but%20your%20project%20may%20be%20banned%20for%20being%20anonymous.)!": ". הערות ל-Zerochan:\n- חובה להזין צבע\n- הגדר את שם המשתמש שלך ב-zerochan באופציית הקונפיג `sidebar.booru.zerochan.username`. ייתכן שתחסם אם לא תעשה זאת!",
|
||||
"Used:": "בשימוש:",
|
||||
"Suspend at": "השהה ב-",
|
||||
"Hi there! First things first...": "שלום! קודם כל...",
|
||||
"Registration failed. Please inspect manually with the <tt>warp-cli</tt> command": "ההרשמה נכשלה. נא לבדוק ידנית עם הפקודה <tt>warp-cli</tt>",
|
||||
"Usage": "שימוש",
|
||||
@@ -300,7 +278,6 @@
|
||||
"Anime": "אנימה",
|
||||
"Online models disallowed\n\nControlled by `policies.ai` config option": "מודלים מקוונים אינם מותרים\n\nנשלט על ידי אפשרות הקונפיג `policies.ai`",
|
||||
"Thought": "מחשבה",
|
||||
"Wednesday": "יום רביעי",
|
||||
"GitHub": "גיטהאב",
|
||||
"Clear chat history": "נקה היסטוריית שיחות",
|
||||
"Resume": "המשך",
|
||||
@@ -321,9 +298,7 @@
|
||||
"Break": "הפסקה",
|
||||
"App": "אפליקציה",
|
||||
"Temperature\nChange with /temp VALUE": "טמפרטורה\nשנה עם /temp VALUE",
|
||||
"Horizontal": "אופקי",
|
||||
"Unknown command:": "פקודה לא ידועה:",
|
||||
"Language setting saved. Please restart Quickshell (Ctrl+Super+R) to apply the new language.": "הגדרת השפה נשמרה. נא להפעיל מחדש את Quickshell (Ctrl+Super+R) כדי להחיל את השפה החדשה.",
|
||||
"There might be a download in progress": "ייתכן שיש הורדה בתהליך",
|
||||
"Go to source (%1)": "עבור למקור (%1)",
|
||||
"Networking": "רשת",
|
||||
@@ -343,7 +318,6 @@
|
||||
"Choose model": "בחר מודל",
|
||||
"Large language models": "מודלי שפה גדולים",
|
||||
"%1 Safe Storage": "%1 אחסון בטוח",
|
||||
"Deadline": "דדליין",
|
||||
"No API key\nSet it with /key YOUR_API_KEY": "אין מפתח API\nהגדר אותו עם /key YOUR_API_KEY",
|
||||
"Logout": "התנתק",
|
||||
"Clean stuff | Excellent quality, no NSFW": "תמונות נקיות | איכות מעולה, ללא NSFW",
|
||||
@@ -353,7 +327,6 @@
|
||||
"Output": "פלט",
|
||||
"**Instructions**: Log into Mistral account, go to Keys on the sidebar, click Create new key": "**הוראות**: התחבר לחשבון Mistral, עבור ל-Keys בסרגל הצד, לחץ על Create new key",
|
||||
"Unknown function call: %1": "קריאת פונקציה לא ידועה: %1",
|
||||
"Sunday": "יום ראשון",
|
||||
"Interface Language": "שפת ממשק",
|
||||
"Fully charged": "טעון במלואו",
|
||||
"Free:": "פנוי:",
|
||||
@@ -368,21 +341,15 @@
|
||||
"Hover to trigger": "עבור עםְ העכבר להפעלה",
|
||||
"Enjoy! You can reopen the welcome app any time with <tt>Super+Shift+Alt+/</tt>. To open the settings app, hit <tt>Super+I</tt>": "תהנה! תוכל לפתוח מחדש את אפליקציית הברוכים הבאים בכל עת עם <tt>Super+Shift+Alt+/</tt>. כדי לפתוח את אפליקציית ההגדרות, לחץ <tt>Super+I</tt>",
|
||||
"Timeout (ms)": "פסק זמן (מילישניות)",
|
||||
"Monday": "יום שני",
|
||||
"Tuesday": "יום שלישי",
|
||||
"Such regions could be images or parts of the screen that have some containment.\nMight not always be accurate.\nThis is done with an image processing algorithm run locally and no AI is used.": "אזורים כאלה יכולים להיות תמונות או חלקים מהמסך שיש בהם תוכן.\nייתכן שלא תמיד יהיה מדויק. זה נעשה עם אלגוריתם עיבוד תמונה מקומי וללא שימוש בבינה מלאכותית.",
|
||||
"Long break": "הפסקה ארוכה",
|
||||
"Arrow keys to navigate, Enter to select\nEsc or click anywhere to cancel": "מקשי החצים לניווט, Enter לבחירה\nEsc או לחיצה בכל מקום לביטול",
|
||||
"Load prompt from %1": "טען פרומפט מ-%1",
|
||||
"That didn't work. Tips:\n- Check your tags and NSFW settings\n- If you don't have a tag in mind, type a page number": "זה לא עבד. טיפים:\n- בדוק את התגיות והגדרות NSFW\n- אם אין לך תגית, הקלד מספר עמוד",
|
||||
"Tip: Hide icons and always show numbers for\nthe classic illogical-impulse experience": "טיפ: הסתר אייקונים והצג תמיד מספרים לחוויית illogical-impulse הקלאסית",
|
||||
"Corner open": "פינה פתוחה",
|
||||
"Select Deadline": "בחר דדליין",
|
||||
"Overall appearance": "מראה כללי",
|
||||
"Disable tools": "השבת כלים",
|
||||
"Reject": "דחה",
|
||||
"Visualize region": "הדמיית אזור",
|
||||
"Thursday": "יום חמישי",
|
||||
"**Pricing**: Free tier available with limited rates. See https://docs.github.com/en/billing/concepts/product-billing/github-models\n\n**Instructions**: Generate a GitHub personal access token with Models permission, then set as API key here\n\n**Note**: To use this you will have to set the temperature parameter to 1": "**מחיר**: יש פרופיל חינם עם תקצב מוגבל. ראה https://docs.github.com/en/billing/concepts/product-billing/github-models\n\n**הוראות**: צור אסימון גישה אישי ב-GitHub עם הרשאת Models, ואז הגדר אותו כאן כמפתח API\n\n**הערה**: כדי להשתמש בזה תצטרך להגדיר את פרמטר הטמפרטורה ל-1",
|
||||
"Select the language for the user interface.\n\"Auto\" will use your system's locale.": "בחר את השפה לממשק המשתמש. \"אוטומטי\" ישתמש בשפת המערכת שלך.",
|
||||
"Automatically suspends the system when battery is low": "משהה אוטומטית את המערכת כאשר הסוללה נמוכה",
|
||||
@@ -392,7 +359,6 @@
|
||||
"Fidelity": "דיוק",
|
||||
"Load chat": "טען שיחה",
|
||||
"All-rounder | Good quality, decent quantity": "כללי | איכות טובה, כמות אדירה",
|
||||
"TimeTable": "לוח זמנים",
|
||||
"Info": "מידע",
|
||||
"Corner style": "סגנון פינות",
|
||||
"Online | Google's model\nFast, can perform searches for up-to-date information": "מקוון | מודל של גוגל\nמהיר, יכול לבצע חיפושים למידע עדכני",
|
||||
@@ -407,5 +373,133 @@
|
||||
"🔴 Focus: %1 minutes": "🔴 פוקוס: %1 דקות",
|
||||
"Set API key": "הגדר מפתח API",
|
||||
"Load chat from %1": "טען שיחה מ-%1",
|
||||
"Code saved to file": "הקוד נשמר לקובץ"
|
||||
"Code saved to file": "הקוד נשמר לקובץ",
|
||||
"Show clock": "הצגת שעון",
|
||||
"Use the system file picker instead\nRight-click to make this the default behavior": "השתמש בבוחר הקבצים של המערכת במקום\nלחיצה ימנית תהפוך את התנהגות זו לברירת המחדל",
|
||||
"Hour marks": "סימוני שעה",
|
||||
"Unread indicator: show count": "מתריע על אי-קריאה: הצגת כמות",
|
||||
"Cookie clock settings": "הגדרות שעון עוגיה",
|
||||
"Not all options are available in this app. You should also check the config file by hitting the \"Config file\" button on the topleft corner or opening %1 manually.": "לא כל האפשרויות נמצאות באפליקציה הזו. מומלץ לבדוק את קובץ ההגדרות על ידי לחיצה על הכפתור \"קובץ הגדרות\" הממוקם למעלה בפינה השמאלית. ניתן גם לפתוח את %1 באופן ידני.",
|
||||
"Border": "גבול",
|
||||
"Classic": "קלאסי",
|
||||
"Connected": "מחובר",
|
||||
"Hit \"/\" to search": "לחץ \"/\" לחיפוש",
|
||||
"Wallpaper & Colors": "רקע וצבעים",
|
||||
"Change any time later with /dark, /light, /wallpaper in the launcher\nIf the shell's colors aren't changing:\n 1. Open the right sidebar with Super+N\n 2. Click \"Reload Hyprland & Quickshell\" in the top-right corner": "ניתן לשנות בכל עת עם /dark, /light, /wallpaper במפעיל\nאם צבעי ה-shell לא משתנים:\n 1. פתח את הסרגל הצדדי הימני עם Super+N\n 2. לחץ על \"טען מחדש Hyprland & Quickshell\" בפינה הימנית העליונה",
|
||||
"Launch on startup": "הפעל בעת הפעלה",
|
||||
"Terminal: Harmonize threshold": "טרמינל: Harmonize threshold",
|
||||
"Quick": "מהיר",
|
||||
"Pills": "גלולות",
|
||||
"Terminal: Harmony (%)": "טרמינל: הרמוניה (%)",
|
||||
"Bar position": "מיקום הסרגל",
|
||||
"Connect to Wi-Fi": "התחבר ל-WiFi",
|
||||
"Force dark mode in terminal": "כפה על מצב כהה בטרמינל",
|
||||
"Wallpaper safety enforced": "בטיחות הרקע נאכפה",
|
||||
"Click to toggle light/dark mode\n(applied when wallpaper is chosen)": "לחץ לשינוי בין מצב בהיר/כהה\n(מיושם לאחר בחירת רקע)",
|
||||
"Dots": "Dots",
|
||||
"Minute hand": "מחוג הדקות",
|
||||
"Open editor": "פתח עורך",
|
||||
"This is usually safe and needed for your browser and AI sidebar anyway\nMostly useful for those who use lock on startup instead of a display manager that does it (GDM, SDDM, etc.)": "זה בדרך כלל בטוח ונדרש עבור הדפדפן שלך וסרגל הצד של הבינה המלאכותית.\nבעיקר שימושי עבור מי שמשתמש בנעילה בעת ההפעלה במקום מנהל תצוגה שעושה זאת (GDM, SDDM וכו').",
|
||||
"Security": "בטיחות",
|
||||
"Work safety": "בטיחות עבודה",
|
||||
"Bar & screen": "סרגל ומסך",
|
||||
"Crosshair overlay": "שכבת כוונת",
|
||||
"Make sure your player has MPRIS support\nor try turning off duplicate player filtering": "וודא שהנגן שלך תומך ב-MPRIS\nאו נסה לכבות סינון נגנים כפולים",
|
||||
"Bottom": "מטה",
|
||||
"Press Super+G to toggle appearance": "לחץ סופר+G לתצוגה או הסתרה",
|
||||
"Thin": "דק",
|
||||
"Sides": "צדדים",
|
||||
"Hollow": "חלול",
|
||||
"Usage: <tt>%1superpaste NUM_OF_ENTRIES[i]</tt>\nSupply <tt>i</tt> when you want images\nExamples:\n<tt>%1superpaste 4i</tt> for the last 4 images\n<tt>%1superpaste 7</tt> for the last 7 entries": "שימוש: <tt>%1superpaste NUM_OF_ENTRIES[i]</tt>\nהוסף <tt>i</tt> כאשר תרצה תמונות\nדוגמאות:\n<tt>%1superpaste 4i</tt> עבור 4 התמונות האחרונות\n<tt>%1superpaste 7</tt> עבור 7 הערכים האחרונים",
|
||||
"Center clock": "מרכוז השעון",
|
||||
"Tip: Close a window with Super+Q": "טיפ: סגור חלון עם Super+Q",
|
||||
"Clock style": "סגנון השעון",
|
||||
"Right": "ימינה",
|
||||
"Exceeded max allowed": "חריגה מהמקסימום המותר",
|
||||
"Bold": "מודגש",
|
||||
"Group style": "סגנון קבוצה",
|
||||
"Numbers": "מספרים",
|
||||
"Disconnect": "התנתקות",
|
||||
"Ignored if terminal theming is not enabled": "מתעלם אם ערכת נושא לטרמינל אינה מופעלת",
|
||||
"Dial style": "סגנון חוגה",
|
||||
"Auto styling with Gemini": "עיצוב אוטומטי עם Gemini",
|
||||
"Screen round corner": "עיגול פינות מסך",
|
||||
"When this is off you'll have to click": "כאשר אפשרות זו כבויה, תצטרך ללחוץ",
|
||||
"Paired": "מחובר",
|
||||
"Details": "פרטים",
|
||||
"Crosshair code (in Valorant's format)": "קוד כוונת (בפורמט של Valorant)",
|
||||
"Positioning": "מיקום",
|
||||
"Also unlock keyring": "פתח גם את שרשרת המפתחות (keyring)",
|
||||
"Make icons pinned by default": "הצמד אייקונים כברירת מחדל",
|
||||
"Background": "רקע",
|
||||
"Random osu! seasonal background\nImage is saved to ~/Pictures/Wallpapers": "רקע osu! עונתי רנדומלי\nהתמונה נשמרת ב- ~/Pictures/Wallpapers",
|
||||
"Cancel wallpaper selection": "בטל בחירת רקע",
|
||||
"Enable if you want clocks to show seconds accurately": "הפעל כדי שהשעון יראה שניות במדויק",
|
||||
"at": "ב",
|
||||
"Quote settings": "הגדרות ציטוט",
|
||||
"Timeout duration (if not defined by notification) (ms)": "משך זמן (אם לא מוגדר על ידי ההתראה) (באלפיות השנייה)",
|
||||
"Connect": "התחבר",
|
||||
"Digits in the middle": "ספרות באמצע",
|
||||
"Rect": "מלבן",
|
||||
"Unknown device": "מכשיר לא ידוע",
|
||||
"Back": "אחורה",
|
||||
"General": "כללי",
|
||||
"Bluetooth devices": "מכשירי Bluetooth",
|
||||
"Bubble": "בועה",
|
||||
"Hour hand": "מחוג השעות",
|
||||
"Enable translator": "הפעלת מתרגם",
|
||||
"Utility buttons": "כפתורי תועלת",
|
||||
"Value scroll": "ערך גלילה",
|
||||
"Remember that on most devices one can always hold the power button to force shutdown\nThis only makes it a tiny bit harder for accidents to happen": "זכור כי ברוב המכשירים תמיד ניתן להחזיק את כפתור ההפעלה כדי לכבות בכוח\nזה רק מקשה מעט על טעויות מקריות לקרות",
|
||||
"Material cookie": "עוגיה",
|
||||
"Locked": "נעול",
|
||||
"Left": "שמאלה",
|
||||
"Place at bottom": "מקם למטה",
|
||||
"Lock screen": "מסך נעילה",
|
||||
"Show \"Locked\" text": "הצג את הטקסט \"נעול\"",
|
||||
"Open network portal": "פתח את פורטל הרשת",
|
||||
"No active player": "אין נגן פעיל",
|
||||
"Simple digital": "דיגיטלי פשוט",
|
||||
"Tip: right-clicking a group\nalso expands it": "טיפ: לחיצה ימנית על קבוצה\nמרחיבה אותה גם כן",
|
||||
"Pick random from this folder": "בחר באקראיות מהתיקייה",
|
||||
"Illegal increment": "הוספה לא חוקית",
|
||||
"Style: Blurred": "סגנון: חיבור",
|
||||
"Full": "מלא",
|
||||
"Style: general": "סגנון: כללי",
|
||||
"Use Hyprlock (instead of Quickshell)": "השתמש ב-Hyprlock (במקום ב-Quickshell)",
|
||||
"Top": "מעלה",
|
||||
"Random: osu! seasonal": "רנדומלי: osu! עונתי",
|
||||
"Require password to power off/restart": "דרוש סיסמה לכיבוי/הפעלה מחדש",
|
||||
"Fill": "מלא",
|
||||
"Constantly rotate": "הסתובב לעד",
|
||||
"Forget": "שכח",
|
||||
"Pick a wallpaper": "בחירת רקע",
|
||||
"Show quote": "הצג ציטוט",
|
||||
"Line-separated": "הפרדת קו",
|
||||
"Shell command": "פקודת של (shell)",
|
||||
"Extra wallpaper zoom (%)": "הגדלת רקע (%)",
|
||||
"Search wallpapers": "חיפוש רקעים",
|
||||
"Bar style": "סגנון הסרגל",
|
||||
"Dot": "נקודה",
|
||||
"Second precision": "דיוק בשנייה",
|
||||
"Line": "קו",
|
||||
"Place the corners to trigger at the bottom": "מקם את הפינות להפעלה בתחתית",
|
||||
"Second hand": "מחוג השניות",
|
||||
"Math": "מתמטיקה",
|
||||
"Edit directory": "ערוך תיקייה",
|
||||
"Password": "סיסמה",
|
||||
"Terminal: Foreground boost (%)": "Terminal: Foreground boost (%)",
|
||||
"If you want to somehow use fingerprint unlock...": "אם תרצה איכשהו לפתוח בעזרת טביעת אצבע...",
|
||||
"Superpaste": "Superpaste",
|
||||
"Date style": "סגנון תאריך",
|
||||
"Enable blur": "הפעל טשטוש",
|
||||
"Brightness and volume": "בהירות ועוצמת שמע",
|
||||
"Quote": "ציטוט",
|
||||
"Mo": "Mo/*keep*/",
|
||||
"Su": "Su/*keep*/",
|
||||
"Sa": "Sa/*keep*/",
|
||||
"Fr": "Fr/*keep*/",
|
||||
"Tu": "Tu/*keep*/",
|
||||
"Th": "Th/*keep*/",
|
||||
"We": "We/*keep*/"
|
||||
}
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
|
||||
# Code details
|
||||
|
||||
## Contributing to i18n
|
||||
|
||||
For contributing in translation (i18n) for Quickshell, see also `.config/quickshell/translations/tools`.
|
||||
|
||||
## Dynamic loading
|
||||
|
||||
- If something's not always necessary, especially when guarded by a config option to enable/disable, put it in a `Loader`. One tip with `Loader`s is sometimes you will need to declare positioning properties (like `anchors`) in the `Loader`, not the `sourceComponent`.
|
||||
|
||||
@@ -28,8 +28,9 @@
|
||||
<details>
|
||||
<summary>Installation (illogical-impulse Quickshell)</summary>
|
||||
|
||||
- See the [Wiki](https://ii.clsty.link/en/ii-qs/01setup/) <sub>(idempotent script provided)</sub>
|
||||
- In case you can't access the wiki, you can always manually clone this repo and run `install.sh`
|
||||
- Just run `bash <(curl -s https://ii.clsty.link/setup)`
|
||||
- Or, clone this repo and run `./install.sh`
|
||||
- See [document](https://ii.clsty.link/en/ii-qs/01setup/) for details.
|
||||
- **Default keybinds**: Should be somewhat familiar to Windows or GNOME users. Important ones:
|
||||
- `Super`+`/` = keybind list
|
||||
- `Super`+`Enter` = terminal
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# This script is for quickly generate helpful info
|
||||
#
|
||||
# It should be as independent as possible and should not source other files unless it has to
|
||||
#
|
||||
# TODO: Add quickshell and Qt version check.
|
||||
# Pay attention to the version of Qt which quickshell built against.
|
||||
|
||||
STY_RED='\e[31m'
|
||||
STY_RESET='\e[00m'
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
+5
-1
@@ -27,5 +27,9 @@ fi
|
||||
#####################################################################################
|
||||
if [[ "${SKIP_ALLFILES}" != true ]]; then
|
||||
printf "${STY_CYAN}[$0]: 3. Copying config files\n${STY_RESET}"
|
||||
source ./scriptdata/step/3.install-files.sh
|
||||
if [[ "${EXPERIMENTAL_FILES_SCRIPT}" != true ]]; then
|
||||
source ./scriptdata/step/3.install-files.sh
|
||||
else
|
||||
source ./scriptdata/step/3.install-files.experimental.sh
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -22,6 +22,7 @@ If no option is specified, run default install process.
|
||||
--skip-plasmaintg Skip installing plasma-browser-integration
|
||||
--skip-miscconf Skip copying the dirs and files to \".configs\" except for
|
||||
AGS, Fish and Hyprland
|
||||
--exp-files Use experimental script for the third step copying files
|
||||
--fontset <set> (Unavailable yet) Use a set of pre-defined font and config
|
||||
--via-nix (Unavailable yet) Use Nix to install dependencies
|
||||
"
|
||||
@@ -34,7 +35,7 @@ cleancache(){
|
||||
# `man getopt` to see more
|
||||
para=$(getopt \
|
||||
-o hfk:cs \
|
||||
-l help,force,fontset:,clean,skip-allgreeting,skip-alldeps,skip-allsetups,skip-allfiles,skip-sysupdate,skip-fish,skip-hyprland,skip-plasmaintg,skip-miscconf,via-nix \
|
||||
-l help,force,fontset:,clean,skip-allgreeting,skip-alldeps,skip-allsetups,skip-allfiles,skip-sysupdate,skip-fish,skip-hyprland,skip-plasmaintg,skip-miscconf,exp-files,via-nix \
|
||||
-n "$0" -- "$@")
|
||||
[ $? != 0 ] && echo "$0: Error when getopt, please recheck parameters." && exit 1
|
||||
#####################################################################################
|
||||
@@ -68,6 +69,7 @@ while true ; do
|
||||
--skip-fish) SKIP_FISH=true;shift;;
|
||||
--skip-miscconf) SKIP_MISCCONF=true;shift;;
|
||||
--skip-plasmaintg) SKIP_PLASMAINTG=true;shift;;
|
||||
--exp-files) EXPERIMENTAL_FILES_SCRIPT=true;shift;;
|
||||
--via-nix) INSTALL_VIA_NIX=true;shift;;
|
||||
## Ones with parameter
|
||||
|
||||
|
||||
Reference in New Issue
Block a user