Merge branch 'main' of github.com:noctalia-dev/noctalia-shell

This commit is contained in:
LemmyCook
2025-09-05 21:04:09 -04:00
2 changed files with 498 additions and 115 deletions

View File

@@ -510,7 +510,7 @@
}
.visual-refresh.theme-dark .slateTextArea_ec4baf > div:first-child .emptyText__1464f::before {
content: "Message #general" !important;
content: "send a message" !important;
color: {{colors.on_surface_variant.default.hex}} !important;
}

View File

@@ -9,51 +9,98 @@ Rectangle {
property color selectedColor: "#000000"
property bool expanded: false
property real scaling: 1.0
property real currentHue: 0
property real currentSaturation: 0
signal colorSelected(color color)
signal colorCancelled
implicitWidth: expanded ? 320 * scaling : 150 * scaling
implicitHeight: expanded ? 300 * scaling : 40 * scaling
implicitWidth: 150 * scaling
implicitHeight: 40 * scaling
radius: Style.radiusM * scaling
radius: Style.radiusM
color: Color.mSurface
border.color: Color.mOutline
border.width: Math.max(1, Style.borderS * scaling)
border.width: Math.max(1, Style.borderS)
property var presetColors: [Color.mPrimary, Color.mSecondary, Color.mTertiary, Color.mError, Color.mSurface, Color.mSurfaceVariant, Color.mOutline, "#FFFFFF", "#000000", "#F44336", "#E91E63", "#9C27B0", "#673AB7", "#3F51B5", "#2196F3", "#03A9F4", "#00BCD4", "#009688", "#4CAF50", "#8BC34A", "#CDDC39", "#FFEB3B", "#FFC107", "#FF9800", "#FF5722", "#795548", "#9E9E9E"]
Behavior on implicitWidth {
NumberAnimation {
duration: Style.animationFast
function rgbToHsv(r, g, b) {
r /= 255
g /= 255
b /= 255
var max = Math.max(r, g, b), min = Math.min(r, g, b)
var h, s, v = max
var d = max - min
s = max === 0 ? 0 : d / max
if (max === min) {
h = 0
} else {
switch (max) {
case r:
h = (g - b) / d + (g < b ? 6 : 0)
break
case g:
h = (b - r) / d + 2
break
case b:
h = (r - g) / d + 4
break
}
h /= 6
}
return [h * 360, s * 100, v * 100]
}
Behavior on implicitHeight {
NumberAnimation {
duration: Style.animationFast
function hsvToRgb(h, s, v) {
h /= 360
s /= 100
v /= 100
var r, g, b
var i = Math.floor(h * 6)
var f = h * 6 - i
var p = v * (1 - s)
var q = v * (1 - f * s)
var t = v * (1 - (1 - f) * s)
switch (i % 6) {
case 0:
r = vg = tb = p
break
case 1:
r = qg = vb = p
break
case 2:
r = pg = vb = t
break
case 3:
r = pg = qb = v
break
case 4:
r = tg = pb = v
break
case 5:
r = vg = pb = q
break
}
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]
}
// Collapsed view - just show current color
MouseArea {
visible: !root.expanded
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: root.expanded = true
onClicked: colorPickerPopup.open()
RowLayout {
anchors.fill: parent
anchors.margins: Style.marginS * scaling
spacing: Style.marginS * scaling
anchors.margins: Style.marginS
spacing: Style.marginS
Rectangle {
Layout.preferredWidth: 24 * scaling
Layout.preferredHeight: 24 * scaling
Layout.preferredWidth: 24
Layout.preferredHeight: 24
radius: Layout.preferredWidth * 0.5
color: root.selectedColor
border.color: Color.mOutline
border.width: Math.max(1, Style.borderS * scaling)
border.width: Math.max(1, Style.borderS)
}
NText {
@@ -69,118 +116,454 @@ Rectangle {
}
}
// Expanded view - color selection
ColumnLayout {
visible: root.expanded
anchors.fill: parent
anchors.margins: Style.marginM * scaling
spacing: Style.marginS * scaling
Popup {
id: colorPickerPopup
// Header
RowLayout {
Layout.fillWidth: true
width: 580 * scaling
height: 750 * scaling
x: (parent.width - width) / 2
y: (parent.height - height) / 2
modal: true
clip: true
NText {
text: "Select Color"
font.weight: Style.fontWeightBold
Layout.fillWidth: true
}
NIconButton {
icon: "close"
onClicked: root.expanded = false
}
background: Rectangle {
color: Color.mSurface
radius: 12 * scaling
border.color: Color.mPrimary
border.width: 2 * scaling
}
// Preset colors grid
Grid {
columns: 9
spacing: Style.marginXS * scaling
Layout.fillWidth: true
ScrollView {
id: scrollView
anchors.fill: parent
anchors.margins: 24 * scaling
Repeater {
model: root.presetColors
ScrollBar.vertical.policy: ScrollBar.AlwaysOff
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
clip: true
ColumnLayout {
width: scrollView.availableWidth
spacing: 20 * scaling
// Header
RowLayout {
Layout.fillWidth: true
Layout.topMargin: 10 * scaling
RowLayout {
spacing: 8 * scaling
NIcon {
text: "palette"
font.pointSize: 20 * scaling
color: Color.mPrimary
}
NText {
text: "Color Picker"
font.pointSize: 20 * scaling
font.weight: Font.Bold
color: Color.mPrimary
}
}
Item {
Layout.fillWidth: true
}
NIconButton {
icon: "close"
onClicked: colorPickerPopup.close()
}
}
// Color preview section
Rectangle {
width: Math.round(29 * scaling)
height: width
radius: Style.radiusXS * scaling
color: modelData
border.color: root.selectedColor === modelData ? Color.mPrimary : Color.mOutline
border.width: root.selectedColor === modelData ? 2 : 1
Layout.fillWidth: true
Layout.preferredHeight: 100 * scaling
radius: 8 * scaling
color: root.selectedColor
border.color: Color.mOutline
border.width: 1 * scaling
MouseArea {
ColumnLayout {
anchors.centerIn: parent
spacing: 5 * scaling
NText {
text: root.selectedColor.toString().toUpperCase()
font.family: Settings.data.ui.fontFixed
font.pointSize: 18 * scaling
font.weight: Font.Bold
color: root.selectedColor.r + root.selectedColor.g + root.selectedColor.b > 1.5 ? "#000000" : "#FFFFFF"
horizontalAlignment: Text.AlignHCenter
}
NText {
text: "RGB(" + Math.round(root.selectedColor.r * 255) + ", " + Math.round(
root.selectedColor.g * 255) + ", " + Math.round(root.selectedColor.b * 255) + ")"
font.family: Settings.data.ui.fontFixed
font.pointSize: 12 * scaling
color: root.selectedColor.r + root.selectedColor.g + root.selectedColor.b > 1.5 ? "#000000" : "#FFFFFF"
horizontalAlignment: Text.AlignHCenter
}
}
}
NDivider {
Layout.fillWidth: true
}
// Hex input
ColumnLayout {
Layout.fillWidth: true
spacing: 8 * scaling
NLabel {
label: "Hex Color"
description: "Enter a hexadecimal color code"
Layout.fillWidth: true
}
NTextInput {
text: root.selectedColor.toString().toUpperCase()
fontFamily: Settings.data.ui.fontFixed
Layout.fillWidth: true
onEditingFinished: {
if (/^#[0-9A-F]{6}$/i.test(text)) {
root.selectedColor = text
}
}
}
}
NDivider {
Layout.fillWidth: true
}
// RGB sliders section
NBox {
Layout.fillWidth: true
Layout.preferredHeight: 240 * scaling
ColumnLayout {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
anchors.margins: 15 * scaling
spacing: 10 * scaling
NLabel {
label: "RGB Values"
description: "Adjust red, green, blue, and brightness values"
Layout.fillWidth: true
}
RowLayout {
Layout.fillWidth: true
spacing: 15 * scaling
NText {
text: "R"
font.weight: Font.Bold
Layout.preferredWidth: 20 * scaling
}
NSlider {
id: redSlider
Layout.fillWidth: true
from: 0
to: 255
value: Math.round(root.selectedColor.r * 255)
onMoved: {
root.selectedColor = Qt.rgba(value / 255, root.selectedColor.g, root.selectedColor.b, 1)
var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255,
root.selectedColor.b * 255)
root.currentHue = hsv[0]
root.currentSaturation = hsv[1]
}
}
NText {
text: Math.round(redSlider.value)
font.family: Settings.data.ui.fontFixed
Layout.preferredWidth: 30 * scaling
}
}
RowLayout {
Layout.fillWidth: true
spacing: 15 * scaling
NText {
text: "G"
font.weight: Font.Bold
Layout.preferredWidth: 20 * scaling
}
NSlider {
id: greenSlider
Layout.fillWidth: true
from: 0
to: 255
value: Math.round(root.selectedColor.g * 255)
onMoved: {
root.selectedColor = Qt.rgba(root.selectedColor.r, value / 255, root.selectedColor.b, 1)
// Update stored hue and saturation when RGB changes
var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255,
root.selectedColor.b * 255)
root.currentHue = hsv[0]
root.currentSaturation = hsv[1]
}
}
NText {
text: Math.round(greenSlider.value)
font.family: Settings.data.ui.fontFixed
Layout.preferredWidth: 30 * scaling
}
}
RowLayout {
Layout.fillWidth: true
spacing: 15 * scaling
NText {
text: "B"
font.weight: Font.Bold
Layout.preferredWidth: 20 * scaling
}
NSlider {
id: blueSlider
Layout.fillWidth: true
from: 0
to: 255
value: Math.round(root.selectedColor.b * 255)
onMoved: {
root.selectedColor = Qt.rgba(root.selectedColor.r, root.selectedColor.g, value / 255, 1)
// Update stored hue and saturation when RGB changes
var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255,
root.selectedColor.b * 255)
root.currentHue = hsv[0]
root.currentSaturation = hsv[1]
}
}
NText {
text: Math.round(blueSlider.value)
font.family: Settings.data.ui.fontFixed
Layout.preferredWidth: 30 * scaling
}
}
RowLayout {
Layout.fillWidth: true
spacing: 15 * scaling
NText {
text: "Brightness"
font.weight: Font.Bold
Layout.preferredWidth: 80 * scaling
}
NSlider {
id: brightnessSlider
Layout.fillWidth: true
from: 0
to: 100
value: {
var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255,
root.selectedColor.b * 255)
return hsv[2]
}
onMoved: {
var hue = root.currentHue
var saturation = root.currentSaturation
if (hue === 0 && saturation === 0) {
var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255,
root.selectedColor.b * 255)
hue = hsv[0]
saturation = hsv[1]
root.currentHue = hue
root.currentSaturation = saturation
}
var rgb = root.hsvToRgb(hue, saturation, value)
root.selectedColor = Qt.rgba(rgb[0] / 255, rgb[1] / 255, rgb[2] / 255, 1)
}
}
NText {
text: Math.round(brightnessSlider.value) + "%"
font.family: Settings.data.ui.fontFixed
Layout.preferredWidth: 40 * scaling
}
}
}
}
NDivider {
Layout.fillWidth: true
}
NBox {
Layout.fillWidth: true
Layout.preferredHeight: 120 * scaling
ColumnLayout {
anchors.fill: parent
anchors.margins: 15 * scaling
spacing: 10 * scaling
NLabel {
label: "Theme Colors"
description: "Quick access to your theme's color palette"
Layout.fillWidth: true
}
Flow {
spacing: 6 * scaling
Layout.fillWidth: true
flow: Flow.LeftToRight
Repeater {
model: [Color.mPrimary, Color.mSecondary, Color.mTertiary, Color.mError, Color.mSurface, Color.mSurfaceVariant, Color.mOutline, "#FFFFFF", "#000000"]
Rectangle {
width: 24 * scaling
height: 24 * scaling
radius: 4 * scaling
color: modelData
border.color: root.selectedColor === modelData ? Color.mPrimary : Color.mOutline
border.width: root.selectedColor === modelData ? 2 * scaling : 1 * scaling
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
root.selectedColor = modelData
var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255,
root.selectedColor.b * 255)
root.currentHue = hsv[0]
root.currentSaturation = hsv[1]
}
}
}
}
}
}
}
NDivider {
Layout.fillWidth: true
}
NBox {
Layout.fillWidth: true
Layout.preferredHeight: 170 * scaling
ColumnLayout {
anchors.fill: parent
anchors.margins: 15 * scaling
spacing: 10 * scaling
NLabel {
label: "Color Palettes"
description: "Choose from a wide range of predefined colors"
Layout.fillWidth: true
}
Flow {
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 6 * scaling
flow: Flow.LeftToRight
Repeater {
model: ["#F44336", "#E91E63", "#9C27B0", "#673AB7", "#3F51B5", "#2196F3", "#03A9F4", "#00BCD4", "#009688", "#4CAF50", "#8BC34A", "#CDDC39", "#FFEB3B", "#FFC107", "#FF9800", "#FF5722", "#795548", "#9E9E9E", "#E74C3C", "#C0392B", "#E67E22", "#D35400", "#F39C12", "#F1C40F", "#2ECC71", "#27AE60", "#1ABC9C", "#16A085", "#3498DB", "#2980B9", "#9B59B6", "#8E44AD", "#34495E", "#2C3E50", "#95A5A6", "#7F8C8D", "#FFFFFF", "#000000"]
Rectangle {
width: 24 * scaling
height: 24 * scaling
radius: 4 * scaling
color: modelData
border.color: root.selectedColor === modelData ? Color.mPrimary : Color.mOutline
border.width: root.selectedColor === modelData ? 2 * scaling : 1 * scaling
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
root.selectedColor = modelData
var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255,
root.selectedColor.b * 255)
root.currentHue = hsv[0]
root.currentSaturation = hsv[1]
}
}
}
}
}
}
}
RowLayout {
Layout.fillWidth: true
Layout.topMargin: 20 * scaling
Layout.bottomMargin: 20 * scaling
spacing: 10 * scaling
Item {
Layout.fillWidth: true
}
NButton {
text: "Cancel"
icon: "close"
outlined: true
customHeight: 36 * scaling
customWidth: 100 * scaling
onClicked: {
root.selectedColor = modelData
// root.colorSelected(modelData)
root.colorCancelled()
colorPickerPopup.close()
}
}
NButton {
text: "Apply"
icon: "check"
customHeight: 36 * scaling
customWidth: 100 * scaling
onClicked: {
root.colorSelected(root.selectedColor)
colorPickerPopup.close()
}
}
}
}
}
}
// Custom color input
RowLayout {
Layout.fillWidth: true
spacing: Style.marginS * scaling
NTextInput {
id: hexInput
label: "Hex Color"
text: root.selectedColor.toString().toUpperCase()
fontFamily: Settings.data.ui.fontFixed
Layout.minimumWidth: 100 * scaling
onEditingFinished: {
if (/^#[0-9A-F]{6}$/i.test(text)) {
root.selectedColor = text
root.colorSelected(text)
}
}
}
Rectangle {
Layout.preferredWidth: 32 * scaling
Layout.preferredHeight: 32 * scaling
radius: Layout.preferredWidth * 0.5
color: root.selectedColor
border.color: Color.mOutline
border.width: 1
Layout.alignment: Qt.AlignBottom
Layout.bottomMargin: 5 * scaling
}
NSlider {
id: hueSlider
visible: false
from: 0
to: 360
value: {
var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255)
return hsv[0]
}
}
// Action buttons row
RowLayout {
Layout.fillWidth: true
spacing: Style.marginS * scaling
Item {
Layout.fillWidth: true
} // Spacer
NButton {
text: "Cancel"
outlined: true
customHeight: Style.baseWidgetSize * scaling
fontSize: Style.fontSizeS * scaling
onClicked: {
root.colorCancelled()
root.expanded = false
}
}
NButton {
text: "Apply"
customHeight: Style.baseWidgetSize * scaling
fontSize: Style.fontSizeS * scaling
onClicked: {
root.colorSelected(root.selectedColor)
root.expanded = false
}
}
NSlider {
id: saturationSlider
visible: false
from: 0
to: 100
value: {
var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255)
return hsv[1]
}
}
}