Merge branch 'main' into addon-i18n

This commit is contained in:
end-4
2025-07-17 17:15:52 +02:00
committed by GitHub
180 changed files with 1000 additions and 1275 deletions
@@ -3,7 +3,7 @@ $entry_background_color = rgba({{colors.on_primary_fixed.default.hex_stripped}}1
$entry_border_color = rgba({{colors.outline.default.hex_stripped}}55)
$entry_color = rgba({{colors.primary_fixed.default.hex_stripped}}FF)
$font_family = Rubik
$font_family_clock = Space Grotesk
$font_family_clock = Space Grotesk DemiBold
$font_material_symbols = Material Symbols Rounded
background {
+2 -2
View File
@@ -1,5 +1,5 @@
import "root:/modules/common/"
import "root:/"
import qs.modules.common
import qs
import QtQuick
import Quickshell
import Quickshell.Hyprland
+1 -1
View File
@@ -3,7 +3,7 @@ pragma Singleton
import QtQuick
import Quickshell
import Quickshell.Io
import "root:/modules/common/"
import qs.modules.common
Singleton {
id: root
@@ -1,12 +1,11 @@
pragma ComponentBehavior: Bound
import "root:/"
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/services"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import qs
import qs.services
import qs.modules.common
import qs.modules.common.widgets
import qs.modules.common.functions as CF
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
@@ -48,7 +47,7 @@ Scope {
// Colors
property color dominantColor: Appearance.colors.colPrimary
property bool dominantColorIsDark: dominantColor.hslLightness < 0.5
property color colText: ColorUtils.colorWithLightness(Appearance.colors.colPrimary, (dominantColorIsDark ? 0.8 : 0.12))
property color colText: CF.ColorUtils.colorWithLightness(Appearance.colors.colPrimary, (dominantColorIsDark ? 0.8 : 0.12))
// Layer props
screen: modelData
@@ -194,8 +193,8 @@ Scope {
horizontalAlignment: bgRoot.textHorizontalAlignment
font {
family: Appearance.font.family.expressive
pixelSize: 85
weight: Font.Medium
pixelSize: 90
weight: Font.Bold
}
color: bgRoot.colText
style: Text.Raised
@@ -208,7 +207,7 @@ Scope {
font {
family: Appearance.font.family.expressive
pixelSize: 20
weight: Font.Medium
weight: Font.DemiBold
}
color: bgRoot.colText
style: Text.Raised
@@ -1,7 +1,7 @@
import "root:/services"
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/"
import qs.services
import qs.modules.common
import qs.modules.common.widgets
import qs
import QtQuick
import QtQuick.Layouts
import Quickshell.Wayland
+5 -7
View File
@@ -1,18 +1,16 @@
import "root:/"
import "root:/services"
import "root:/modules/common/"
import "root:/modules/common/widgets"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import "./weather"
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Qt5Compat.GraphicalEffects
import Quickshell
import Quickshell.Io
import Quickshell.Wayland
import Quickshell.Hyprland
import Quickshell.Services.UPower
import qs
import qs.services
import qs.modules.common
import qs.modules.common.widgets
import qs.modules.common.functions
Scope {
id: bar
@@ -1,6 +1,6 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/services"
import qs.modules.common
import qs.modules.common.widgets
import qs.services
import QtQuick
import QtQuick.Layouts
@@ -1,11 +1,8 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/services"
import qs.modules.common
import qs.modules.common.widgets
import qs.services
import QtQuick
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
import Quickshell.Services.UPower
Item {
id: root
@@ -1,11 +1,6 @@
import "root:/modules/common"
import "root:/modules/common/widgets/"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import qs.modules.common
import qs.modules.common.widgets
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
RippleButton {
id: button
@@ -1,6 +1,6 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/services"
import qs.modules.common
import qs.modules.common.widgets
import qs.services
import QtQuick
import QtQuick.Layouts
+6 -7
View File
@@ -1,12 +1,11 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/services"
import "root:/"
import "root:/modules/common/functions/string_utils.js" as StringUtils
import qs.modules.common
import qs.modules.common.widgets
import qs.services
import qs
import qs.modules.common.functions
import QtQuick
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
import Quickshell.Services.Mpris
import Quickshell.Hyprland
@@ -1,9 +1,7 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import qs.modules.common
import qs.modules.common.widgets
import QtQuick
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
Item {
required property string iconName
@@ -1,11 +1,8 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/services"
import qs.modules.common
import qs.modules.common.widgets
import qs.services
import QtQuick
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
import Quickshell.Services.Mpris
Item {
id: root
@@ -1,8 +1,7 @@
import "root:/"
import "root:/modules/common"
import "root:/modules/common/widgets"
import qs
import qs.modules.common
import qs.modules.common.widgets
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Revealer { // Scroll hint
@@ -1,11 +1,8 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import qs.modules.common
import qs.modules.common.widgets
import QtQuick
import QtQuick.Layouts
import Quickshell.Hyprland
import Quickshell.Services.SystemTray
import Quickshell.Wayland
import Quickshell.Widgets
// TODO: More fancy animation
Item {
@@ -1,5 +1,5 @@
import "root:/modules/common/"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import qs.modules.common
import qs.modules.common.functions
import QtQuick
import QtQuick.Layouts
import Quickshell
@@ -1,9 +1,8 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import qs.modules.common
import qs.modules.common.widgets
import QtQuick
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
import Quickshell.Hyprland
import Quickshell.Services.Pipewire
@@ -24,7 +23,7 @@ Item {
visible: Config.options.bar.utilButtons.showScreenSnip
sourceComponent: CircleUtilButton {
Layout.alignment: Qt.AlignVCenter
onClicked: Hyprland.dispatch("exec hyprshot --freeze --clipboard-only --mode region --silent")
onClicked: Quickshell.execDetached(["qs", "-p", Quickshell.configPath("screenshot.qml")])
MaterialSymbol {
horizontalAlignment: Qt.AlignHCenter
fill: 1
@@ -40,7 +39,7 @@ Item {
visible: Config.options.bar.utilButtons.showColorPicker
sourceComponent: CircleUtilButton {
Layout.alignment: Qt.AlignVCenter
onClicked: Hyprland.dispatch("exec hyprpicker -a")
onClicked: Quickshell.execDetached(["hyprpicker", "-a"])
MaterialSymbol {
horizontalAlignment: Qt.AlignHCenter
fill: 1
@@ -72,7 +71,7 @@ Item {
visible: Config.options.bar.utilButtons.showMicToggle
sourceComponent: CircleUtilButton {
Layout.alignment: Qt.AlignVCenter
onClicked: Hyprland.dispatch("exec wpctl set-mute @DEFAULT_SOURCE@ toggle")
onClicked: Quickshell.execDetached(["wpctl", "set-mute", "@DEFAULT_SOURCE@", "toggle"])
MaterialSymbol {
horizontalAlignment: Qt.AlignHCenter
fill: 0
@@ -1,15 +1,14 @@
import "root:/"
import "root:/services/"
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import qs
import qs.services
import qs.modules.common
import qs.modules.common.widgets
import qs.modules.common.functions
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Wayland
import Quickshell.Hyprland
import Quickshell.Io
import Quickshell.Widgets
import Qt5Compat.GraphicalEffects
@@ -1,7 +1,7 @@
pragma ComponentBehavior: Bound
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/services"
import qs.modules.common
import qs.modules.common.widgets
import qs.services
import Quickshell
import QtQuick
import QtQuick.Layouts
@@ -1,8 +1,8 @@
import QtQuick
import QtQuick.Layouts
import "root:/modules/common"
import "root:/modules/common/widgets"
import qs.modules.common
import qs.modules.common.widgets
Rectangle {
id: root
@@ -1,7 +1,7 @@
import "root:/"
import "root:/services"
import "root:/modules/common"
import "root:/modules/common/widgets"
import qs
import qs.services
import qs.modules.common
import qs.modules.common.widgets
import QtQuick
import QtQuick.Layouts
@@ -1,16 +1,13 @@
import "root:/"
import "root:/services"
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import qs
import qs.services
import qs.modules.common
import qs.modules.common.widgets
import QtQuick
import QtQuick.Controls
import QtQuick.Effects
import QtQuick.Layouts
import Qt5Compat.GraphicalEffects
import Quickshell.Io
import Quickshell
import Quickshell.Widgets
import Quickshell.Wayland
import Quickshell.Hyprland
@@ -1,15 +1,10 @@
import "root:/"
import "root:/services"
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/modules/common/functions/file_utils.js" as FileUtils
import qs
import qs.services
import qs.modules.common
import qs.modules.common.widgets
import qs.modules.common.functions
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
import Quickshell.Widgets
import Quickshell.Hyprland
Item {
id: root
@@ -1,16 +1,11 @@
import "root:/"
import "root:/services"
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/modules/common/functions/file_utils.js" as FileUtils
import qs
import qs.services
import qs.modules.common
import qs.modules.common.widgets
import qs.modules.common.functions
import "periodic_table.js" as PTable
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
import Quickshell.Widgets
import Quickshell.Hyprland
Item {
id: root
@@ -1,10 +1,6 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import qs.modules.common
import qs.modules.common.widgets
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
RippleButton {
id: root
@@ -1,6 +1,6 @@
import QtQuick
import Quickshell
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import qs.modules.common.functions
pragma Singleton
pragma ComponentBehavior: Bound
@@ -1,11 +1,10 @@
pragma Singleton
pragma ComponentBehavior: Bound
import "root:/modules/common/functions/file_utils.js" as FileUtils
import qs.modules.common.functions
import Qt.labs.platform
import QtQuick
import Quickshell
import Quickshell.Hyprland
Singleton {
// XDG Dirs, with "file://"
@@ -0,0 +1,114 @@
pragma Singleton
import Quickshell
Singleton {
id: root
/**
* 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);
}
/**
* Returns a color with the given lightness and the hue, saturation, and alpha of the input color (using HSL).
*
* @param {string} color - The base color (any Qt.color-compatible string).
* @param {number} lightness - The lightness value to use (0-1).
* @returns {Qt.rgba} The resulting color.
*/
function colorWithLightness(color, lightness) {
var c = Qt.color(color);
return Qt.hsla(c.hslHue, c.hslSaturation, lightness, c.a);
}
/**
* Returns a color with the lightness of color2 and the hue, saturation, and alpha of color1 (using HSL).
*
* @param {string} color1 - The base color (any Qt.color-compatible string).
* @param {string} color2 - The color to take lightness from.
* @returns {Qt.rgba} The resulting color.
*/
function colorWithLightnessOf(color1, color2) {
var c2 = Qt.color(color2);
return colorWithLightness(color1, c2.hslLightness);
}
/**
* 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 = 0.5) {
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 = 1) {
var c = Qt.color(color);
return Qt.rgba(c.r, c.g, c.b, c.a * (1 - percentage));
}
}
@@ -0,0 +1,41 @@
pragma Singleton
import Quickshell
Singleton {
id: root
/**
* Trims the File protocol off the input string
* @param {string} str
* @returns {string}
*/
function trimFileProtocol(str) {
return str.startsWith("file://") ? str.slice(7) : str;
}
/**
* Extracts the file name from a file path
* @param {string} str
* @returns {string}
*/
function fileNameForPath(str) {
if (typeof str !== "string") return "";
const trimmed = trimFileProtocol(str);
return trimmed.split(/[\\/]/).pop();
}
/**
* Removes the file extension from a file path or name
* @param {string} str
* @returns {string}
*/
function trimFileExt(str) {
if (typeof str !== "string") return "";
const trimmed = trimFileProtocol(str);
const lastDot = trimmed.lastIndexOf(".");
if (lastDot > -1 && lastDot > trimmed.lastIndexOf("/")) {
return trimmed.slice(0, lastDot);
}
return trimmed;
}
}
@@ -0,0 +1,98 @@
pragma Singleton
import Quickshell
Singleton {
id: root
function toPlainObject(qtObj) {
if (qtObj === null || typeof qtObj !== "object") return qtObj;
// Handle true arrays
if (Array.isArray(qtObj)) {
return qtObj.map(item => toPlainObject(item));
}
// Handle array-like Qt objects (e.g., have length and numeric keys)
if (
typeof qtObj.length === "number" &&
qtObj.length > 0 &&
Object.keys(qtObj).every(
key => !isNaN(key) || key === "length"
)
) {
let arr = [];
for (let i = 0; i < qtObj.length; i++) {
arr.push(toPlainObject(qtObj[i]));
}
return arr;
}
const result = ({});
for (let key in qtObj) {
if (
typeof qtObj[key] !== "function" &&
!key.startsWith("objectName") &&
!key.startsWith("children") &&
!key.startsWith("object") &&
!key.startsWith("parent") &&
!key.startsWith("metaObject") &&
!key.startsWith("destroyed") &&
!key.startsWith("reloadableId")
) {
result[key] = toPlainObject(qtObj[key]);
}
}
// console.log(JSON.stringify(result))
return result;
}
function applyToQtObject(qtObj, jsonObj) {
// console.log("applyToQtObject", JSON.stringify(qtObj, null, 2), "<<", JSON.stringify(jsonObj, null, 2));
if (!qtObj || typeof jsonObj !== "object" || jsonObj === null) return;
// Detect array-like Qt objects
const isQtArrayLike = obj => {
return obj && typeof obj === "object" &&
typeof obj.length === "number" &&
obj.length > 0 &&
Object.keys(obj).every(key => !isNaN(key) || key === "length");
};
// If both are arrays or array-like, update in place or replace
if ((Array.isArray(qtObj) || isQtArrayLike(qtObj)) && Array.isArray(jsonObj)) {
qtObj.length = 0;
for (let i = 0; i < jsonObj.length; i++) {
qtObj.push(jsonObj[i]);
}
return;
}
// If target is array or array-like but source is not, clear
if ((Array.isArray(qtObj) || isQtArrayLike(qtObj)) && !Array.isArray(jsonObj)) {
qtObj.length = 0;
return;
}
// If source is array but target is not, assign directly if possible
if (!(Array.isArray(qtObj) || isQtArrayLike(qtObj)) && Array.isArray(jsonObj)) {
return jsonObj;
}
for (let key in jsonObj) {
if (!qtObj.hasOwnProperty(key)) continue;
const value = qtObj[key];
const jsonValue = jsonObj[key];
// console.log("applying to qt obj key:", value, "jsonValue:", jsonValue);
if ((Array.isArray(value) || isQtArrayLike(value)) && Array.isArray(jsonValue)) {
value.length = 0;
for (let i = 0; i < jsonValue.length; i++) {
value.push(jsonValue[i]);
}
} else if (value && typeof value === "object" && !Array.isArray(value) && !isQtArrayLike(value)) {
applyToQtObject(value, jsonValue);
} else {
qtObj[key] = jsonValue;
}
}
}
}
@@ -0,0 +1,221 @@
pragma Singleton
import Quickshell
Singleton {
id: root
/**
* Formats a string according to the args that are passed inc
* @param { string } str
* @param {...any} args
* @returns
*/
function format(str, ...args) {
return str.replace(/{(\d+)}/g, (match, index) => typeof args[index] !== 'undefined' ? args[index] : match);
}
/**
* Returns the domain of the passed in url or null
* @param { string } url
* @returns { string| null }
*/
function getDomain(url) {
const match = url.match(/^(?:https?:\/\/)?(?:www\.)?([^\/]+)/);
return match ? match[1] : null;
}
/**
* Returns the base url of the passed in url or null
* @param { string } url
* @returns { string | null }
*/
function getBaseUrl(url) {
const match = url.match(/^(https?:\/\/[^\/]+)(\/.*)?$/);
return match ? match[1] : null;
}
/**
* Escapes single quotes in shell commands
* @param { string } str
* @returns { string }
*/
function shellSingleQuoteEscape(str) {
// escape single quotes
return String(str)
// .replace(/\\/g, '\\\\')
.replace(/'/g, "'\\''");
}
/**
* Splits markdown blocks into three different types: text, think, and code.
* @param { string } markdown
*/
function splitMarkdownBlocks(markdown) {
const regex = /```(\w+)?\n([\s\S]*?)```|<think>([\s\S]*?)<\/think>/g;
/**
* @type {{type: "text" | "think" | "code"; content: string; lang: string | undefined; completed: boolean | undefined}[]}
*/
let result = [];
let lastIndex = 0;
let match;
while ((match = regex.exec(markdown)) !== null) {
if (match.index > lastIndex) {
const text = markdown.slice(lastIndex, match.index);
if (text.trim()) {
result.push({
type: "text",
content: text
});
}
}
if (match[0].startsWith('```')) {
if (match[2] && match[2].trim()) {
result.push({
type: "code",
lang: match[1] || "",
content: match[2],
completed: true
});
}
} else if (match[0].startsWith('<think>')) {
if (match[3] && match[3].trim()) {
result.push({
type: "think",
content: match[3],
completed: true
});
}
}
lastIndex = regex.lastIndex;
}
// Handle any remaining text after the last match
if (lastIndex < markdown.length) {
const text = markdown.slice(lastIndex);
// Check for unfinished <think> block
const thinkStart = text.indexOf('<think>');
const codeStart = text.indexOf('```');
if (thinkStart !== -1 && (codeStart === -1 || thinkStart < codeStart)) {
const beforeThink = text.slice(0, thinkStart);
if (beforeThink.trim()) {
result.push({
type: "text",
content: beforeThink
});
}
const thinkContent = text.slice(thinkStart + 7);
if (thinkContent.trim()) {
result.push({
type: "think",
content: thinkContent,
completed: false
});
}
} else if (codeStart !== -1) {
const beforeCode = text.slice(0, codeStart);
if (beforeCode.trim()) {
result.push({
type: "text",
content: beforeCode
});
}
// Try to detect language after ```
const codeLangMatch = text.slice(codeStart + 3).match(/^(\w+)?\n/);
let lang = "";
let codeContentStart = codeStart + 3;
if (codeLangMatch) {
lang = codeLangMatch[1] || "";
codeContentStart += codeLangMatch[0].length;
} else if (text[codeStart + 3] === '\n') {
codeContentStart += 1;
}
const codeContent = text.slice(codeContentStart);
if (codeContent.trim()) {
result.push({
type: "code",
lang,
content: codeContent,
completed: false
});
}
} else if (text.trim()) {
result.push({
type: "text",
content: text
});
}
}
// console.log(JSON.stringify(result, null, 2));
return result;
}
/**
* Returns the original string with backslashes escaped
* @param { string } str
* @returns { string }
*/
function escapeBackslashes(str) {
return str.replace(/\\/g, '\\\\');
}
/**
* Wraps words to supplied maximum length
* @param { string | null } str
* @param { number } maxLen
* @returns { string }
*/
function wordWrap(str, maxLen) {
if (!str)
return "";
let words = str.split(" ");
let lines = [];
let current = "";
for (let i = 0; i < words.length; ++i) {
if ((current + (current.length > 0 ? " " : "") + words[i]).length > maxLen) {
if (current.length > 0)
lines.push(current);
current = words[i];
} else {
current += (current.length > 0 ? " " : "") + words[i];
}
}
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 thingie
title = title.replace(/^ *『[^』]*』/, ""); // OP/ED thingie
return title.trim();
}
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')}`;
}
}
function escapeHtml(str) {
if (typeof str !== 'string')
return str;
return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;');
}
}
@@ -1,109 +0,0 @@
// 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);
}
/**
* Returns a color with the given lightness and the hue, saturation, and alpha of the input color (using HSL).
*
* @param {string} color - The base color (any Qt.color-compatible string).
* @param {number} lightness - The lightness value to use (0-1).
* @returns {Qt.rgba} The resulting color.
*/
function colorWithLightness(color, lightness) {
var c = Qt.color(color);
return Qt.hsla(c.hslHue, c.hslSaturation, lightness, c.a);
}
/**
* Returns a color with the lightness of color2 and the hue, saturation, and alpha of color1 (using HSL).
*
* @param {string} color1 - The base color (any Qt.color-compatible string).
* @param {string} color2 - The color to take lightness from.
* @returns {Qt.rgba} The resulting color.
*/
function colorWithLightnessOf(color1, color2) {
var c2 = Qt.color(color2);
return colorWithLightness(color1, c2.hslLightness);
}
/**
* 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 = 0.5) {
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 = 1) {
var c = Qt.color(color);
return Qt.rgba(c.r, c.g, c.b, c.a * (1 - percentage));
}
@@ -1,34 +0,0 @@
/**
* Trims the File protocol off the input string
* @param {string} str
* @returns {string}
*/
function trimFileProtocol(str) {
return str.startsWith("file://") ? str.slice(7) : str;
}
/**
* Extracts the file name from a file path
* @param {string} str
* @returns {string}
*/
function fileNameForPath(str) {
if (typeof str !== "string") return "";
const trimmed = trimFileProtocol(str);
return trimmed.split(/[\\/]/).pop();
}
/**
* Removes the file extension from a file path or name
* @param {string} str
* @returns {string}
*/
function trimFileExt(str) {
if (typeof str !== "string") return "";
const trimmed = trimFileProtocol(str);
const lastDot = trimmed.lastIndexOf(".");
if (lastDot > -1 && lastDot > trimmed.lastIndexOf("/")) {
return trimmed.slice(0, lastDot);
}
return trimmed;
}
@@ -1,91 +0,0 @@
function toPlainObject(qtObj) {
if (qtObj === null || typeof qtObj !== "object") return qtObj;
// Handle true arrays
if (Array.isArray(qtObj)) {
return qtObj.map(item => toPlainObject(item));
}
// Handle array-like Qt objects (e.g., have length and numeric keys)
if (
typeof qtObj.length === "number" &&
qtObj.length > 0 &&
Object.keys(qtObj).every(
key => !isNaN(key) || key === "length"
)
) {
let arr = [];
for (let i = 0; i < qtObj.length; i++) {
arr.push(toPlainObject(qtObj[i]));
}
return arr;
}
const result = ({});
for (let key in qtObj) {
if (
typeof qtObj[key] !== "function" &&
!key.startsWith("objectName") &&
!key.startsWith("children") &&
!key.startsWith("object") &&
!key.startsWith("parent") &&
!key.startsWith("metaObject") &&
!key.startsWith("destroyed") &&
!key.startsWith("reloadableId")
) {
result[key] = toPlainObject(qtObj[key]);
}
}
// console.log(JSON.stringify(result))
return result;
}
function applyToQtObject(qtObj, jsonObj) {
// console.log("applyToQtObject", JSON.stringify(qtObj, null, 2), "<<", JSON.stringify(jsonObj, null, 2));
if (!qtObj || typeof jsonObj !== "object" || jsonObj === null) return;
// Detect array-like Qt objects
const isQtArrayLike = obj => {
return obj && typeof obj === "object" &&
typeof obj.length === "number" &&
obj.length > 0 &&
Object.keys(obj).every(key => !isNaN(key) || key === "length");
};
// If both are arrays or array-like, update in place or replace
if ((Array.isArray(qtObj) || isQtArrayLike(qtObj)) && Array.isArray(jsonObj)) {
qtObj.length = 0;
for (let i = 0; i < jsonObj.length; i++) {
qtObj.push(jsonObj[i]);
}
return;
}
// If target is array or array-like but source is not, clear
if ((Array.isArray(qtObj) || isQtArrayLike(qtObj)) && !Array.isArray(jsonObj)) {
qtObj.length = 0;
return;
}
// If source is array but target is not, assign directly if possible
if (!(Array.isArray(qtObj) || isQtArrayLike(qtObj)) && Array.isArray(jsonObj)) {
return jsonObj;
}
for (let key in jsonObj) {
if (!qtObj.hasOwnProperty(key)) continue;
const value = qtObj[key];
const jsonValue = jsonObj[key];
// console.log("applying to qt obj key:", value, "jsonValue:", jsonValue);
if ((Array.isArray(value) || isQtArrayLike(value)) && Array.isArray(jsonValue)) {
value.length = 0;
for (let i = 0; i < jsonValue.length; i++) {
value.push(jsonValue[i]);
}
} else if (value && typeof value === "object" && !Array.isArray(value) && !isQtArrayLike(value)) {
applyToQtObject(value, jsonValue);
} else {
qtObj[key] = jsonValue;
}
}
}
@@ -1,188 +0,0 @@
/**
* Formats a string according to the args that are passed in
* @param { string } str
* @param {...any} args
* @returns
*/
function format(str, ...args) {
return str.replace(/{(\d+)}/g, (match, index) =>
typeof args[index] !== 'undefined' ? args[index] : match
);
}
/**
* Returns the domain of the passed in url or null
* @param { string } url
* @returns { string| null }
*/
function getDomain(url) {
const match = url.match(/^(?:https?:\/\/)?(?:www\.)?([^\/]+)/);
return match ? match[1] : null;
}
/**
* Returns the base url of the passed in url or null
* @param { string } url
* @returns { string | null }
*/
function getBaseUrl(url) {
const match = url.match(/^(https?:\/\/[^\/]+)(\/.*)?$/);
return match ? match[1] : null;
}
/**
* Escapes single quotes in shell commands
* @param { string } str
* @returns { string }
*/
function shellSingleQuoteEscape(str) {
// escape single quotes
return String(str)
// .replace(/\\/g, '\\\\')
.replace(/'/g, "'\\''");
}
/**
* Splits markdown blocks into three different types: text, think, and code.
* @param { string } markdown
*/
function splitMarkdownBlocks(markdown) {
const regex = /```(\w+)?\n([\s\S]*?)```|<think>([\s\S]*?)<\/think>/g;
/**
* @type {{type: "text" | "think" | "code"; content: string; lang: string | undefined; completed: boolean | undefined}[]}
*/
let result = [];
let lastIndex = 0;
let match;
while ((match = regex.exec(markdown)) !== null) {
if (match.index > lastIndex) {
const text = markdown.slice(lastIndex, match.index);
if (text.trim()) {
result.push({ type: "text", content: text });
}
}
if (match[0].startsWith('```')) {
if (match[2] && match[2].trim()) {
result.push({ type: "code", lang: match[1] || "", content: match[2], completed: true });
}
} else if (match[0].startsWith('<think>')) {
if (match[3] && match[3].trim()) {
result.push({ type: "think", content: match[3], completed: true });
}
}
lastIndex = regex.lastIndex;
}
// Handle any remaining text after the last match
if (lastIndex < markdown.length) {
const text = markdown.slice(lastIndex);
// Check for unfinished <think> block
const thinkStart = text.indexOf('<think>');
const codeStart = text.indexOf('```');
if (
thinkStart !== -1 &&
(codeStart === -1 || thinkStart < codeStart)
) {
const beforeThink = text.slice(0, thinkStart);
if (beforeThink.trim()) {
result.push({ type: "text", content: beforeThink });
}
const thinkContent = text.slice(thinkStart + 7);
if (thinkContent.trim()) {
result.push({ type: "think", content: thinkContent, completed: false });
}
} else if (codeStart !== -1) {
const beforeCode = text.slice(0, codeStart);
if (beforeCode.trim()) {
result.push({ type: "text", content: beforeCode });
}
// Try to detect language after ```
const codeLangMatch = text.slice(codeStart + 3).match(/^(\w+)?\n/);
let lang = "";
let codeContentStart = codeStart + 3;
if (codeLangMatch) {
lang = codeLangMatch[1] || "";
codeContentStart += codeLangMatch[0].length;
} else if (text[codeStart + 3] === '\n') {
codeContentStart += 1;
}
const codeContent = text.slice(codeContentStart);
if (codeContent.trim()) {
result.push({ type: "code", lang, content: codeContent, completed: false });
}
} else if (text.trim()) {
result.push({ type: "text", content: text });
}
}
// console.log(JSON.stringify(result, null, 2));
return result;
}
/**
* Returns the original string with backslashes escaped
* @param { string } str
* @returns { string }
*/
function escapeBackslashes(str) {
return str.replace(/\\/g, '\\\\');
}
/**
* Wraps words to supplied maximum length
* @param { string | null } str
* @param { number } maxLen
* @returns { string }
*/
function wordWrap(str, maxLen) {
if (!str) return "";
let words = str.split(" ");
let lines = [];
let current = "";
for (let i = 0; i < words.length; ++i) {
if ((current + (current.length > 0 ? " " : "") + words[i]).length > maxLen) {
if (current.length > 0) lines.push(current);
current = words[i];
} else {
current += (current.length > 0 ? " " : "") + words[i];
}
}
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 thingie
title = title.replace(/^ *『[^』]*』/, "") // OP/ED thingie
return title.trim();
}
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')}`;
}
}
function escapeHtml(str) {
if (typeof str !== 'string') return str;
return str
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
}
@@ -1,8 +1,6 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import qs.modules.common
import qs.modules.common.widgets
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
/**
@@ -2,7 +2,7 @@
// License: LGPL-3.0 - A copy can be found in `licenses` folder of repo
import QtQuick
import "root:/modules/common"
import qs.modules.common
/**
* Material 3 circular progress. See https://m3.material.io/components/progress-indicators/specs
@@ -1,17 +1,11 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/services"
import "root:/modules/common/functions/string_utils.js" as StringUtils
import "root:/modules/common/functions/file_utils.js" as FileUtils
import qs.modules.common
import qs.modules.common.widgets
import qs.services
import qs.modules.common.functions
import Qt5Compat.GraphicalEffects
import Qt.labs.platform
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
import Quickshell.Widgets
import Quickshell.Hyprland
Rectangle {
id: root
@@ -1,14 +1,9 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
import Quickshell.Hyprland
import "root:/services/"
import "root:/modules/common/"
import "root:/modules/common/widgets/"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import "root:/modules/common/functions/file_utils.js" as FileUtils
import qs.services
import qs.modules.common
import qs.modules.common.widgets
import qs.modules.common.functions
Flow {
id: root
@@ -1,8 +1,7 @@
import "root:/modules/common/widgets/"
import "root:/modules/common/"
import qs.modules.common.widgets
import qs.modules.common
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
RowLayout {
id: root
@@ -1,5 +1,5 @@
import "root:/modules/common/widgets/"
import "root:/modules/common/"
import qs.modules.common.widgets
import qs.modules.common
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
@@ -1,8 +1,7 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import "root:/modules/common/"
import "root:/modules/common/widgets/"
import qs.modules.common
import qs.modules.common.widgets
Flickable {
id: root
@@ -1,8 +1,8 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import "root:/modules/common/"
import "root:/modules/common/widgets/"
import qs.modules.common
import qs.modules.common.widgets
ColumnLayout {
id: root
@@ -1,8 +1,7 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import "root:/modules/common/"
import "root:/modules/common/widgets/"
import qs.modules.common
import qs.modules.common.widgets
ColumnLayout {
id: root
@@ -1,7 +1,7 @@
import QtQuick
import QtQuick.Layouts
import "root:/modules/common/"
import "root:/modules/common/widgets/"
import qs.modules.common
import qs.modules.common.widgets
StyledText {
text: "Subsection"
@@ -9,7 +9,7 @@ Item {
property bool colorize: false
property color color
property string source: ""
property string iconFolder: "root:/assets/icons" // The folder to check first
property string iconFolder: Qt.resolvedUrl(Quickshell.configPath("assets/icons")) // The folder to check first
width: 30
height: 30
@@ -17,8 +17,9 @@ Item {
id: iconImage
anchors.fill: parent
source: {
if (iconFolder && iconFolder + "/" + root.source) {
return iconFolder + "/" + root.source
const fullPathWhenSourceIsIconName = iconFolder + "/" + root.source;
if (iconFolder && fullPathWhenSourceIsIconName) {
return fullPathWhenSourceIsIconName
}
return root.source
}
@@ -1,10 +1,5 @@
import "root:/modules/common"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import qs.modules.common
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
/**
* Material 3 dialog button. See https://m3.material.io/components/dialogs/overview
@@ -1,8 +1,6 @@
import "root:/modules/common"
import "root:/services"
import qs.modules.common
import qs.services
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
/**
* A convenience MouseArea for handling drag events.
@@ -1,16 +1,11 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/services"
import "root:/modules/common/functions/string_utils.js" as StringUtils
import "root:/modules/common/functions/file_utils.js" as FileUtils
import qs.modules.common
import qs.modules.common.widgets
import qs.services
import qs.modules.common.functions
import Qt5Compat.GraphicalEffects
import Qt.labs.platform
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell.Io
import Quickshell.Widgets
import Quickshell.Hyprland
IconImage {
id: root
@@ -1,8 +1,7 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import "root:/modules/common/"
import "root:/modules/common/widgets/"
import qs.modules.common
import qs.modules.common.widgets
/**
* Material 3 FAB.
@@ -1,12 +1,9 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import Qt5Compat.GraphicalEffects
import qs.modules.common
import qs.modules.common.widgets
import qs.modules.common.functions
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell.Io
import Quickshell.Widgets
/**
* Material 3 button with expressive bounciness.
@@ -1,9 +1,5 @@
import "root:/modules/common"
import qs.modules.common
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
Rectangle {
id: root
@@ -1,13 +1,10 @@
import "root:/"
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import qs
import qs.modules.common
import qs.modules.common.widgets
import qs.modules.common.functions
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
import Quickshell.Hyprland
GroupButton {
id: lightDarkButtonRoot
@@ -1,6 +1,5 @@
import "root:/modules/common/"
import qs.modules.common
import QtQuick
import QtQuick.Layouts
Text {
id: root
@@ -1,5 +1,4 @@
import "root:/modules/common"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import qs.modules.common
import QtQuick
import QtQuick.Controls.Material
import QtQuick.Controls
@@ -1,10 +1,5 @@
import "root:/modules/common"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import qs.modules.common
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
RippleButton {
id: root
@@ -1,8 +1,7 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import "root:/modules/common/"
import "root:/modules/common/widgets/"
import qs.modules.common
import qs.modules.common.widgets
ColumnLayout { // Window content with navigation rail and content pane
id: root
@@ -1,10 +1,9 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import qs.modules.common
import qs.modules.common.widgets
import qs.modules.common.functions
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell.Io
TabButton {
id: root
@@ -1,8 +1,7 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import "root:/modules/common/"
import "root:/modules/common/widgets/"
import qs.modules.common
import qs.modules.common.widgets
RippleButton {
id: root
@@ -1,10 +1,7 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import qs.modules.common
import qs.modules.common.widgets
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell.Io
Item {
id: root
@@ -1,9 +1,6 @@
import "root:/modules/common"
import "root:/services"
import qs.modules.common
import qs.services
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Services.Notifications
RippleButton {
@@ -1,9 +1,7 @@
import "root:/modules/common"
import qs.modules.common
import "./notification_utils.js" as NotificationUtils
import Qt5Compat.GraphicalEffects
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Widgets
import Quickshell.Services.Notifications
@@ -1,18 +1,10 @@
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 qs.modules.common
import qs.services
import qs.modules.common.functions
import "./notification_utils.js" as NotificationUtils
import Qt5Compat.GraphicalEffects
import QtQuick
import QtQuick.Controls
import QtQuick.Effects
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
import Quickshell.Widgets
import Quickshell.Hyprland
import Quickshell.Services.Notifications
/**
* A group of notifications from the same app.
@@ -1,12 +1,8 @@
import "root:/modules/common"
import "root:/services"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import qs.services
import qs.modules.common
import qs.modules.common.functions
import QtQuick
import QtQuick.Controls
import QtQuick.Effects
import QtQuick.Layouts
import Quickshell
import Quickshell.Services.Notifications
RippleButton { // Expand button
id: root
@@ -1,16 +1,10 @@
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 "./notification_utils.js" as NotificationUtils
import Qt5Compat.GraphicalEffects
import qs
import qs.modules.common
import qs.services
import qs.modules.common.functions
import QtQuick
import QtQuick.Controls
import QtQuick.Effects
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
import Quickshell.Widgets
import Quickshell.Hyprland
import Quickshell.Services.Notifications
@@ -181,13 +175,14 @@ Item { // Notification item area
StyledText {
opacity: !root.expanded ? 1 : 0
visible: opacity > 0
Layout.fillWidth: true
Behavior on opacity {
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
}
Layout.fillWidth: true
font.pixelSize: root.fontSize
color: Appearance.colors.colSubtext
elide: Text.ElideRight
wrapMode: Text.Wrap // Needed for proper eliding????
maximumLineCount: 1
textFormat: Text.StyledText
text: {
@@ -1,13 +1,9 @@
import "root:/"
import "root:/modules/common/"
import "root:/modules/common/widgets"
import "root:/services"
import qs
import qs.modules.common
import qs.modules.common.widgets
import qs.services
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Wayland
import Quickshell.Hyprland
StyledListView { // Scrollable window
id: root
@@ -1,9 +1,8 @@
import "root:/modules/common"
import "root:/"
import qs.modules.common
import qs
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
ColumnLayout {
id: root
@@ -1,12 +1,10 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import qs.modules.common
import qs.modules.common.widgets
import qs.modules.common.functions
import Qt5Compat.GraphicalEffects
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell.Io
import Quickshell.Widgets
TabButton {
id: button
@@ -1,6 +1,5 @@
import "root:/modules/common"
import qs.modules.common
import QtQuick
import Quickshell
/**
* Recreation of GTK revealer. Expects one single child.
@@ -1,12 +1,9 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import qs.modules.common
import qs.modules.common.widgets
import qs.modules.common.functions
import Qt5Compat.GraphicalEffects
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell.Io
import Quickshell.Widgets
/**
* A button with ripple effect similar to in Material Design.
@@ -1,8 +1,7 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import "root:/modules/common/"
import "root:/modules/common/widgets/"
import qs.modules.common
import qs.modules.common.widgets
RippleButton {
id: buttonWithIconRoot
@@ -1,12 +1,10 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import qs.modules.common
import qs.modules.common.widgets
import qs.modules.common.functions
import Qt5Compat.GraphicalEffects
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell.Io
import Quickshell.Widgets
TabButton {
id: root
@@ -1,10 +1,8 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/services"
import "root:/"
import Qt5Compat.GraphicalEffects
import qs.modules.common
import qs.modules.common.widgets
import qs.services
import qs
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
@@ -3,9 +3,9 @@ import QtQuick.Layouts
import Quickshell
import Quickshell.Io
import Quickshell.Hyprland
import "root:/services/"
import "root:/modules/common/"
import "root:/modules/common/widgets/"
import qs.services
import qs.modules.common
import qs.modules.common.widgets
GroupButton {
id: root
@@ -1,7 +1,6 @@
import "root:/modules/common"
import qs.modules.common
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Label {
renderType: Text.NativeRendering
@@ -1,13 +1,8 @@
import "root:/"
import "root:/modules/common/"
import "root:/modules/common/widgets"
import "root:/services"
import qs
import qs.modules.common
import qs.modules.common.widgets
import qs.services
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Wayland
import Quickshell.Hyprland
/**
* A ListView with animations.
@@ -1,6 +1,6 @@
import "root:/services"
import "root:/modules/common"
import "root:/modules/common/widgets"
import qs.services
import qs.modules.common
import qs.modules.common.widgets
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
@@ -1,6 +1,6 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/services"
import qs.modules.common
import qs.modules.common.widgets
import qs.services
import Qt5Compat.GraphicalEffects
import QtQuick
import QtQuick.Controls
@@ -1,6 +1,6 @@
import QtQuick
import QtQuick.Effects
import "root:/modules/common"
import qs.modules.common
RectangularShadow {
required property var target
@@ -1,6 +1,6 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/services"
import qs.modules.common
import qs.modules.common.widgets
import qs.services
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
@@ -1,5 +1,5 @@
import "root:/modules/common"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import qs.modules.common
import qs.modules.common.functions
import QtQuick
import QtQuick.Controls
@@ -1,4 +1,4 @@
import "root:/modules/common/"
import qs.modules.common
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
@@ -1,4 +1,4 @@
import "root:/modules/common"
import qs.modules.common
import QtQuick
import QtQuick.Layouts
@@ -1,4 +1,4 @@
import "root:/modules/common"
import qs.modules.common
import QtQuick
import QtQuick.Controls
@@ -1,4 +1,4 @@
import "root:/modules/common"
import qs.modules.common
import QtQuick
import QtQuick.Controls
@@ -1,5 +1,5 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import qs.modules.common
import qs.modules.common.widgets
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
@@ -1,8 +1,6 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import qs.modules.common
import qs.modules.common.widgets
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
/**
@@ -1,13 +1,8 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/services"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import qs.services
import qs.modules.common
import qs.modules.common.widgets
import QtQuick
import QtQuick.Effects
import QtQuick.Layouts
import QtQuick.Controls
import Quickshell
import Quickshell.Io
Canvas { // Visualizer
id: root
+4 -4
View File
@@ -1,7 +1,7 @@
import "root:/"
import "root:/services"
import "root:/modules/common"
import "root:/modules/common/widgets"
import qs
import qs.services
import qs.modules.common
import qs.modules.common.widgets
import QtQuick
import QtQuick.Controls
import QtQuick.Effects
@@ -1,18 +1,14 @@
import "root:/"
import "root:/services"
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import qs
import qs.services
import qs.modules.common
import qs.modules.common.widgets
import qs.modules.common.functions
import Qt5Compat.GraphicalEffects
import QtQuick
import QtQuick.Controls
import QtQuick.Effects
import QtQuick.Layouts
import Quickshell.Io
import Quickshell
import Quickshell.Widgets
import Quickshell.Wayland
import Quickshell.Hyprland
DockButton {
id: root
@@ -1,18 +1,15 @@
import "root:/"
import "root:/services"
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import qs
import qs.services
import qs.modules.common
import qs.modules.common.widgets
import qs.modules.common.functions
import Qt5Compat.GraphicalEffects
import QtQuick
import QtQuick.Controls
import QtQuick.Effects
import QtQuick.Layouts
import Quickshell.Io
import Quickshell
import Quickshell.Widgets
import Quickshell.Wayland
import Quickshell.Hyprland
Item {
id: root
@@ -1,6 +1,6 @@
import "root:/"
import "root:/modules/common"
import "root:/modules/common/widgets"
import qs
import qs.modules.common
import qs.modules.common.widgets
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
@@ -1,5 +1,5 @@
import "root:/"
import "root:/modules/common"
import qs
import qs.modules.common
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
@@ -1,17 +1,13 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/services"
import "root:/"
import "root:/modules/common/functions/string_utils.js" as StringUtils
import "root:/modules/common/functions/file_utils.js" as FileUtils
import Qt5Compat.GraphicalEffects
import qs.modules.common
import qs.modules.common.widgets
import qs.services
import qs
import qs.modules.common.functions
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import Quickshell
import Quickshell.Io
import Quickshell.Services.Mpris
import Quickshell.Widgets
import Quickshell.Wayland
import Quickshell.Hyprland
@@ -1,20 +1,14 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/services"
import "root:/modules/common/functions/string_utils.js" as StringUtils
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import "root:/modules/common/functions/file_utils.js" as FileUtils
import qs.modules.common
import qs.modules.common.widgets
import qs.services
import qs.modules.common.functions
import Qt5Compat.GraphicalEffects
import QtQuick
import QtQuick.Effects
import QtQuick.Layouts
import QtQuick.Controls
import Quickshell
import Quickshell.Io
import Quickshell.Services.Mpris
import Quickshell.Widgets
import Quickshell.Wayland
import Quickshell.Hyprland
Item { // Player instance
id: playerController
@@ -1,7 +1,7 @@
import "root:/"
import "root:/modules/common/"
import "root:/modules/common/widgets"
import "root:/services"
import qs
import qs.modules.common
import qs.modules.common.widgets
import qs.services
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
@@ -1,7 +1,7 @@
import "root:/"
import "root:/services/"
import "root:/modules/common"
import "root:/modules/common/widgets"
import qs
import qs.services
import qs.modules.common
import qs.modules.common.widgets
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
@@ -1,7 +1,7 @@
import "root:/"
import "root:/services/"
import "root:/modules/common"
import "root:/modules/common/widgets"
import qs
import qs.services
import qs.modules.common
import qs.modules.common.widgets
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
@@ -1,6 +1,6 @@
import "root:/services"
import "root:/modules/common"
import "root:/modules/common/widgets"
import qs.services
import qs.modules.common
import qs.modules.common.widgets
import QtQuick
import QtQuick.Controls
import QtQuick.Effects
@@ -1,15 +1,12 @@
import "root:/"
import "root:/services"
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import qs
import qs.services
import qs.modules.common
import qs.modules.common.widgets
import QtQuick
import QtQuick.Controls
import QtQuick.Effects
import QtQuick.Layouts
import Quickshell.Io
import Quickshell
import Quickshell.Widgets
import Quickshell.Wayland
import Quickshell.Hyprland

Some files were not shown because too many files have changed in this diff Show More