merge upstream

This commit is contained in:
Greyfeather
2025-05-21 00:22:49 -06:00
parent 08b9014ee2
commit 65b5ec93c7
87 changed files with 2119 additions and 1602 deletions
@@ -1,9 +1,11 @@
import QtQuick
import Quickshell
import "root:/modules/common/functions/color_utils.js" as ColorUtils
pragma Singleton
pragma ComponentBehavior: Bound
Singleton {
id: root
property QtObject m3colors
property QtObject animation
property QtObject animationCurves
@@ -13,18 +15,6 @@ Singleton {
property QtObject sizes
property string syntaxHighlightingTheme
function mix(color1, color2, percentage) {
var c1 = Qt.color(color1);
var c2 = Qt.color(color2);
return Qt.rgba(percentage * c1.r + (1 - percentage) * c2.r, percentage * c1.g + (1 - percentage) * c2.g, percentage * c1.b + (1 - percentage) * c2.b, percentage * c1.a + (1 - percentage) * c2.a);
}
// Transparentize
function transparentize(color, percentage) {
var c = Qt.color(color);
return Qt.rgba(c.r, c.g, c.b, c.a * (1 - percentage));
}
m3colors: QtObject {
property bool darkmode: false
property bool transparent: false
@@ -108,37 +98,37 @@ Singleton {
property color colSubtext: m3colors.m3outline
property color colLayer0: m3colors.m3background
property color colOnLayer0: m3colors.m3onBackground
property color colLayer0Hover: mix(colLayer0, colOnLayer0, 0.9)
property color colLayer0Active: mix(colLayer0, colOnLayer0, 0.8)
property color colLayer0Hover: ColorUtils.mix(colLayer0, colOnLayer0, 0.9)
property color colLayer0Active: ColorUtils.mix(colLayer0, colOnLayer0, 0.8)
property color colLayer1: m3colors.m3surfaceContainerLow;
property color colOnLayer1: m3colors.m3onSurfaceVariant;
property color colOnLayer1Inactive: mix(colOnLayer1, colLayer1, 0.45);
property color colLayer2: mix(m3colors.m3surfaceContainer, m3colors.m3surfaceContainerHigh, 0.55);
property color colOnLayer1Inactive: ColorUtils.mix(colOnLayer1, colLayer1, 0.45);
property color colLayer2: ColorUtils.mix(m3colors.m3surfaceContainer, m3colors.m3surfaceContainerHigh, 0.55);
property color colOnLayer2: m3colors.m3onSurface;
property color colOnLayer2Disabled: mix(colOnLayer2, m3colors.m3background, 0.4);
property color colLayer3: mix(m3colors.m3surfaceContainerHigh, m3colors.m3onSurface, 0.96);
property color colOnLayer2Disabled: ColorUtils.mix(colOnLayer2, m3colors.m3background, 0.4);
property color colLayer3: ColorUtils.mix(m3colors.m3surfaceContainerHigh, m3colors.m3onSurface, 0.96);
property color colOnLayer3: m3colors.m3onSurface;
property color colLayer1Hover: mix(colLayer1, colOnLayer1, 0.88);
property color colLayer1Active: mix(colLayer1, colOnLayer1, 0.77);
property color colLayer2Hover: mix(colLayer2, colOnLayer2, 0.90);
property color colLayer2Active: mix(colLayer2, colOnLayer2, 0.80);
property color colLayer2Disabled: mix(colLayer2, m3colors.m3background, 0.8);
property color colLayer3Hover: mix(colLayer3, colOnLayer3, 0.90);
property color colLayer3Active: mix(colLayer3, colOnLayer3, 0.80);
property color colPrimaryHover: mix(m3colors.m3primary, colLayer1Hover, 0.85)
property color colPrimaryActive: mix(m3colors.m3primary, colLayer1Active, 0.7)
property color colPrimaryContainerHover: mix(m3colors.m3primaryContainer, colLayer1Hover, 0.7)
property color colPrimaryContainerActive: mix(m3colors.m3primaryContainer, colLayer1Active, 0.6)
property color colSecondaryHover: mix(m3colors.m3secondary, colLayer1Hover, 0.85)
property color colSecondaryActive: mix(m3colors.m3secondary, colLayer1Active, 0.4)
property color colSecondaryContainerHover: mix(m3colors.m3secondaryContainer, colLayer1Hover, 0.6)
property color colSecondaryContainerActive: mix(m3colors.m3secondaryContainer, colLayer1Active, 0.54)
property color colSurfaceContainerHighestHover: mix(m3colors.m3surfaceContainerHighest, m3colors.m3onSurface, 0.95)
property color colSurfaceContainerHighestActive: mix(m3colors.m3surfaceContainerHighest, m3colors.m3onSurface, 0.85)
property color colLayer1Hover: ColorUtils.mix(colLayer1, colOnLayer1, 0.92);
property color colLayer1Active: ColorUtils.mix(colLayer1, colOnLayer1, 0.85);
property color colLayer2Hover: ColorUtils.mix(colLayer2, colOnLayer2, 0.90);
property color colLayer2Active: ColorUtils.mix(colLayer2, colOnLayer2, 0.80);
property color colLayer2Disabled: ColorUtils.mix(colLayer2, m3colors.m3background, 0.8);
property color colLayer3Hover: ColorUtils.mix(colLayer3, colOnLayer3, 0.90);
property color colLayer3Active: ColorUtils.mix(colLayer3, colOnLayer3, 0.80);
property color colPrimaryHover: ColorUtils.mix(m3colors.m3primary, colLayer1Hover, 0.85)
property color colPrimaryActive: ColorUtils.mix(m3colors.m3primary, colLayer1Active, 0.7)
property color colPrimaryContainerHover: ColorUtils.mix(m3colors.m3primaryContainer, colLayer1Hover, 0.7)
property color colPrimaryContainerActive: ColorUtils.mix(m3colors.m3primaryContainer, colLayer1Active, 0.6)
property color colSecondaryHover: ColorUtils.mix(m3colors.m3secondary, colLayer1Hover, 0.85)
property color colSecondaryActive: ColorUtils.mix(m3colors.m3secondary, colLayer1Active, 0.4)
property color colSecondaryContainerHover: ColorUtils.mix(m3colors.m3secondaryContainer, colLayer1Hover, 0.6)
property color colSecondaryContainerActive: ColorUtils.mix(m3colors.m3secondaryContainer, colLayer1Active, 0.54)
property color colSurfaceContainerHighestHover: ColorUtils.mix(m3colors.m3surfaceContainerHighest, m3colors.m3onSurface, 0.95)
property color colSurfaceContainerHighestActive: ColorUtils.mix(m3colors.m3surfaceContainerHighest, m3colors.m3onSurface, 0.85)
property color colTooltip: "#3C4043" // m3colors.m3inverseSurface in the specs, but the m3 website actually uses this color
property color colOnTooltip: "#F8F9FA" // m3colors.m3inverseOnSurface in the specs, but the m3 website actually uses this color
property color colScrim: transparentize(m3colors.m3scrim, 0.5)
property color colShadow: transparentize(m3colors.m3shadow, 0.75)
property color colScrim: ColorUtils.transparentize(m3colors.m3scrim, 0.5)
property color colShadow: ColorUtils.transparentize(m3colors.m3shadow, 0.75)
}
rounding: QtObject {
@@ -189,24 +179,57 @@ Singleton {
property int type: Easing.BezierSpline
property list<real> bezierCurve: animationCurves.emphasized
property int velocity: 650
property Component numberAnimation: Component {
NumberAnimation {
duration: root.animation.elementMove.duration
easing.type: root.animation.elementMove.type
easing.bezierCurve: root.animation.elementMove.bezierCurve
}
}
property Component colorAnimation: Component {
ColorAnimation {
duration: root.animation.elementMove.duration
easing.type: root.animation.elementMove.type
easing.bezierCurve: root.animation.elementMove.bezierCurve
}
}
}
property QtObject elementMoveEnter: QtObject {
property int duration: 400
property int type: Easing.BezierSpline
property list<real> bezierCurve: animationCurves.emphasizedDecel
property int velocity: 650
property Component numberAnimation: Component {
NumberAnimation {
duration: root.animation.elementMoveEnter.duration
easing.type: root.animation.elementMoveEnter.type
easing.bezierCurve: root.animation.elementMoveEnter.bezierCurve
}
}
}
property QtObject elementMoveExit: QtObject {
property int duration: 200
property int type: Easing.BezierSpline
property list<real> bezierCurve: animationCurves.emphasizedAccel
property int velocity: 650
property Component numberAnimation: Component {
NumberAnimation {
duration: root.animation.elementMoveExit.duration
easing.type: root.animation.elementMoveExit.type
easing.bezierCurve: root.animation.elementMoveExit.bezierCurve
}
}
}
property QtObject elementMoveFast: QtObject {
property int duration: 200
property int type: Easing.BezierSpline
property list<real> bezierCurve: animationCurves.standardDecel
property int velocity: 850
property Component colorAnimation: Component {ColorAnimation {
duration: root.animation.elementMoveFast.duration
easing.type: root.animation.elementMoveFast.type
easing.bezierCurve: root.animation.elementMoveFast.bezierCurve
}}
}
property QtObject scroll: QtObject {
property int duration: 400
@@ -226,18 +249,21 @@ Singleton {
}
sizes: QtObject {
property int barHeight: 40
property int barCenterSideModuleWidth: 360
property int barPreferredSideSectionWidth: 400
property int sidebarWidth: 450
property int sidebarWidthExtended: 750
property int notificationPopupWidth: 410
property int searchWidthCollapsed: 260
property int searchWidth: 450
property int hyprlandGapsOut: 5
property int elevationMargin: 7
property int fabShadowRadius: 5
property int fabHoveredShadowRadius: 7
property real barHeight: 40
property real barCenterSideModuleWidth: 360
property real barPreferredSideSectionWidth: 400
property real sidebarWidth: 460
property real sidebarWidthExtended: 750
property real osdWidth: 200
property real mediaControlsWidth: 440
property real mediaControlsHeight: 160
property real notificationPopupWidth: 410
property real searchWidthCollapsed: 260
property real searchWidth: 450
property real hyprlandGapsOut: 5
property real elevationMargin: 8
property real fabShadowRadius: 5
property real fabHoveredShadowRadius: 7
}
syntaxHighlightingTheme: Appearance.m3colors.darkmode ? "Monokai" : "ayu Light"
@@ -5,7 +5,7 @@ pragma ComponentBehavior: Bound
Singleton {
property QtObject ai: QtObject {
property string systemPrompt: "Use casual tone. No user knowledge is to be assumed except basic Linux literacy. Be brief and concise: When explaining concepts, use bullet points (prefer minus sign (-) over asterisk (*)) and highlight keywords in bold to pinpoint the main concepts instead of long paragraphs. You are also encouraged to split your response with h2 headers, each header title beginning with an emoji, like `## 🐧 Linux`."
property string systemPrompt: qsTr("Use casual tone. No user knowledge is to be assumed except basic Linux literacy. Be brief and concise: When explaining concepts, use bullet points (prefer minus sign (-) over asterisk (*)) and highlight keywords in bold to pinpoint the main concepts instead of long paragraphs. You are also encouraged to split your response with h2 headers, each header title beginning with an emoji, like `## 🐧 Linux`.")
}
property QtObject appearance: QtObject {
@@ -13,10 +13,10 @@ Singleton {
}
property QtObject apps: QtObject {
property string bluetooth: "blueberry"
property string bluetooth: "better-control --bluetooth"
property string imageViewer: "loupe"
property string network: "XDG_CURRENT_DESKTOP=\"gnome\" gnome-control-center wifi"
property string settings: "XDG_CURRENT_DESKTOP=\"gnome\" gnome-control-center"
property string network: "better-control --wifi"
property string settings: "better-control"
property string taskManager: "gnome-usage"
property string terminal: "foot" // This is only for shell actions
}
@@ -25,6 +25,7 @@ Singleton {
property int batteryLowThreshold: 20
property string topLeftIcon: "spark" // Options: distro, spark
property bool showBackground: true
property bool borderless: false
property QtObject resources: QtObject {
property bool alwaysShowSwap: true
property bool alwaysShowCpu: false
@@ -70,7 +71,7 @@ Singleton {
property string defaultProvider: "yandere"
property int limit: 20
property QtObject zerochan: QtObject {
property string username: ""
property string username: "[unset]"
}
}
}
@@ -9,12 +9,6 @@ Singleton {
}
property QtObject sidebar: QtObject {
property QtObject leftSide: QtObject {
property int selectedTab: 0
}
property QtObject centerGroup: QtObject {
property int selectedTab: 0
}
property QtObject bottomGroup: QtObject {
property bool collapsed: false
property int selectedTab: 0
@@ -0,0 +1,85 @@
// This module provides high level utility functions for color manipulation.
/**
* Returns a color with the hue of color2 and the saturation, value, and alpha of color1.
*
* @param {string} color1 - The base color (any Qt.color-compatible string).
* @param {string} color2 - The color to take hue from.
* @returns {Qt.rgba} The resulting color.
*/
function colorWithHueOf(color1, color2) {
var c1 = Qt.color(color1);
var c2 = Qt.color(color2);
// Qt.color hsvHue/hsvSaturation/hsvValue/alpha return 0-1
var hue = c2.hsvHue;
var sat = c1.hsvSaturation;
var val = c1.hsvValue;
var alpha = c1.a;
return Qt.hsva(hue, sat, val, alpha);
}
/**
* Returns a color with the saturation of color2 and the hue/value/alpha of color1.
*
* @param {string} color1 - The base color (any Qt.color-compatible string).
* @param {string} color2 - The color to take saturation from.
* @returns {Qt.rgba} The resulting color.
*/
function colorWithSaturationOf(color1, color2) {
var c1 = Qt.color(color1);
var c2 = Qt.color(color2);
var hue = c1.hsvHue;
var sat = c2.hsvSaturation;
var val = c1.hsvValue;
var alpha = c1.a;
return Qt.hsva(hue, sat, val, alpha);
}
/**
* Adapts color1 to the accent (hue and saturation) of color2 using HSL, keeping lightness and alpha from color1.
*
* @param {string} color1 - The base color (any Qt.color-compatible string).
* @param {string} color2 - The accent color.
* @returns {Qt.rgba} The resulting color.
*/
function adaptToAccent(color1, color2) {
var c1 = Qt.color(color1);
var c2 = Qt.color(color2);
var hue = c2.hslHue;
var sat = c2.hslSaturation;
var light = c1.hslLightness;
var alpha = c1.a;
return Qt.hsla(hue, sat, light, alpha);
}
/**
* Mixes two colors by a given percentage.
*
* @param {string} color1 - The first color (any Qt.color-compatible string).
* @param {string} color2 - The second color.
* @param {number} percentage - The mix ratio (0-1). 1 = all color1, 0 = all color2.
* @returns {Qt.rgba} The resulting mixed color.
*/
function mix(color1, color2, percentage) {
var c1 = Qt.color(color1);
var c2 = Qt.color(color2);
return Qt.rgba(percentage * c1.r + (1 - percentage) * c2.r, percentage * c1.g + (1 - percentage) * c2.g, percentage * c1.b + (1 - percentage) * c2.b, percentage * c1.a + (1 - percentage) * c2.a);
}
/**
* Transparentizes a color by a given percentage.
*
* @param {string} color - The color (any Qt.color-compatible string).
* @param {number} percentage - The amount to transparentize (0-1).
* @returns {Qt.rgba} The resulting color.
*/
function transparentize(color, percentage) {
var c = Qt.color(color);
return Qt.rgba(c.r, c.g, c.b, c.a * (1 - percentage));
}
@@ -147,4 +147,32 @@ function wordWrap(str, maxLen) {
}
if (current.length > 0) lines.push(current);
return lines.join("\n");
}
function cleanMusicTitle(title) {
if (!title) return "";
// Brackets
title = title.replace(/^ *\([^)]*\) */g, " "); // Round brackets
title = title.replace(/^ *\[[^\]]*\] */g, " "); // Square brackets
title = title.replace(/^ *\{[^\}]*\} */g, " "); // Curly brackets
// Japenis brackets
title = title.replace(/^ *【[^】]*】/, "") // Touhou
title = title.replace(/^ *《[^》]*》/, "") // ??
title = title.replace(/^ *「[^」]*」/, "") // OP/ED
title = title.replace(/^ *『[^』]*』/, "") // OP/ED
return title;
}
function friendlyTimeForSeconds(seconds) {
if (isNaN(seconds) || seconds < 0) return "0:00";
seconds = Math.floor(seconds);
const h = Math.floor(seconds / 3600);
const m = Math.floor((seconds % 3600) / 60);
const s = seconds % 60;
if (h > 0) {
return `${h}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`;
} else {
return `${m}:${s.toString().padStart(2, '0')}`;
}
}
@@ -1,4 +1,5 @@
import "root:/modules/common"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
@@ -17,14 +18,12 @@ Button {
background: Rectangle {
anchors.fill: parent
radius: Appearance.rounding.full
color: (button.down && button.enabled) ? Appearance.colors.colLayer1Active : ((button.hovered && button.enabled) ? Appearance.colors.colLayer1Hover : Appearance.transparentize(Appearance.m3colors.m3surfaceContainerHigh, 1))
color: (button.down && button.enabled) ? Appearance.colors.colLayer1Active :
((button.hovered && button.enabled) ? Appearance.colors.colLayer1Hover :
ColorUtils.transparentize(Appearance.m3colors.m3surfaceContainerHigh, 1))
Behavior on color {
ColorAnimation {
duration: Appearance.animation.elementMove.duration
easing.type: Appearance.animation.elementMove.type
easing.bezierCurve: Appearance.animation.elementMove.bezierCurve
}
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
}
@@ -41,11 +40,7 @@ Button {
color: button.enabled ? Appearance.m3colors.m3primary : Appearance.m3colors.m3outline
Behavior on color {
ColorAnimation {
duration: Appearance.animation.elementMove.duration
easing.type: Appearance.animation.elementMove.type
easing.bezierCurve: Appearance.animation.elementMove.bezierCurve
}
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
}
}
@@ -1,4 +1,5 @@
import "root:/modules/common"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
@@ -16,17 +17,12 @@ Button {
background: Rectangle {
anchors.fill: parent
color: (button.down && button.enabled) ? Appearance.transparentize(Appearance.m3colors.m3onSurface, 0.84) :
((button.hovered && button.enabled) ? Appearance.transparentize(Appearance.m3colors.m3onSurface, 0.92) :
Appearance.transparentize(Appearance.m3colors.m3onSurface, 1))
color: (button.down && button.enabled) ? ColorUtils.transparentize(Appearance.m3colors.m3onSurface, 0.84) :
((button.hovered && button.enabled) ? ColorUtils.transparentize(Appearance.m3colors.m3onSurface, 0.92) :
ColorUtils.transparentize(Appearance.m3colors.m3onSurface, 1))
Behavior on color {
ColorAnimation {
duration: Appearance.animation.elementMove.duration
easing.type: Appearance.animation.elementMove.type
easing.bezierCurve: Appearance.animation.elementMove.bezierCurve
}
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
}
}
@@ -42,11 +38,7 @@ Button {
color: button.enabled ? Appearance.m3colors.m3onSurface : Appearance.m3colors.m3outline
Behavior on color {
ColorAnimation {
duration: Appearance.animation.elementMove.duration
easing.type: Appearance.animation.elementMove.type
easing.bezierCurve: Appearance.animation.elementMove.bezierCurve
}
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
}
}
@@ -1,5 +1,6 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
@@ -16,7 +17,7 @@ Button {
implicitHeight: columnLayout.implicitHeight
implicitWidth: columnLayout.implicitWidth
background: Item {}
background: null
PointingHandInteraction {}
// Real stuff
@@ -30,14 +31,10 @@ Button {
radius: Appearance.rounding.full
color: toggled ?
(button.down ? Appearance.colors.colSecondaryContainerActive : button.hovered ? Appearance.colors.colSecondaryContainerHover : Appearance.m3colors.m3secondaryContainer) :
(button.down ? Appearance.colors.colLayer1Active : button.hovered ? Appearance.colors.colLayer1Hover : Appearance.transparentize(Appearance.colors.colLayer1Hover, 1))
(button.down ? Appearance.colors.colLayer1Active : button.hovered ? Appearance.colors.colLayer1Hover : ColorUtils.transparentize(Appearance.colors.colLayer1Hover, 1))
Behavior on color {
ColorAnimation {
duration: Appearance.animation.elementMove.duration
easing.type: Appearance.animation.elementMove.type
easing.bezierCurve: Appearance.animation.elementMove.bezierCurve
}
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
}
MaterialSymbol {
id: navRailButtonIcon
@@ -48,11 +45,7 @@ Button {
color: toggled ? Appearance.m3colors.m3onSecondaryContainer : Appearance.colors.colOnLayer1
Behavior on color {
ColorAnimation {
duration: Appearance.animation.elementMove.duration
easing.type: Appearance.animation.elementMove.type
easing.bezierCurve: Appearance.animation.elementMove.bezierCurve
}
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
}
}
}
@@ -1,9 +1,11 @@
import "root:/modules/common"
import "root:/services"
import "root:/modules/common/functions/string_utils.js" as StringUtils
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import Qt5Compat.GraphicalEffects
import QtQuick
import QtQuick.Controls
import QtQuick.Effects
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
@@ -126,7 +128,7 @@ Item {
onPressAndHold: (mouse) => {
if (mouse.button === Qt.LeftButton) {
Hyprland.dispatch(`exec wl-copy '${StringUtils.shellSingleQuoteEscape(notificationObject.body)}'`)
notificationSummaryText.text = `${notificationObject.summary} (copied)`
notificationSummaryText.text = String.format(qsTr("{0} (copied)"), notificationObject.summary)
}
}
onDragStartedChanged: () => {
@@ -187,9 +189,19 @@ Item {
height: notificationColumnLayout.implicitHeight
color: (notificationObject.urgency == NotificationUrgency.Critical) ?
Appearance.mix(Appearance.m3colors.m3secondaryContainer, Appearance.colors.colLayer2, 0.35) : Appearance.colors.colLayer2
ColorUtils.mix(Appearance.m3colors.m3secondaryContainer, Appearance.colors.colLayer2, 0.35) : Appearance.colors.colLayer2
radius: Appearance.rounding.normal
layer.enabled: true
layer.effect: MultiEffect {
source: notificationBackground
anchors.fill: notificationBackground
shadowEnabled: popup
shadowColor: Appearance.colors.colShadow
shadowVerticalOffset: 1
shadowBlur: 0.5
}
Behavior on x {
enabled: enableAnimation
NumberAnimation {
@@ -207,20 +219,6 @@ Item {
}
}
}
Loader {
active: popup
anchors.fill: notificationBackground
sourceComponent: DropShadow {
id: notificationShadow
source: notificationBackground
radius: 5
samples: radius * 2 + 1
color: Appearance.colors.colShadow
verticalOffset: 2
horizontalOffset: 0
}
}
}
@@ -289,7 +287,7 @@ Item {
}
anchors.fill: parent
color: (notificationObject.urgency == NotificationUrgency.Critical) ?
Appearance.mix(Appearance.m3colors.m3onSecondary, Appearance.m3colors.m3onSecondaryContainer, 0.1) :
ColorUtils.mix(Appearance.m3colors.m3onSecondary, Appearance.m3colors.m3onSecondaryContainer, 0.1) :
Appearance.m3colors.m3onSecondaryContainer
iconSize: 27
horizontalAlignment: Text.AlignHCenter
@@ -422,17 +420,11 @@ Item {
background: Rectangle {
anchors.fill: parent
radius: Appearance.rounding.full
color: (expandButton.down) ? Appearance.colors.colLayer2Active : (expandButton.hovered ? Appearance.colors.colLayer2Hover : Appearance.transparentize(Appearance.colors.colLayer2, 1))
color: (expandButton.down) ? Appearance.colors.colLayer2Active : (expandButton.hovered ? Appearance.colors.colLayer2Hover : ColorUtils.transparentize(Appearance.colors.colLayer2, 1))
Behavior on color {
ColorAnimation {
duration: Appearance.animation.elementMoveFast.duration
easing.type: Appearance.animation.elementMoveFast.type
easing.bezierCurve: Appearance.animation.elementMoveFast.bezierCurve
}
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
}
}
contentItem: MaterialSymbol {
@@ -52,38 +52,31 @@ ColumnLayout {
root.enableIndicatorAnimation = true
}
}
Rectangle {
id: indicator
property int tabCount: root.tabButtonList.length
property real fullTabSize: root.width / tabCount;
property real targetWidth: tabBar.contentItem.children[0].children[tabBar.currentIndex].tabContentWidth
implicitWidth: targetWidth
anchors {
top: parent.top
bottom: parent.bottom
}
x: tabBar.currentIndex * fullTabSize + (fullTabSize - targetWidth) / 2
color: Appearance.m3colors.m3primary
radius: Appearance.rounding.full
z: 2
anchors.fill: parent
// TODO: make the end point in the moving direction go first
anchors.leftMargin: {
const tabCount = root.tabButtonList.length
const targetWidth = tabBar.contentItem.children[0].children[tabBar.currentIndex].tabContentWidth
const fullTabSize = root.width / tabCount;
return fullTabSize * root.externalTrackedTab + (fullTabSize - targetWidth) / 2;
Behavior on x {
animation: Appearance.animation.elementMove.numberAnimation.createObject(this)
}
anchors.rightMargin: {
const tabCount = root.tabButtonList.length
const targetWidth = tabBar.contentItem.children[0].children[tabBar.currentIndex].tabContentWidth
const fullTabSize = root.width / tabCount;
return fullTabSize * (tabCount - root.externalTrackedTab - 1) + (fullTabSize - targetWidth) / 2;
Behavior on implicitWidth {
animation: Appearance.animation.elementMove.numberAnimation.createObject(this)
}
Behavior on anchors.leftMargin {
enabled: root.enableIndicatorAnimation
SmoothedAnimation {
velocity: Appearance.animation.positionShift.velocity
}
}
Behavior on anchors.rightMargin {
enabled: root.enableIndicatorAnimation
SmoothedAnimation {
velocity: Appearance.animation.positionShift.velocity
}
}
}
}
@@ -1,5 +1,7 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import Qt5Compat.GraphicalEffects
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
@@ -12,24 +14,108 @@ TabButton {
property string buttonIcon
property bool selected: false
property int tabContentWidth: contentItem.children[0].implicitWidth
property int rippleDuration: 1200
height: buttonBackground.height
PointingHandInteraction {}
component RippleAnim: NumberAnimation {
duration: rippleDuration
easing.type: Appearance.animation.elementMoveEnter.type
easing.bezierCurve: Appearance.animationCurves.standardDecel
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onPressed: (event) => {
const {x,y} = event
const stateY = buttonBackground.y;
rippleAnim.x = x;
rippleAnim.y = y - stateY;
const dist = (ox,oy) => ox*ox + oy*oy
const stateEndY = stateY + buttonBackground.height
rippleAnim.radius = Math.sqrt(Math.max(dist(0, stateY), dist(0, stateEndY), dist(width, stateY), dist(width, stateEndY)))
rippleFadeAnim.complete();
rippleAnim.restart();
}
onReleased: (event) => {
button.click() // Because the MouseArea already consumed the event
rippleFadeAnim.restart();
}
}
RippleAnim {
id: rippleFadeAnim
target: ripple
property: "opacity"
to: 0
}
SequentialAnimation {
id: rippleAnim
property real x
property real y
property real radius
PropertyAction {
target: ripple
property: "x"
value: rippleAnim.x
}
PropertyAction {
target: ripple
property: "y"
value: rippleAnim.y
}
PropertyAction {
target: ripple
property: "opacity"
value: 1
}
ParallelAnimation {
RippleAnim {
target: ripple
properties: "implicitWidth,implicitHeight"
from: 0
to: rippleAnim.radius * 2
}
}
}
background: Rectangle {
id: buttonBackground
radius: Appearance.rounding.small
implicitHeight: 50
color: (button.down ? Appearance.colors.colLayer1Active : button.hovered ? Appearance.colors.colLayer1Hover : Appearance.transparentize(Appearance.colors.colLayer1Hover, 1))
color: (button.hovered ? Appearance.colors.colLayer1Hover : ColorUtils.transparentize(Appearance.colors.colLayer1Hover, 1))
layer.enabled: true
layer.effect: OpacityMask {
maskSource: Rectangle {
width: buttonBackground.width
height: buttonBackground.height
radius: buttonBackground.radius
}
}
Behavior on color {
ColorAnimation {
duration: Appearance.animation.elementMove.duration
easing.type: Appearance.animation.elementMove.type
easing.bezierCurve: Appearance.animation.elementMove.bezierCurve
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
}
Rectangle {
id: ripple
radius: Appearance.rounding.full
color: Appearance.colors.colLayer1Active
opacity: 0
transform: Translate {
x: -ripple.width / 2
y: -ripple.height / 2
}
}
}
contentItem: Item {
anchors.centerIn: buttonBackground
ColumnLayout {
@@ -44,11 +130,7 @@ TabButton {
fill: selected ? 1 : 0
color: selected ? Appearance.m3colors.m3primary : Appearance.colors.colOnLayer1
Behavior on color {
ColorAnimation {
duration: Appearance.animation.elementMove.duration
easing.type: Appearance.animation.elementMove.type
easing.bezierCurve: Appearance.animation.elementMove.bezierCurve
}
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
}
}
StyledText {
@@ -59,11 +141,7 @@ TabButton {
color: selected ? Appearance.m3colors.m3primary : Appearance.colors.colOnLayer1
text: buttonText
Behavior on color {
ColorAnimation {
duration: Appearance.animation.elementMove.duration
easing.type: Appearance.animation.elementMove.type
easing.bezierCurve: Appearance.animation.elementMove.bezierCurve
}
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
}
}
}
@@ -16,18 +16,10 @@ Item {
Behavior on implicitWidth {
enabled: !vertical
NumberAnimation {
duration: Appearance.animation.elementMoveEnter.duration
easing.type: Appearance.animation.elementMoveEnter.type
easing.bezierCurve: Appearance.animation.elementMoveEnter.bezierCurve
}
animation: Appearance.animation.elementMoveEnter.numberAnimation.createObject(this)
}
Behavior on implicitHeight {
enabled: vertical
NumberAnimation {
duration: Appearance.animation.elementMoveEnter.duration
easing.type: Appearance.animation.elementMoveEnter.type
easing.bezierCurve: Appearance.animation.elementMoveEnter.bezierCurve
}
animation: Appearance.animation.elementMoveEnter.numberAnimation.createObject(this)
}
}
@@ -1,5 +1,7 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import Qt5Compat.GraphicalEffects
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
@@ -11,25 +13,111 @@ TabButton {
property string buttonText
property string buttonIcon
property bool selected: false
property int rippleDuration: 1200
height: buttonBackground.height
property int tabContentWidth: buttonBackground.width - buttonBackground.radius*2
PointingHandInteraction {}
component RippleAnim: NumberAnimation {
duration: rippleDuration
easing.type: Appearance.animation.elementMoveEnter.type
easing.bezierCurve: Appearance.animationCurves.standardDecel
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onPressed: (event) => {
const {x,y} = event
const stateY = buttonBackground.y;
rippleAnim.x = x;
rippleAnim.y = y - stateY;
const dist = (ox,oy) => ox*ox + oy*oy
const stateEndY = stateY + buttonBackground.height
rippleAnim.radius = Math.sqrt(Math.max(dist(0, stateY), dist(0, stateEndY), dist(width, stateY), dist(width, stateEndY)))
rippleFadeAnim.complete();
rippleAnim.restart();
}
onReleased: (event) => {
button.click() // Because the MouseArea already consumed the event
rippleFadeAnim.restart();
}
}
RippleAnim {
id: rippleFadeAnim
target: ripple
property: "opacity"
to: 0
}
SequentialAnimation {
id: rippleAnim
property real x
property real y
property real radius
PropertyAction {
target: ripple
property: "x"
value: rippleAnim.x
}
PropertyAction {
target: ripple
property: "y"
value: rippleAnim.y
}
PropertyAction {
target: ripple
property: "opacity"
value: 1
}
ParallelAnimation {
RippleAnim {
target: ripple
properties: "implicitWidth,implicitHeight"
from: 0
to: rippleAnim.radius * 2
}
}
}
background: Rectangle {
id: buttonBackground
radius: Appearance.rounding.small
implicitHeight: 37
color: (button.down ? Appearance.colors.colLayer1Active : button.hovered ? Appearance.colors.colLayer1Hover : Appearance.transparentize(Appearance.colors.colLayer1Hover, 1))
color: (button.hovered ? Appearance.colors.colLayer1Hover : ColorUtils.transparentize(Appearance.colors.colLayer1Hover, 1))
layer.enabled: true
layer.effect: OpacityMask {
maskSource: Rectangle {
width: buttonBackground.width
height: buttonBackground.height
radius: buttonBackground.radius
}
}
Behavior on color {
ColorAnimation {
duration: Appearance.animation.elementMove.duration
easing.type: Appearance.animation.elementMove.type
easing.bezierCurve: Appearance.animation.elementMove.bezierCurve
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
}
Rectangle {
id: ripple
radius: Appearance.rounding.full
color: Appearance.colors.colLayer1Active
opacity: 0
transform: Translate {
x: -ripple.width / 2
y: -ripple.height / 2
}
}
}
contentItem: Item {
anchors.centerIn: buttonBackground
RowLayout {
@@ -52,11 +140,7 @@ TabButton {
fill: selected ? 1 : 0
color: selected ? Appearance.m3colors.m3primary : Appearance.colors.colOnLayer1
Behavior on color {
ColorAnimation {
duration: Appearance.animation.elementMove.duration
easing.type: Appearance.animation.elementMove.type
easing.bezierCurve: Appearance.animation.elementMove.bezierCurve
}
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
}
}
}
@@ -67,11 +151,7 @@ TabButton {
color: selected ? Appearance.m3colors.m3primary : Appearance.colors.colOnLayer1
text: buttonText
Behavior on color {
ColorAnimation {
duration: Appearance.animation.elementMove.duration
easing.type: Appearance.animation.elementMove.type
easing.bezierCurve: Appearance.animation.elementMove.bezierCurve
}
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
}
}
}
@@ -13,13 +13,11 @@ ProgressBar {
property real valueBarWidth: 120
property real valueBarHeight: 4
property real valueBarGap: 4
property color highlightColor: Appearance.m3colors.m3primary
property color trackColor: Appearance.m3colors.m3secondaryContainer
Behavior on value {
NumberAnimation {
duration: Appearance.animation.elementMoveEnter.duration
easing.type: Appearance.animation.elementMoveEnter.type
easing.bezierCurve: Appearance.animation.elementMoveEnter.bezierCurve
}
animation: Appearance.animation.elementMoveEnter.numberAnimation.createObject(this)
}
background: Rectangle {
@@ -38,21 +36,21 @@ ProgressBar {
width: root.visualPosition * parent.width
height: parent.height
radius: Appearance.rounding.full
color: Appearance.m3colors.m3primary
color: root.highlightColor
}
Rectangle { // Right remaining part fill
anchors.right: parent.right
width: (1 - root.visualPosition) * parent.width - valueBarGap
height: parent.height
radius: Appearance.rounding.full
color: Appearance.m3colors.m3secondaryContainer
color: root.trackColor
}
Rectangle { // Stop point
anchors.right: parent.right
width: valueBarGap
height: valueBarGap
radius: Appearance.rounding.full
color: Appearance.m3colors.m3primary
color: root.highlightColor
}
}
}
@@ -16,8 +16,13 @@ Slider {
property real handleWidth: (slider.pressed ? 3 : 5) * scale
property real handleHeight: 44 * scale
property real handleLimit: slider.backgroundDotMargins * scale
property real trackHeight: 15 * scale
property color highlightColor: Appearance.m3colors.m3primary
property color trackColor: Appearance.m3colors.m3secondaryContainer
property color handleColor: Appearance.m3colors.m3onSecondaryContainer
property real limitedHandleRangeWidth: (slider.availableWidth - handleWidth - slider.handleLimit * 2)
property string tooltipContent: `${Math.round(value * 100)}%`
Layout.fillWidth: true
from: 0
to: 1
@@ -44,14 +49,15 @@ Slider {
background: Item {
anchors.verticalCenter: parent.verticalCenter
implicitHeight: 12 // Somehow binding this makes it fill height. Must be set with a constant like this
implicitHeight: trackHeight
// Fill left
Rectangle {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
width: slider.handleLimit + slider.visualPosition * slider.limitedHandleRangeWidth - (slider.handleMargins + slider.handleWidth / 2)
height: parent.height
color: Appearance.m3colors.m3primary
height: trackHeight
color: slider.highlightColor
topLeftRadius: Appearance.rounding.full
bottomLeftRadius: Appearance.rounding.full
topRightRadius: Appearance.rounding.unsharpen
@@ -60,10 +66,11 @@ Slider {
// Fill right
Rectangle {
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
width: slider.handleLimit + (1 - slider.visualPosition) * slider.limitedHandleRangeWidth - (slider.handleMargins + slider.handleWidth / 2)
height: parent.height
color: Appearance.m3colors.m3secondaryContainer
height: trackHeight
color: slider.trackColor
topLeftRadius: Appearance.rounding.unsharpen
bottomLeftRadius: Appearance.rounding.unsharpen
topRightRadius: Appearance.rounding.full
@@ -78,7 +85,7 @@ Slider {
width: slider.backgroundDotSize
height: slider.backgroundDotSize
radius: Appearance.rounding.full
color: Appearance.m3colors.m3onSecondaryContainer
color: slider.handleColor
}
}
@@ -89,7 +96,7 @@ Slider {
implicitWidth: slider.handleWidth
implicitHeight: slider.handleHeight
radius: Appearance.rounding.full
color: Appearance.m3colors.m3onSecondaryContainer
color: slider.handleColor
Behavior on implicitWidth {
NumberAnimation {
@@ -101,7 +108,7 @@ Slider {
StyledToolTip {
extraVisibleCondition: slider.pressed
content: `${Math.round(slider.value * 100)}%`
content: slider.tooltipContent
}
}
}
@@ -22,18 +22,10 @@ Switch {
border.color: root.checked ? Appearance.m3colors.m3primary : Appearance.m3colors.m3outline
Behavior on color {
ColorAnimation {
duration: Appearance.animation.elementMove.duration
easing.type: Appearance.animation.elementMove.type
easing.bezierCurve: Appearance.animation.elementMove.bezierCurve
}
animation: Appearance.animation.elementMove.colorAnimation.createObject(this)
}
Behavior on border.color {
ColorAnimation {
duration: Appearance.animation.elementMove.duration
easing.type: Appearance.animation.elementMove.type
easing.bezierCurve: Appearance.animation.elementMove.bezierCurve
}
animation: Appearance.animation.elementMove.colorAnimation.createObject(this)
}
}
@@ -48,32 +40,16 @@ Switch {
anchors.leftMargin: root.checked ? (root.pressed ? (22 * root.scale) : 24 * root.scale) : (root.pressed ? (2 * root.scale) : 8 * root.scale)
Behavior on anchors.leftMargin {
NumberAnimation {
duration: Appearance.animation.elementMove.duration
easing.type: Appearance.animation.elementMove.type
easing.bezierCurve: Appearance.animation.elementMove.bezierCurve
}
animation: Appearance.animation.elementMove.numberAnimation.createObject(this)
}
Behavior on width {
NumberAnimation {
duration: Appearance.animation.elementMove.duration
easing.type: Appearance.animation.elementMove.type
easing.bezierCurve: Appearance.animation.elementMove.bezierCurve
}
animation: Appearance.animation.elementMove.numberAnimation.createObject(this)
}
Behavior on height {
NumberAnimation {
duration: Appearance.animation.elementMove.duration
easing.type: Appearance.animation.elementMove.type
easing.bezierCurve: Appearance.animation.elementMove.bezierCurve
}
animation: Appearance.animation.elementMove.numberAnimation.createObject(this)
}
Behavior on color {
ColorAnimation {
duration: Appearance.animation.elementMove.duration
easing.type: Appearance.animation.elementMove.type
easing.bezierCurve: Appearance.animation.elementMove.bezierCurve
}
animation: Appearance.animation.elementMove.colorAnimation.createObject(this)
}
}
}
@@ -26,7 +26,7 @@ ToolTip {
}
}
background: Item {}
background: null
contentItem: Item {
id: contentItemBackground