separate dashboard and settings changes to new branch
C++ / fmt (pull_request) Successful in 6s
C++ / build (pull_request) Failing after 10s
C++ / clang-tidy (pull_request) Failing after 9s
JS/TS / fmt (pull_request) Successful in 11s
JS/TS / lint (pull_request) Successful in 9s
Python / static (pull_request) Successful in 28s
Rust / build (pull_request) Successful in 49s
Python / verify (pull_request) Successful in 1m40s
Rust / fmt (pull_request) Successful in 26s
Rust / clippy (pull_request) Successful in 46s

This commit is contained in:
2026-09-30 15:11:51 +02:00
parent 83bc153ee3
commit 4f797a9741
6 changed files with 185 additions and 5 deletions
+1
View File
@@ -20,3 +20,4 @@ network-dev/
**/zshell.dist/ **/zshell.dist/
.opencode/ .opencode/
run-agent.sh run-agent.sh
AGENTS.md
+42
View File
@@ -0,0 +1,42 @@
import QtQuick
import Quickshell
ShaderEffect {
id: root
property Item target: parent
property real glowSize: 40
property real innerGlow: 0
property real lineWidth: 2
property real intensity: 1.0
property real speed: 1.0
property int period: 6000
property bool running: true
property color color1: "#4285F4"
property color color2: "#9B72CB"
property color color3: "#D96570"
property color color4: "#F2A54A"
readonly property size itemSize: Qt.size(width, height)
readonly property size rectSize: target ? Qt.size(target.width, target.height) : Qt.size(0, 0)
readonly property real radius: (target as Rectangle).radius ?? 0
property real phase: 0
anchors.fill: target
anchors.margins: -glowSize
z: -1
enabled: false
fragmentShader: Qt.resolvedUrl(`${Quickshell.shellDir}/assets/shaders/geminiglow.frag.qsb`)
FrameAnimation {
running: root.running && root.visible
onTriggered: {
const dt = frameTime * 1000;
root.phase = (root.phase + dt * root.speed / root.period) % 1.0;
}
}
}
@@ -170,7 +170,7 @@ Item {
Layout.fillWidth: ChatState.isWindow ? false : true Layout.fillWidth: ChatState.isWindow ? false : true
Layout.alignment: ChatState.isWindow ? Qt.AlignCenter : Qt.AlignLeft | Qt.AlignVCenter Layout.alignment: ChatState.isWindow ? Qt.AlignCenter : Qt.AlignLeft | Qt.AlignVCenter
elide: Text.ElideRight elide: Text.ElideRight
font.pointSize: Tokens.font.size.larger font: Tokens.font.title.medium
text: qsTr(root.chatData.title) text: qsTr(root.chatData.title)
} }
} }
@@ -346,7 +346,7 @@ Item {
id: scrollToBottom id: scrollToBottom
anchors.centerIn: parent anchors.centerIn: parent
font.pointSize: Tokens.font.size.large font: Tokens.font.icon.large
icon: "arrow_downward" icon: "arrow_downward"
isRound: true isRound: true
padding: Tokens.padding.extraSmall padding: Tokens.padding.extraSmall
@@ -455,7 +455,7 @@ Item {
MaterialIcon { MaterialIcon {
anchors.centerIn: parent anchors.centerIn: parent
font.pointSize: Tokens.font.size.extraLarge font.pointSize: Tokens.font.size.large
text: thumb.fileIcon(thumb.modelData?.mimeType ?? "") text: thumb.fileIcon(thumb.modelData?.mimeType ?? "")
visible: !thumb.modelData?.isImage ?? false visible: !thumb.modelData?.isImage ?? false
} }
@@ -537,13 +537,15 @@ Item {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.margins: Tokens.padding.medium
bg.border.color: Colors.palette.m3outlineVariant bg.border.color: Colors.palette.m3outlineVariant
bg.color: Colors.tPalette.m3surfaceContainerLowest bg.color: Colors.tPalette.m3surfaceContainerLowest
font.pointSize: Tokens.font.size.normal fastGlow: Chat.busy
font: Tokens.font.body.small
implicitHeight: Math.min(root.height / 5, contentHeight + topPadding + bottomPadding) implicitHeight: Math.min(root.height / 5, contentHeight + topPadding + bottomPadding)
focus: true focus: true
placeholderText: qsTr("Send a message") placeholderText: qsTr("Send a message")
sendIcon.font.pointSize: Tokens.font.size.large sendIcon.font: Tokens.font.icon.medium
sendIcon.icon: "arrow_upward" sendIcon.icon: "arrow_upward"
sendIcon.padding: Tokens.padding.extraSmall sendIcon.padding: Tokens.padding.extraSmall
@@ -9,6 +9,8 @@ TextAreaBase {
readonly property alias bg: bg readonly property alias bg: bg
readonly property alias sendIcon: sendIcon readonly property alias sendIcon: sendIcon
property bool fastGlow: false
signal sendPressed signal sendPressed
bottomPadding: Tokens.padding.large bottomPadding: Tokens.padding.large
@@ -17,6 +19,16 @@ TextAreaBase {
topPadding: Tokens.padding.large topPadding: Tokens.padding.large
wrapMode: TextAreaBase.Wrap wrapMode: TextAreaBase.Wrap
onFastGlowChanged: {
if (fastGlow) {
resetAnim.stop();
boostAnim.restart();
} else {
boostAnim.stop();
resetAnim.restart();
}
}
background: CustomRect { background: CustomRect {
id: bg id: bg
@@ -24,6 +36,47 @@ TextAreaBase {
color: Colors.tPalette.m3surfaceContainer color: Colors.tPalette.m3surfaceContainer
radius: Tokens.rounding.extraLarge radius: Tokens.rounding.extraLarge
GeminiGlow {
id: glow
glowSize: 32
opacity: root.activeFocus ? 1 : 0
visible: opacity > 0
Behavior on opacity {
Anim {}
}
SequentialAnimation {
id: boostAnim
NumberAnimation {
target: glow
property: "speed"
to: 4.0
duration: 250
easing.type: Easing.OutCubic
}
NumberAnimation {
target: glow
property: "speed"
to: 2.25
duration: 1500
easing.type: Easing.InOutQuad
}
}
// Ease back down to normal once fastGlow is false
NumberAnimation {
id: resetAnim
target: glow
property: "speed"
to: 1.0
duration: 800
easing.type: Easing.InOutQuad
}
}
StateLayer { StateLayer {
id: stateLayer id: stateLayer
+82
View File
@@ -0,0 +1,82 @@
#version 440
layout(location = 0) in vec2 qt_TexCoord0;
layout(location = 0) out vec4 fragColor;
layout(std140, binding = 0) uniform buf {
mat4 qt_Matrix;
float qt_Opacity;
vec2 itemSize;
vec2 rectSize;
float radius;
float glowSize;
float innerGlow;
float lineWidth;
float phase;
float intensity;
vec4 color1;
vec4 color2;
vec4 color3;
vec4 color4;
};
const float TAU = 6.28318530718;
float sdRoundBox(vec2 p, vec2 halfSize, float r)
{
vec2 q = abs(p) - (halfSize - r);
return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - r;
}
vec3 palette(float t)
{
t = fract(t) * 4.0;
float f = smoothstep(0.0, 1.0, fract(t));
if (t < 1.0) return mix(color1.rgb, color2.rgb, f);
if (t < 2.0) return mix(color2.rgb, color3.rgb, f);
if (t < 3.0) return mix(color3.rgb, color4.rgb, f);
return mix(color4.rgb, color1.rgb, f);
}
float hash(vec2 p)
{
return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453);
}
void main()
{
vec2 p = (qt_TexCoord0 - 0.5) * itemSize;
float r = clamp(radius, 0.0, min(rectSize.x, rectSize.y) * 0.5);
float d = sdRoundBox(p, rectSize * 0.5, r);
float ang = atan(p.y, p.x);
float a2 = phase * TAU;
float u = ang / TAU + 0.5 + phase;
u += 0.07 * sin(ang * 2.0 + a2) + 0.04 * sin(ang * 3.0 - a2 * 2.0);
vec3 col = palette(u);
float g = 0.0;
if (d > 0.0) {
float t = clamp(d / max(glowSize, 0.001), 0.0, 1.0);
g = pow(1.0 - t, 3.0);
} else if (innerGlow > 0.0) {
g = exp(d / innerGlow * 3.0);
}
float pulse = 0.9 + 0.1 * sin(a2 * 2.0 + ang);
g *= pulse;
float line = 0.0;
if (lineWidth > 0.0)
line = 1.0 - smoothstep(0.0, lineWidth, abs(d));
float a = clamp(g * intensity + line * 0.9, 0.0, 1.0);
col = mix(col, vec3(1.0), line * 0.25);
a += (hash(gl_FragCoord.xy) - 0.5) / 255.0;
a = clamp(a, 0.0, 1.0);
fragColor = vec4(col * a, a) * qt_Opacity;
}
Binary file not shown.