Feat: LLM Chat #155

Merged
zach merged 67 commits from feat/llm-chat-tab into main 2026-10-18 17:05:05 +02:00
9 changed files with 133 additions and 128 deletions
Showing only changes of commit 99fdfbc465 - Show all commits
+3
View File
@@ -34,4 +34,7 @@ PersistentProperties {
// Drawing state
property color penColor: "white"
property int penWidth: 4
// Screenshot state
property bool screenshot
}
+18 -3
View File
@@ -56,11 +56,10 @@ CustomWindow {
property color surfaceColor: Colors.tPalette.m3surface
WlrLayershell.exclusionMode: ExclusionMode.Ignore
WlrLayershell.keyboardFocus: screenState.launcher || screenState.settings || screenState.sidebar ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None
WlrLayershell.keyboardFocus: screenState.screenshot ? WlrKeyboardFocus.Exclusive : screenState.launcher || screenState.settings || screenState.sidebar ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None
WlrLayershell.layer: (fsTransitionProg > 0 && Config.general.showOverFullscreen) || (hasSpecialWorkspace && hasFullscreenOnNormalWs) ? WlrLayer.Overlay : WlrLayer.Top
color: "transparent"
contentItem.focus: true
mask: screenState.isDrawing ? null : (hasFullscreen && !bar.isHovered ? emptyRegion : regions)
mask: screenState.isDrawing || screenState.screenshot ? null : (hasFullscreen && !bar.isHovered ? emptyRegion : regions)
name: "Bar"
Behavior on fsTransitionProg {
@@ -427,6 +426,22 @@ CustomWindow {
}
}
LazyLoader {
id: loader
property bool closing: !root.screenState.screenshot
onClosingChanged: if (!closing)
activeAsync = true
Picker {
loader: loader
parent: root.contentItem
screen: root.screen
screenState: root.screenState
}
}
component PanelBg: BlobRect2 {
property real deformAmount: 0.15
required property Item panel
-88
View File
@@ -1,88 +0,0 @@
pragma ComponentBehavior: Bound
import Quickshell
import Quickshell.Wayland
import Quickshell.Io
import Quickshell.Hyprland
import ZShell
import qs.Components
Scope {
LazyLoader {
id: root
property bool closing
property bool freeze
Variants {
model: Quickshell.screens
PanelWindow {
id: win
required property ShellScreen modelData
WlrLayershell.exclusionMode: ExclusionMode.Ignore
WlrLayershell.keyboardFocus: root.closing ? WlrKeyboardFocus.None : WlrKeyboardFocus.Exclusive
WlrLayershell.layer: WlrLayer.Overlay
WlrLayershell.namespace: "areapicker"
color: "transparent"
mask: root.closing ? empty : null
screen: modelData
anchors {
bottom: true
left: true
right: true
top: true
}
Region {
id: empty
}
Picker {
loader: root
screen: win.modelData
}
}
}
}
IpcHandler {
function open(): void {
root.freeze = false;
root.closing = false;
root.activeAsync = true;
}
function openFreeze(): void {
root.freeze = true;
root.closing = false;
root.activeAsync = true;
}
target: "picker"
}
CustomShortcut {
name: "screenshot"
onPressed: {
root.freeze = false;
root.closing = false;
root.activeAsync = true;
}
}
CustomShortcut {
name: "screenshotFreeze"
onPressed: {
root.freeze = true;
root.closing = false;
root.activeAsync = true;
}
}
}
+69 -24
View File
@@ -41,6 +41,7 @@ Item {
property real rsy: Math.min(sy, ey)
readonly property real scaleRatio: Hypr.monitorFor(screen).scale
required property ShellScreen screen
required property ScreenState screenState
property real sh: Math.abs(sy - ey)
readonly property color shadowColor: Hypr.options.decoration.shadow?.color ?? "black"
readonly property bool shadowEnabled: Hypr.options.decoration.shadow.enabled
@@ -97,10 +98,6 @@ Item {
const args = Config.screenshot.mode === "auto" ? ["--rounding", `${rounding}`, "--radius", root.cornerRadius, "--shadow", root.shadowEnabled, "--shadow-blur", `${shadow_blur}`, "--shadow-color", `${r},${g},${b},${a}`, "--shadow-offset-x", root.shadowOffset[0], "--shadow-offset-y", root.shadowOffset[1]] : [];
const postCmd = Config.screenshot.enable_pp ? ["zshell-img-tools", "--scale", root.scaleRatio, ...args, "--image"] : null;
overlay.visible = border.visible = false;
handles.visible = false;
toolbar.visible = false;
ZShellIo.saveItem(captureLayer, tmpfile, Qt.rect(Math.ceil(rsx), Math.ceil(rsy), Math.floor(sw), Math.floor(sh)), path => {
const finalize = finalPath => {
if (copyToClipboard) {
@@ -154,7 +151,7 @@ Item {
Component.onCompleted: {
Hypr.extras.refreshOptions();
screencopy.active = true;
root.forceActiveFocus();
opacity = 1;
@@ -219,13 +216,63 @@ Item {
onReleased: root.enterEditMode()
}
Connections {
function onClosingChanged(): void {
if (root.loader.closing)
closeAnim.start();
else {
closeAnim.stop();
returnAnim.start();
}
}
target: root.loader
}
ParallelAnimation {
id: returnAnim
Anim {
duration: 300
property: "opacity"
target: root
to: 1
}
Anim {
property: "rsx"
target: root
to: Math.min(root.sx, root.ex)
}
Anim {
property: "rsy"
target: root
to: Math.min(root.sy, root.ey)
}
Anim {
property: "sw"
target: root
to: Math.abs(root.sx - root.ex)
}
Anim {
property: "sh"
target: root
to: Math.abs(root.sy - root.ey)
}
}
SequentialAnimation {
id: closeAnim
PropertyAction {
property: "closing"
target: root.loader
value: true
ScriptAction {
script: {
const states = ShellState.allStates();
for (const s of states)
s.screenshot = false;
}
}
ParallelAnimation {
@@ -267,17 +314,12 @@ Item {
anchors.fill: parent
Loader {
ScreencopyView {
id: screencopy
active: false
anchors.fill: parent
asynchronous: true
sourceComponent: ScreencopyView {
captureSource: root.screen
paintCursor: false
}
captureSource: root.screen
paintCursor: false
}
AnnotationCanvas {
@@ -305,8 +347,7 @@ Item {
color: "white"
layer.enabled: true
opacity: 0.3
radius: root.realRounding
visible: screencopy.item?.hasContent ?? false
visible: screencopy.hasContent
layer.effect: MultiEffect {
maskEnabled: true
@@ -343,7 +384,7 @@ Item {
implicitHeight: selectionRect.implicitHeight + root.realBorderWidth * 2
implicitWidth: selectionRect.implicitWidth + root.realBorderWidth * 2
radius: root.realRounding > 0 ? root.realRounding + root.realBorderWidth : 0
visible: screencopy.item?.hasContent ?? false
visible: screencopy.hasContent
x: selectionRect.x - root.realBorderWidth
y: selectionRect.y - root.realBorderWidth
@@ -365,10 +406,14 @@ Item {
visible: root.mode === "edit" && root.tool === "move"
onBoundsChanged: (x, y, w, h) => {
root.sx = x;
root.sy = y;
root.ex = x + w;
root.ey = y + h;
let nx = Math.max(0, x);
let ny = Math.max(0, y);
let nw = Math.min(w, root.screen.width - nx);
let nh = Math.min(h, root.screen.height - ny);
root.sx = nx;
root.sy = ny;
root.ex = nx + nw;
root.ey = ny + nh;
}
onMoveBy: (dx, dy) => {
const w = root.sw, h = root.sh;
+7 -5
View File
@@ -59,6 +59,7 @@ Item {
}
anchors.fill: parent
enabled: tool !== "none"
StrokeCanvas {
id: canvas
@@ -77,15 +78,12 @@ Item {
acceptedButtons: Qt.LeftButton | Qt.RightButton
anchors.fill: parent
cursorShape: undefined
enabled: root.tool !== "none"
hoverEnabled: true
enabled: root.enabled
onPositionChanged: e => {
const x = e.x;
const y = e.y;
canvas.hoverPoint = Qt.point(x, y);
if (!pressed)
return;
@@ -125,12 +123,16 @@ Item {
const withinYHeight = y > root.selection.y && y < root.selection.y + root.selection.implicitHeight;
if (withinXWidth && withinYHeight) {
canvas.showHover(x, y);
if (!drawHandler.pressed)
canvas.showHover(x, y);
else
canvas.showHover(drawHandler.mouseX, drawHandler.mouseY);
return Qt.BlankCursor;
} else {
canvas.hideHover();
return undefined;
}
}
enabled: root.enabled
}
}
+13 -3
View File
@@ -1,13 +1,15 @@
pragma ComponentBehavior: Bound
import QtQuick
import ZShell.Internal
import qs.Services
Item {
id: root
required property int border
property color handleBorder: "#3584e4"
property color handleFill: "white"
property color handleBorder: Colors.palette.m3primary
property color handleFill: Colors.palette.m3onPrimary
property real hs: 12
property real minSize: 24
required property real selH
@@ -26,6 +28,8 @@ Item {
x: selX
y: selY
Component.onDestruction: Cursor.clearOverride()
DragHandler {
id: moveHandler
@@ -33,6 +37,7 @@ Item {
property real accumY: 0
cursorShape: undefined
dragThreshold: 0
target: null
onActiveChanged: {
@@ -54,7 +59,7 @@ Item {
if (root.tool !== "move")
return undefined;
if (moveHandler.centroid.pressedButtons & Qt.LeftButton)
if ((moveHandler.centroid.pressedButtons & Qt.LeftButton) && moveHandler.active)
return Qt.ClosedHandCursor;
else
return Qt.OpenHandCursor;
@@ -123,6 +128,8 @@ Item {
z: 10
HoverHandler {
id: hover
cursorShape: {
switch (handle.edge) {
case "tl":
@@ -148,6 +155,7 @@ Item {
property real startX
property real startY
dragThreshold: 0
grabPermissions: PointerHandler.CanTakeOverFromAnything | PointerHandler.TakeOverForbidden
target: null
@@ -157,8 +165,10 @@ Item {
startY = root.y;
startW = root.width;
startH = root.height;
Cursor.setOverride(hover.cursorShape);
} else {
root.dragFinished();
Cursor.clearOverride();
}
}
onTranslationChanged: {
+17
View File
@@ -11,6 +11,18 @@ Scope {
readonly property bool hasFullscreen: Hypr.focusedWorkspace?.toplevels.values.some(t => t.lastIpcObject.fullscreen === 2) ?? false
property bool launcherInterrupted
CustomShortcut {
description: "Open screenshot"
name: "screenshot"
onPressed: {
const states = ShellState.allStates();
for (const s of states) {
s.screenshot = true;
}
}
}
CustomShortcut {
description: "Toggle launcher"
name: "toggle-launcher"
@@ -26,6 +38,7 @@ Scope {
}
CustomShortcut {
description: "Toggle drawing"
name: "toggle-drawing"
onPressed: {
@@ -35,6 +48,7 @@ Scope {
}
CustomShortcut {
description: "Toggle sidebar"
name: "toggle-nc"
onPressed: {
@@ -44,6 +58,7 @@ Scope {
}
CustomShortcut {
description: "Show On-Screen-Display"
name: "show-osd"
onPressed: {
@@ -53,6 +68,7 @@ Scope {
}
CustomShortcut {
description: "Toggle settings"
name: "toggle-settings"
onPressed: {
@@ -62,6 +78,7 @@ Scope {
}
CustomShortcut {
description: "Toggle clipboard"
name: "toggle-clipboard"
onPressed: {
+6 -1
View File
@@ -6,6 +6,10 @@ import qs.Components
import qs.Helpers
Singleton {
function allStates(): list<ScreenState> {
return [...states.instances];
}
function anySidebarOpen(): bool {
return states.instances.some(s => s.sidebar);
}
@@ -30,6 +34,7 @@ Singleton {
model: Quickshell.screens
ScreenState {}
ScreenState {
}
}
}
-4
View File
@@ -12,7 +12,6 @@ import qs.Modules
import qs.Modules.Wallpaper
import qs.Modules.Lock
import qs.Drawers
import qs.Helpers
import qs.Modules.Polkit
import qs.Daemons
@@ -29,9 +28,6 @@ ShellRoot {
Wallpaper {
}
AreaPicker {
}
Lock {
id: lock
}