Merge remote-tracking branch 'origin/main' into addon-i18n

This commit is contained in:
月月
2025-07-02 22:21:58 +08:00
79 changed files with 1631 additions and 830 deletions
@@ -16,8 +16,8 @@ Singleton {
property string syntaxHighlightingTheme
// Extremely conservative transparency values for consistency and readability
property real transparency: ConfigOptions?.appearance.transparency ? (m3colors.darkmode ? 0.1 : 0.07) : 0
property real contentTransparency: ConfigOptions?.appearance.transparency ? (m3colors.darkmode ? 0.55 : 0.55) : 0
property real transparency: Config.options?.appearance.transparency ? (m3colors.darkmode ? 0.1 : 0.07) : 0
property real contentTransparency: Config.options?.appearance.transparency ? (m3colors.darkmode ? 0.55 : 0.55) : 0
m3colors: QtObject {
property bool darkmode: false
@@ -131,7 +131,7 @@ Singleton {
property color colSecondaryHover: ColorUtils.mix(m3colors.m3secondary, colLayer1Hover, 0.85)
property color colSecondaryActive: ColorUtils.mix(m3colors.m3secondary, colLayer1Active, 0.4)
property color colSecondaryContainer: m3colors.m3secondaryContainer
property color colSecondaryContainerHover: ColorUtils.mix(m3colors.m3secondaryContainer, colLayer1Hover, 0.6)
property color colSecondaryContainerHover: ColorUtils.mix(m3colors.m3secondaryContainer, m3colors.m3onSecondaryContainer, 0.90)
property color colSecondaryContainerActive: ColorUtils.mix(m3colors.m3secondaryContainer, colLayer1Active, 0.54)
property color colOnSecondaryContainer: m3colors.m3onSecondaryContainer
property color colSurfaceContainerLow: ColorUtils.transparentize(m3colors.m3surfaceContainerLow, root.contentTransparency)
@@ -171,7 +171,7 @@ Singleton {
}
property QtObject pixelSize: QtObject {
property int smallest: 10
property int smaller: 13
property int smaller: 12
property int small: 15
property int normal: 16
property int large: 17
@@ -288,8 +288,10 @@ Singleton {
}
sizes: QtObject {
property real barHeight: 40
property real barCenterSideModuleWidth: ConfigOptions?.bar.verbose ? 360 : 140
property real baseBarHeight: 40
property real barHeight: Config.options.bar.cornerStyle === 1 ?
(baseBarHeight + Appearance.sizes.hyprlandGapsOut * 2) : baseBarHeight
property real barCenterSideModuleWidth: Config.options?.bar.verbose ? 360 : 140
property real barCenterSideModuleWidthShortened: 280
property real barCenterSideModuleWidthHellaShortened: 190
property real barShortenScreenWidthThreshold: 1200 // Shorten if screen width is at most this value
@@ -0,0 +1,217 @@
pragma Singleton
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
import Quickshell.Io
Singleton {
id: root
property string filePath: Directories.shellConfigPath
property alias options: configOptionsJsonAdapter
function setNestedValue(nestedKey, value) {
let keys = nestedKey.split(".");
let obj = root.options;
let parents = [obj];
// Traverse and collect parent objects
for (let i = 0; i < keys.length - 1; ++i) {
if (!obj[keys[i]] || typeof obj[keys[i]] !== "object") {
obj[keys[i]] = {};
}
obj = obj[keys[i]];
parents.push(obj);
}
// Convert value to correct type using JSON.parse when safe
let convertedValue = value;
if (typeof value === "string") {
let trimmed = value.trim();
if (trimmed === "true" || trimmed === "false" || !isNaN(Number(trimmed))) {
try {
convertedValue = JSON.parse(trimmed);
} catch (e) {
convertedValue = value;
}
}
}
obj[keys[keys.length - 1]] = convertedValue;
}
FileView {
path: root.filePath
watchChanges: true
onFileChanged: reload()
onAdapterUpdated: writeAdapter()
onLoadFailed: error => {
if (error == FileViewError.FileNotFound) {
writeAdapter();
}
}
JsonAdapter {
id: configOptionsJsonAdapter
property JsonObject policies: JsonObject {
property int ai: 1 // 0: No | 1: Yes | 2: Local
property int weeb: 1 // 0: No | 1: Open | 2: Closet
}
property JsonObject ai: JsonObject {
property string systemPrompt: qsTr("## Style\n- Use casual tone, don't be formal! Make sure you answer precisely without hallucination and prefer bullet points over walls of text. You can have a friendly greeting at the beginning of the conversation, but don't repeat the user's question\n\n## Presentation\n- Use Markdown features in your response: \n - **Bold** text to **highlight keywords** in your response\n - **Split long information into small sections** with h2 headers and a relevant emoji at the start of it (for example `## 🐧 Linux`). Bullet points are preferred over long paragraphs, unless you're offering writing support or instructed otherwise by the user.\n- Asked to compare different options? You should firstly use a table to compare the main aspects, then elaborate or include relevant comments from online forums *after* the table. Make sure to provide a final recommendation for the user's use case!\n- Use LaTeX formatting for mathematical and scientific notations whenever appropriate. Enclose all LaTeX '$$' delimiters. NEVER generate LaTeX code in a latex block unless the user explicitly asks for it. DO NOT use LaTeX for regular documents (resumes, letters, essays, CVs, etc.).\n\nThanks!\n\n## Tools\nMay or may not be available depending on the user's settings. If they're available, follow these guidelines:\n\n### Search\n- When user asks for information that might benefit from up-to-date information, use this to get search access\n\n### Shell configuration\n- Always fetch the config options to see the available keys before setting\n- Avoid unnecessarily asking the user to confirm the changes they explicitly asked for, just do it\n")
}
property JsonObject appearance: JsonObject {
property int fakeScreenRounding: 2 // 0: None | 1: Always | 2: When not fullscreen
property bool transparency: false
property JsonObject palette: JsonObject {
property string type: "auto" // Allowed: auto, scheme-content, scheme-expressive, scheme-fidelity, scheme-fruit-salad, scheme-monochrome, scheme-neutral, scheme-rainbow, scheme-tonal-spot
}
}
property JsonObject audio: JsonObject {
// Values in %
property JsonObject protection: JsonObject {
// Prevent sudden bangs
property bool enable: true
property real maxAllowedIncrease: 10
property real maxAllowed: 90 // Realistically should already provide some protection when it's 99...
}
}
property JsonObject apps: JsonObject {
property string bluetooth: "kcmshell6 kcm_bluetooth"
property string network: "plasmawindowed org.kde.plasma.networkmanagement"
property string networkEthernet: "kcmshell6 kcm_networkmanagement"
property string taskManager: "plasma-systemmonitor --page-name Processes"
property string terminal: "kitty -1" // This is only for shell actions
}
property JsonObject background: JsonObject {
property bool fixedClockPosition: false
property real clockX: -500
property real clockY: -500
}
property JsonObject bar: JsonObject {
property bool bottom: false // Instead of top
property int cornerStyle: 0 // 0: Hug | 1: Float | 2: Plain rectangle
property bool borderless: false // true for no grouping of items
property string topLeftIcon: "spark" // Options: distro, spark
property bool showBackground: true
property bool verbose: true
property JsonObject resources: JsonObject {
property bool alwaysShowSwap: true
property bool alwaysShowCpu: false
}
property list<string> screenList: [] // List of names, like "eDP-1", find out with 'hyprctl monitors' command
property JsonObject utilButtons: JsonObject {
property bool showScreenSnip: true
property bool showColorPicker: false
property bool showMicToggle: false
property bool showKeyboardToggle: true
property bool showDarkModeToggle: true
}
property JsonObject tray: JsonObject {
property bool monochromeIcons: true
}
property JsonObject workspaces: JsonObject {
property int shown: 10
property bool showAppIcons: true
property bool alwaysShowNumbers: false
property int showNumberDelay: 300 // milliseconds
}
}
property JsonObject battery: JsonObject {
property int low: 20
property int critical: 5
property bool automaticSuspend: true
property int suspend: 3
}
property JsonObject dock: JsonObject {
property bool enable: false
property real height: 60
property real hoverRegionHeight: 3
property bool pinnedOnStartup: false
property bool hoverToReveal: true // When false, only reveals on empty workspace
property list<string> pinnedApps: [ // IDs of pinned entries
"org.kde.dolphin", "kitty",]
}
property JsonObject language: JsonObject {
property JsonObject translator: JsonObject {
property string engine: "auto" // Run `trans -list-engines` for available engines. auto should use google
property string targetLanguage: "auto" // Run `trans -list-all` for available languages
property string sourceLanguage: "auto"
}
}
property JsonObject networking: JsonObject {
property string userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"
}
property JsonObject osd: JsonObject {
property int timeout: 1000
}
property JsonObject osk: JsonObject {
property string layout: "qwerty_full"
property bool pinnedOnStartup: false
}
property JsonObject overview: JsonObject {
property real scale: 0.18 // Relative to screen size
property real rows: 2
property real columns: 5
}
property JsonObject resources: JsonObject {
property int updateInterval: 3000
}
property JsonObject search: JsonObject {
property int nonAppResultDelay: 30 // This prevents lagging when typing
property string engineBaseUrl: "https://www.google.com/search?q="
property list<string> excludedSites: ["quora.com"]
property bool sloppy: false // Uses levenshtein distance based scoring instead of fuzzy sort. Very weird.
property JsonObject prefix: JsonObject {
property string action: "/"
property string clipboard: ";"
property string emojis: ":"
}
}
property JsonObject sidebar: JsonObject {
property JsonObject translator: JsonObject {
property int delay: 300 // Delay before sending request. Reduces (potential) rate limits and lag.
}
property JsonObject booru: JsonObject {
property bool allowNsfw: false
property string defaultProvider: "yandere"
property int limit: 20
property JsonObject zerochan: JsonObject {
property string username: "[unset]"
}
}
}
property JsonObject time: JsonObject {
// https://doc.qt.io/qt-6/qtime.html#toString
property string format: "hh:mm"
property string dateFormat: "dddd, dd/MM"
}
property JsonObject windows: JsonObject {
property bool showTitlebar: true // Client-side decoration for shell apps
property bool centerTitle: true
}
property JsonObject hacks: JsonObject {
property int arbitraryRaceConditionDelay: 20 // milliseconds
}
}
}
}
@@ -1,165 +0,0 @@
pragma Singleton
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
Singleton {
property QtObject policies: QtObject {
property int ai: 1 // 0: No | 1: Yes | 2: Local
property int weeb: 1 // 0: No | 1: Open | 2: Closet
}
property QtObject ai: QtObject {
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`. When making changes to the user's config, you must get the config to know what values there are before setting.")
}
property QtObject appearance: QtObject {
property int fakeScreenRounding: 2 // 0: None | 1: Always | 2: When not fullscreen
property bool transparency: false
property QtObject palette: QtObject {
property string type: "auto" // Allowed: auto, scheme-content, scheme-expressive, scheme-fidelity, scheme-fruit-salad, scheme-monochrome, scheme-neutral, scheme-rainbow, scheme-tonal-spot
}
}
property QtObject audio: QtObject {
// Values in %
property QtObject protection: QtObject {
// Prevent sudden bangs
property bool enable: true
property real maxAllowedIncrease: 10
property real maxAllowed: 90 // Realistically should already provide some protection when it's 99...
}
}
property QtObject apps: QtObject {
property string bluetooth: "kcmshell6 kcm_bluetooth"
property string network: "plasmawindowed org.kde.plasma.networkmanagement"
property string networkEthernet: "kcmshell6 kcm_networkmanagement"
property string taskManager: "plasma-systemmonitor --page-name Processes"
property string terminal: "kitty -1" // This is only for shell actions
}
property QtObject background: QtObject {
property bool fixedClockPosition: false
property real clockX: -500
property real clockY: -500
}
property QtObject bar: QtObject {
property bool bottom: false // Instead of top
property bool borderless: false // true for no grouping of items
property string topLeftIcon: "spark" // Options: distro, spark
property bool showBackground: true
property bool verbose: true
property QtObject resources: QtObject {
property bool alwaysShowSwap: true
property bool alwaysShowCpu: false
}
property list<string> screenList: [] // List of names, like "eDP-1", find out with 'hyprctl monitors' command
property QtObject utilButtons: QtObject {
property bool showScreenSnip: true
property bool showColorPicker: false
property bool showMicToggle: false
property bool showKeyboardToggle: true
property bool showDarkModeToggle: true
}
property QtObject tray: QtObject {
property bool monochromeIcons: true
}
property QtObject workspaces: QtObject {
property int shown: 10
property bool showAppIcons: true
property bool alwaysShowNumbers: false
property int showNumberDelay: 300 // milliseconds
}
}
property QtObject battery: QtObject {
property int low: 20
property int critical: 5
property bool automaticSuspend: true
property int suspend: 3
}
property QtObject dock: QtObject {
property real height: 60
property real hoverRegionHeight: 3
property bool pinnedOnStartup: false
property bool hoverToReveal: false // When false, only reveals on empty workspace
property list<string> pinnedApps: [ // IDs of pinned entries
"org.kde.dolphin", "kitty",]
}
property QtObject language: QtObject {
property string ui: "auto" // Interface language: "auto", "en", "zh-CN", "zh-TW", etc.
property QtObject translator: QtObject {
property string engine: "auto" // Run `trans -list-engines` for available engines. auto should use google
property string targetLanguage: "auto" // Run `trans -list-all` for available languages
property string sourceLanguage: "auto"
}
}
property QtObject networking: QtObject {
property string userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"
}
property QtObject osd: QtObject {
property int timeout: 1000
}
property QtObject osk: QtObject {
property string layout: "qwerty_full"
property bool pinnedOnStartup: false
}
property QtObject overview: QtObject {
property real scale: 0.18 // Relative to screen size
property real rows: 2
property real columns: 5
}
property QtObject resources: QtObject {
property int updateInterval: 3000
}
property QtObject search: QtObject {
property int nonAppResultDelay: 30 // This prevents lagging when typing
property string engineBaseUrl: "https://www.google.com/search?q="
property list<string> excludedSites: ["quora.com"]
property bool sloppy: false // Uses levenshtein distance based scoring instead of fuzzy sort. Very weird.
property QtObject prefix: QtObject {
property string action: "/"
property string clipboard: ";"
property string emojis: ":"
}
}
property QtObject sidebar: QtObject {
property QtObject translator: QtObject {
property int delay: 300 // Delay before sending request. Reduces (potential) rate limits and lag.
}
property QtObject booru: QtObject {
property bool allowNsfw: false
property string defaultProvider: "yandere"
property int limit: 20
property QtObject zerochan: QtObject {
property string username: "[unset]"
}
}
}
property QtObject time: QtObject {
// https://doc.qt.io/qt-6/qtime.html#toString
property string format: "hh:mm"
property string dateFormat: "dddd, dd/MM"
}
property QtObject windows: QtObject {
property bool showTitlebar: true // Client-side decoration for shell apps
property bool centerTitle: true
}
property QtObject hacks: QtObject {
property int arbitraryRaceConditionDelay: 20 // milliseconds
}
}
@@ -16,6 +16,7 @@ Singleton {
readonly property string downloads: StandardPaths.standardLocations(StandardPaths.DownloadLocation)[0]
// Other dirs used by the shell, without "file://"
property string scriptPath: FileUtils.trimFileProtocol(`${Directories.config}/quickshell/scripts`)
property string favicons: FileUtils.trimFileProtocol(`${Directories.cache}/media/favicons`)
property string coverArt: FileUtils.trimFileProtocol(`${Directories.cache}/media/coverart`)
property string booruPreviews: FileUtils.trimFileProtocol(`${Directories.cache}/media/boorus`)
@@ -29,7 +30,9 @@ Singleton {
property string notificationsPath: FileUtils.trimFileProtocol(`${Directories.cache}/notifications/notifications.json`)
property string generatedMaterialThemePath: FileUtils.trimFileProtocol(`${Directories.state}/user/generated/colors.json`)
property string cliphistDecode: FileUtils.trimFileProtocol(`/tmp/quickshell/media/cliphist`)
property string wallpaperSwitchScriptPath: FileUtils.trimFileProtocol(`${Directories.config}/quickshell/scripts/colors/switchwall.sh`)
property string wallpaperSwitchScriptPath: FileUtils.trimFileProtocol(`${Directories.scriptPath}/colors/switchwall.sh`)
property string defaultAiPrompts: FileUtils.trimFileProtocol(`${Directories.config}/quickshell/defaults/ai/prompts`)
property string userAiPrompts: FileUtils.trimFileProtocol(`${Directories.shellConfig}/ai/prompts`)
// Cleanup on init
Component.onCompleted: {
Quickshell.execDetached(["bash", "-c", `mkdir -p '${shellConfig}'`])
@@ -0,0 +1,48 @@
pragma Singleton
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
import Quickshell.Io
Singleton {
id: root
property alias states: persistentStatesJsonAdapter
property string fileDir: Directories.state
property string fileName: "states.json"
property string filePath: `${root.fileDir}/${root.fileName}`
FileView {
path: root.filePath
watchChanges: true
onFileChanged: reload()
onAdapterUpdated: {
writeAdapter()
}
onLoadFailed: error => {
console.log("Failed to load persistent states file:", error);
if (error == FileViewError.FileNotFound) {
writeAdapter();
}
}
adapter: JsonAdapter {
id: persistentStatesJsonAdapter
property JsonObject ai: JsonObject {
property string model
property real temperature: 0.5
}
property JsonObject sidebar: JsonObject {
property JsonObject bottomGroup: JsonObject {
property bool collapsed: false
}
}
property JsonObject booru: JsonObject {
property bool allowNsfw: false
property string provider: "yandere"
}
}
}
}
@@ -7,3 +7,28 @@ 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;
}
@@ -18,7 +18,7 @@ IconImage {
property string displayText
property real size: 32
property string downloadUserAgent: ConfigOptions?.networking.userAgent ?? ""
property string downloadUserAgent: Config.options?.networking.userAgent ?? ""
property string faviconDownloadPath: Directories.favicons
property string domainName: url.includes("vertexaisearch") ? displayText : StringUtils.getDomain(url)
property string faviconUrl: `https://www.google.com/s2/favicons?domain=${domainName}&sz=32`
@@ -9,8 +9,8 @@ Rectangle {
id: root
property string key
property real horizontalPadding: 7
property real verticalPadding: 2
property real horizontalPadding: 6
property real verticalPadding: 1
property real borderWidth: 1
property real extraBottomBorderWidth: 2
property color borderColor: Appearance.colors.colOnLayer0
@@ -13,6 +13,12 @@ Text {
family: Appearance?.font.family.iconMaterial ?? "Material Symbols Rounded"
pixelSize: iconSize
weight: Font.Normal + (Font.DemiBold - Font.Normal) * fill
variableAxes: {
"FILL": truncatedFill,
// "wght": font.weight,
// "GRAD": 0,
"opsz": iconSize,
}
}
verticalAlignment: Text.AlignVCenter
color: Appearance.m3colors.m3onBackground
@@ -24,11 +30,4 @@ Text {
// easing.bezierCurve: Appearance?.animation.elementMoveFast.bezierCurve ?? [0.34, 0.80, 0.34, 1.00, 1, 1]
// }
// }
font.variableAxes: {
"FILL": truncatedFill,
// "wght": font.weight,
// "GRAD": 0,
"opsz": iconSize,
}
}
@@ -188,6 +188,7 @@ Item { // Notification item area
font.pixelSize: root.fontSize
color: Appearance.colors.colSubtext
elide: Text.ElideRight
maximumLineCount: 1
textFormat: Text.StyledText
text: {
return processNotificationBody(notificationObject.body, notificationObject.appName || notificationObject.summary).replace(/\n/g, "<br/>")
@@ -3,24 +3,21 @@ import QtQuick 2.9
Item {
id: root
enum CornerEnum { TopLeft, TopRight, BottomLeft, BottomRight }
property var corner: RoundCorner.CornerEnum.TopLeft // Default to TopLeft
property int size: 25
property color color: "#000000"
onColorChanged: {
canvas.requestPaint();
}
property QtObject cornerEnum: QtObject {
property int topLeft: 0
property int topRight: 1
property int bottomLeft: 2
property int bottomRight: 3
onCornerChanged: {
canvas.requestPaint();
}
property int corner: cornerEnum.topLeft // Default to TopLeft
width: size
height: size
implicitWidth: size
implicitHeight: size
Canvas {
id: canvas
@@ -31,22 +28,22 @@ Item {
onPaint: {
var ctx = getContext("2d");
var r = root.size;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
switch (root.corner) {
case cornerEnum.topLeft:
case RoundCorner.CornerEnum.TopLeft:
ctx.arc(r, r, r, Math.PI, 3 * Math.PI / 2);
ctx.lineTo(0, 0);
break;
case cornerEnum.topRight:
case RoundCorner.CornerEnum.TopRight:
ctx.arc(0, r, r, 3 * Math.PI / 2, 2 * Math.PI);
ctx.lineTo(r, 0);
break;
case cornerEnum.bottomLeft:
case RoundCorner.CornerEnum.BottomLeft:
ctx.arc(r, 0, r, Math.PI / 2, Math.PI);
ctx.lineTo(0, r);
break;
case cornerEnum.bottomRight:
case RoundCorner.CornerEnum.BottomRight:
ctx.arc(0, 0, r, 0, Math.PI / 2);
ctx.lineTo(r, r);
break;