diff --git a/Assets/Matugen/templates/vesktop.css b/Assets/Matugen/templates/vesktop.css index 9876c8a..ac5b166 100644 --- a/Assets/Matugen/templates/vesktop.css +++ b/Assets/Matugen/templates/vesktop.css @@ -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; } diff --git a/Widgets/NColorPicker.qml b/Widgets/NColorPicker.qml index 8dd348e..112932f 100644 --- a/Widgets/NColorPicker.qml +++ b/Widgets/NColorPicker.qml @@ -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] } } }