Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7469d44003 | |||
| cee0c547db | |||
| 4816912b35 | |||
| ee65cfd9f8 |
@@ -1,42 +0,0 @@
|
|||||||
name: Lint & Format (JS/TS)
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
lint-format:
|
|
||||||
runs-on: alpine
|
|
||||||
container: node:26-alpine
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install tools
|
|
||||||
run: |
|
|
||||||
apk add --no-cache \
|
|
||||||
git
|
|
||||||
|
|
||||||
- name: Prettier
|
|
||||||
continue-on-error: true
|
|
||||||
run: |
|
|
||||||
if [ -n "$(find . \( -iname "*.js" -o -iname "*.jsx" -o -iname "*.ts" -o -iname "*.tsx" -o -iname "*.mjs" -o -iname "*.cjs" \) -print -quit)" ]; then
|
|
||||||
npx --yes prettier --check "**/*.{js,jsx,ts,tsx,mjs,cjs}" --ignore-path .prettierignore
|
|
||||||
else
|
|
||||||
echo "No JS/TS files found"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: ESLint
|
|
||||||
run: |
|
|
||||||
if [ -n "$(find . \( -iname "*.js" -o -iname "*.jsx" -o -iname "*.ts" -o -iname "*.tsx" -o -iname "*.mjs" -o -iname "*.cjs" \) -print -quit)" ]; then
|
|
||||||
if [ -f package.json ]; then
|
|
||||||
npm install --no-audit --no-fund
|
|
||||||
fi
|
|
||||||
if [ -f eslint.config.js ] || [ -f eslint.config.mjs ] || [ -f eslint.config.cjs ] || [ -f .eslintrc ] || [ -f .eslintrc.js ] || [ -f .eslintrc.cjs ] || [ -f .eslintrc.json ] || [ -f .eslintrc.yaml ] || [ -f .eslintrc.yml ]; then
|
|
||||||
npx --yes eslint . && echo "ESLint passed" || echo "ESLint failed"
|
|
||||||
else
|
|
||||||
echo "No eslint config found"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "No JS/TS files found"
|
|
||||||
fi
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
name: Lint & Format (Python)
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
lint-format:
|
|
||||||
runs-on: alpine
|
|
||||||
container: node:26-alpine
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install tools
|
|
||||||
run: |
|
|
||||||
apk add --no-cache \
|
|
||||||
git \
|
|
||||||
python3 \
|
|
||||||
py3-pip
|
|
||||||
python3 -m venv .venv
|
|
||||||
. .venv/bin/activate
|
|
||||||
pip install --no-cache-dir ruff
|
|
||||||
|
|
||||||
- name: Format check
|
|
||||||
continue-on-error: true
|
|
||||||
run: |
|
|
||||||
. .venv/bin/activate
|
|
||||||
ruff format --check .
|
|
||||||
|
|
||||||
- name: Lint
|
|
||||||
run: |
|
|
||||||
. .venv/bin/activate
|
|
||||||
ruff check .
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
name: Lint & Format (Rust)
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
lint-format:
|
|
||||||
runs-on: alpine
|
|
||||||
container: node:26-alpine
|
|
||||||
env:
|
|
||||||
CARGO_HOME: ${{ github.workspace }}/.cargo
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Cache cargo packages
|
|
||||||
uses: actions/cache@v4
|
|
||||||
env:
|
|
||||||
cache-name: cache-cargo-packages
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
.cargo/registry
|
|
||||||
.cargo/git
|
|
||||||
target
|
|
||||||
key: rust-${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/Cargo.lock') }}
|
|
||||||
restore-keys: |
|
|
||||||
rust-${{ runner.os }}-build-${{ env.cache-name }}-
|
|
||||||
rust-${{ runner.os }}-build-
|
|
||||||
rust-
|
|
||||||
|
|
||||||
- name: Install tools
|
|
||||||
run: |
|
|
||||||
apk add --no-cache \
|
|
||||||
git \
|
|
||||||
cargo \
|
|
||||||
rust \
|
|
||||||
rustfmt \
|
|
||||||
rust-clippy
|
|
||||||
|
|
||||||
- name: Format check
|
|
||||||
continue-on-error: true
|
|
||||||
run: |
|
|
||||||
if [ -n "$(find . -name "Cargo.toml" -print -quit)" ]; then
|
|
||||||
for manifest in $(find . -name "Cargo.toml"); do
|
|
||||||
cargo fmt --manifest-path "$manifest" --check && \
|
|
||||||
echo "$manifest: formatting OK" || \
|
|
||||||
echo "$manifest: needs formatting"
|
|
||||||
done
|
|
||||||
elif [ -n "$(find . -name "*.rs" -print -quit)" ]; then
|
|
||||||
echo "Rust files found but no Cargo.toml"
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
echo "No Rust project found"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Clippy
|
|
||||||
run: |
|
|
||||||
if [ -n "$(find . -name "Cargo.toml" -print -quit)" ]; then
|
|
||||||
status=0
|
|
||||||
for manifest in $(find . -name "Cargo.toml"); do
|
|
||||||
cargo clippy --manifest-path "$manifest" --all-targets --all-features -- -D warnings && \
|
|
||||||
echo "$manifest: Clippy passed" || \
|
|
||||||
{ echo "$manifest: Clippy failed"; status=1; }
|
|
||||||
done
|
|
||||||
exit $status
|
|
||||||
elif [ -n "$(find . -name "*.rs" -print -quit)" ]; then
|
|
||||||
echo "Rust files found but no Cargo.toml"
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
echo "No Rust project found"
|
|
||||||
fi
|
|
||||||
+1
-2
@@ -1,4 +1,4 @@
|
|||||||
**/__pycache__/
|
./__pycache__/
|
||||||
./result/
|
./result/
|
||||||
.pyre/
|
.pyre/
|
||||||
.cache/
|
.cache/
|
||||||
@@ -12,4 +12,3 @@ pkg/
|
|||||||
uv.lock
|
uv.lock
|
||||||
.qtcreator/
|
.qtcreator/
|
||||||
dist/
|
dist/
|
||||||
**/target/
|
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
.venv/
|
|
||||||
scripts/fzf.js
|
|
||||||
scripts/fuzzysort.js
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"semi": true,
|
|
||||||
"singleQuote": false,
|
|
||||||
"jsxSingleQuote": false,
|
|
||||||
"tabWidth": 4,
|
|
||||||
"printWidth": 80,
|
|
||||||
"trailingComma": "es5",
|
|
||||||
"bracketSpacing": true,
|
|
||||||
"bracketSameLine": false,
|
|
||||||
"arrowParens": "always",
|
|
||||||
"endOfLine": "lf",
|
|
||||||
"proseWrap": "preserve"
|
|
||||||
}
|
|
||||||
+2
-2
@@ -2,7 +2,7 @@ import QtQuick
|
|||||||
import qs.Config
|
import qs.Config
|
||||||
|
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
duration: Appearance.anim.durations.normal
|
duration: MaterialEasing.standardTime
|
||||||
easing.bezierCurve: Appearance.anim.curves.standard
|
easing.bezierCurve: MaterialEasing.standard
|
||||||
easing.type: Easing.BezierSpline
|
easing.type: Easing.BezierSpline
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import QtQuick.Controls
|
|
||||||
import qs.Config
|
|
||||||
|
|
||||||
IconButton {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
required property bool shouldBeVisible
|
|
||||||
|
|
||||||
opacity: 0
|
|
||||||
scale: 0
|
|
||||||
visible: root.scale > 0
|
|
||||||
|
|
||||||
Behavior on opacity {
|
|
||||||
Anim {
|
|
||||||
duration: Appearance.anim.durations.small
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Behavior on scale {
|
|
||||||
Anim {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onShouldBeVisibleChanged: {
|
|
||||||
if (root.shouldBeVisible) {
|
|
||||||
root.opacity = 1;
|
|
||||||
root.scale = 1;
|
|
||||||
} else {
|
|
||||||
root.opacity = 0;
|
|
||||||
root.scale = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -41,11 +41,12 @@ CustomRect {
|
|||||||
color: type === IconButton.Text ? "transparent" : disabled ? disabledColour : internalChecked ? activeColour : inactiveColour
|
color: type === IconButton.Text ? "transparent" : disabled ? disabledColour : internalChecked ? activeColour : inactiveColour
|
||||||
implicitHeight: label.implicitHeight + padding * 2
|
implicitHeight: label.implicitHeight + padding * 2
|
||||||
implicitWidth: implicitHeight
|
implicitWidth: implicitHeight
|
||||||
radius: internalChecked ? 6 : (implicitHeight / 2 * Math.min(1, 1)) * Appearance.rounding.scale
|
radius: internalChecked ? 6 : implicitHeight / 2 * Math.min(1, 1)
|
||||||
|
|
||||||
Behavior on radius {
|
Behavior on radius {
|
||||||
Anim {
|
Anim {
|
||||||
id: radiusAnim
|
id: radiusAnim
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,4 @@ JsonObject {
|
|||||||
property real alignX: 0.5
|
property real alignX: 0.5
|
||||||
property real alignY: 0.5
|
property real alignY: 0.5
|
||||||
property real zoom: 1.0
|
property real zoom: 1.0
|
||||||
property real sourceClipX: 0
|
|
||||||
property real sourceClipY: 0
|
|
||||||
property real sourceClipW: 0
|
|
||||||
property real sourceClipH: 0
|
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-1
@@ -8,6 +8,10 @@ JsonObject {
|
|||||||
id: "workspaces",
|
id: "workspaces",
|
||||||
enabled: true
|
enabled: true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: "audio",
|
||||||
|
enabled: true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: "media",
|
id: "media",
|
||||||
enabled: true
|
enabled: true
|
||||||
@@ -20,6 +24,10 @@ JsonObject {
|
|||||||
id: "updates",
|
id: "updates",
|
||||||
enabled: true
|
enabled: true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: "dash",
|
||||||
|
enabled: true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: "spacer",
|
id: "spacer",
|
||||||
enabled: true
|
enabled: true
|
||||||
@@ -40,6 +48,10 @@ JsonObject {
|
|||||||
id: "tray",
|
id: "tray",
|
||||||
enabled: true
|
enabled: true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: "upower",
|
||||||
|
enabled: false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: "network",
|
id: "network",
|
||||||
enabled: false
|
enabled: false
|
||||||
@@ -58,7 +70,6 @@ JsonObject {
|
|||||||
property Popouts popouts: Popouts {
|
property Popouts popouts: Popouts {
|
||||||
}
|
}
|
||||||
property int rounding: 8
|
property int rounding: 8
|
||||||
property int smoothing: 32
|
|
||||||
|
|
||||||
component Popouts: JsonObject {
|
component Popouts: JsonObject {
|
||||||
property bool activeWindow: true
|
property bool activeWindow: true
|
||||||
|
|||||||
+1
-26
@@ -23,7 +23,6 @@ Singleton {
|
|||||||
property alias osd: adapter.osd
|
property alias osd: adapter.osd
|
||||||
property alias overview: adapter.overview
|
property alias overview: adapter.overview
|
||||||
property bool recentlySaved: false
|
property bool recentlySaved: false
|
||||||
property alias screenshot: adapter.screenshot
|
|
||||||
property alias services: adapter.services
|
property alias services: adapter.services
|
||||||
property alias sidebar: adapter.sidebar
|
property alias sidebar: adapter.sidebar
|
||||||
property alias utilities: adapter.utilities
|
property alias utilities: adapter.utilities
|
||||||
@@ -83,10 +82,6 @@ Singleton {
|
|||||||
wallFadeDuration: background.wallFadeDuration,
|
wallFadeDuration: background.wallFadeDuration,
|
||||||
enabled: background.enabled,
|
enabled: background.enabled,
|
||||||
alignX: background.alignX,
|
alignX: background.alignX,
|
||||||
sourceClipX: background.sourceClipX,
|
|
||||||
sourceClipY: background.sourceClipY,
|
|
||||||
sourceClipW: background.sourceClipW,
|
|
||||||
sourceClipH: background.sourceClipH,
|
|
||||||
alignY: background.alignY,
|
alignY: background.alignY,
|
||||||
zoom: background.zoom
|
zoom: background.zoom
|
||||||
};
|
};
|
||||||
@@ -98,7 +93,6 @@ Singleton {
|
|||||||
hideWhenNotif: barConfig.hideWhenNotif,
|
hideWhenNotif: barConfig.hideWhenNotif,
|
||||||
rounding: barConfig.rounding,
|
rounding: barConfig.rounding,
|
||||||
border: barConfig.border,
|
border: barConfig.border,
|
||||||
smoothing: barConfig.smoothing,
|
|
||||||
height: barConfig.height,
|
height: barConfig.height,
|
||||||
popouts: {
|
popouts: {
|
||||||
tray: barConfig.popouts.tray,
|
tray: barConfig.popouts.tray,
|
||||||
@@ -134,8 +128,7 @@ Singleton {
|
|||||||
background: serializeBackground(),
|
background: serializeBackground(),
|
||||||
launcher: serializeLauncher(),
|
launcher: serializeLauncher(),
|
||||||
colors: serializeColors(),
|
colors: serializeColors(),
|
||||||
dock: serializeDock(),
|
dock: serializeDock()
|
||||||
screenshot: serializeScreenshot()
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,7 +180,6 @@ Singleton {
|
|||||||
logo: general.logo,
|
logo: general.logo,
|
||||||
wallpaperPath: general.wallpaperPath,
|
wallpaperPath: general.wallpaperPath,
|
||||||
desktopIcons: general.desktopIcons,
|
desktopIcons: general.desktopIcons,
|
||||||
dateFormat: general.dateFormat,
|
|
||||||
color: {
|
color: {
|
||||||
mode: general.color.mode,
|
mode: general.color.mode,
|
||||||
smart: general.color.smart,
|
smart: general.color.smart,
|
||||||
@@ -241,7 +233,6 @@ Singleton {
|
|||||||
return {
|
return {
|
||||||
recolorLogo: lock.recolorLogo,
|
recolorLogo: lock.recolorLogo,
|
||||||
enableFprint: lock.enableFprint,
|
enableFprint: lock.enableFprint,
|
||||||
showNotifContent: lock.showNotifContent,
|
|
||||||
maxFprintTries: lock.maxFprintTries,
|
maxFprintTries: lock.maxFprintTries,
|
||||||
blurAmount: lock.blurAmount,
|
blurAmount: lock.blurAmount,
|
||||||
sizes: {
|
sizes: {
|
||||||
@@ -283,20 +274,6 @@ Singleton {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function serializeScreenshot(): var {
|
|
||||||
return {
|
|
||||||
enable_pp: screenshot.enable_pp,
|
|
||||||
mode: screenshot.mode,
|
|
||||||
corner_radius: screenshot.corner_radius,
|
|
||||||
drop_shadow: screenshot.drop_shadow,
|
|
||||||
rounded_corners: screenshot.rounded_corners,
|
|
||||||
shadow_blur_radius: screenshot.shadow_blur_radius,
|
|
||||||
shadow_color: screenshot.shadow_color,
|
|
||||||
shadow_offset_x: screenshot.shadow_offset_x,
|
|
||||||
shadow_offset_y: screenshot.shadow_offset_y
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function serializeServices(): var {
|
function serializeServices(): var {
|
||||||
return {
|
return {
|
||||||
weatherLocation: services.weatherLocation,
|
weatherLocation: services.weatherLocation,
|
||||||
@@ -452,8 +429,6 @@ Singleton {
|
|||||||
}
|
}
|
||||||
property Overview overview: Overview {
|
property Overview overview: Overview {
|
||||||
}
|
}
|
||||||
property Screenshot screenshot: Screenshot {
|
|
||||||
}
|
|
||||||
property Services services: Services {
|
property Services services: Services {
|
||||||
}
|
}
|
||||||
property SidebarConfig sidebar: SidebarConfig {
|
property SidebarConfig sidebar: SidebarConfig {
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ pragma ComponentBehavior: Bound
|
|||||||
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Io
|
import Quickshell.Io
|
||||||
import Quickshell.Hyprland
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import ZShell
|
import ZShell
|
||||||
import qs.Helpers
|
import qs.Helpers
|
||||||
@@ -80,32 +79,10 @@ Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function reloadHyprRules(): void {
|
function reloadHyprRules(): void {
|
||||||
const blur = transparency.enabled ? 1 : 0;
|
const barStr = "keyword layerrule %1 %2, match:namespace ZShell-Bar";
|
||||||
const alpha = transparency.base - 0.03;
|
const authStr = "keyword layerrule %1 %2, match:namespace ZShell-Auth";
|
||||||
|
Hypr.extras.batchMessage([barStr.arg("blur").arg(transparency.enabled ? 1 : 0), barStr.arg("ignore_alpha").arg(transparency.base - 0.03)]);
|
||||||
const rules = `
|
Hypr.extras.batchMessage([authStr.arg("blur").arg(transparency.enabled ? 1 : 0), authStr.arg("ignore_alpha").arg(transparency.base - 0.03)]);
|
||||||
hl.layer_rule({
|
|
||||||
match = { namespace = "ZShell-Bar" },
|
|
||||||
blur = ${blur}
|
|
||||||
})
|
|
||||||
|
|
||||||
hl.layer_rule({
|
|
||||||
match = { namespace = "ZShell-Bar" },
|
|
||||||
ignore_alpha = ${alpha}
|
|
||||||
})
|
|
||||||
|
|
||||||
hl.layer_rule({
|
|
||||||
match = { namespace = "ZShell-Auth" },
|
|
||||||
blur = ${blur}
|
|
||||||
})
|
|
||||||
|
|
||||||
hl.layer_rule({
|
|
||||||
match = { namespace = "ZShell-Auth" },
|
|
||||||
ignore_alpha = ${alpha}
|
|
||||||
})
|
|
||||||
`;
|
|
||||||
|
|
||||||
Hypr.extras.message(`eval ${rules}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setMode(mode: string): void {
|
function setMode(mode: string): void {
|
||||||
@@ -116,14 +93,6 @@ Singleton {
|
|||||||
|
|
||||||
Component.onCompleted: debounceTimer.triggered()
|
Component.onCompleted: debounceTimer.triggered()
|
||||||
|
|
||||||
Connections {
|
|
||||||
function onUsingLuaChanged(): void {
|
|
||||||
root.reloadHyprRules();
|
|
||||||
}
|
|
||||||
|
|
||||||
target: Hyprland
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
function onConfigReloaded(): void {
|
function onConfigReloaded(): void {
|
||||||
root.reloadHyprRules();
|
root.reloadHyprRules();
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ JsonObject {
|
|||||||
}
|
}
|
||||||
property Color color: Color {
|
property Color color: Color {
|
||||||
}
|
}
|
||||||
property string dateFormat: "ddd d MMM - hh:mm:ss"
|
|
||||||
property bool desktopIcons: false
|
property bool desktopIcons: false
|
||||||
property Idle idle: Idle {
|
property Idle idle: Idle {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ JsonObject {
|
|||||||
property bool enableFprint: true
|
property bool enableFprint: true
|
||||||
property int maxFprintTries: 3
|
property int maxFprintTries: 3
|
||||||
property bool recolorLogo: false
|
property bool recolorLogo: false
|
||||||
property bool showNotifContent: false
|
|
||||||
property Sizes sizes: Sizes {
|
property Sizes sizes: Sizes {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
import Quickshell.Io
|
|
||||||
|
|
||||||
JsonObject {
|
|
||||||
property real corner_radius: 12.0
|
|
||||||
property bool drop_shadow: true
|
|
||||||
property bool enable_pp: true
|
|
||||||
property string mode: "manual"
|
|
||||||
property bool rounded_corners: false
|
|
||||||
property real shadow_blur_radius: 22.0
|
|
||||||
property list<int> shadow_color: [0, 0, 0, 160]
|
|
||||||
property real shadow_offset_x: 5.0
|
|
||||||
property real shadow_offset_y: 5.0
|
|
||||||
}
|
|
||||||
+175
-24
@@ -3,33 +3,184 @@ import QtQuick
|
|||||||
Canvas {
|
Canvas {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
property rect dirtyRect: Qt.rect(0, 0, 0, 0)
|
||||||
|
property bool frameQueued: false
|
||||||
|
property bool fullRepaintPending: true
|
||||||
|
property point lastPoint: Qt.point(0, 0)
|
||||||
|
property real minPointDistance: 2.0
|
||||||
property color penColor: "white"
|
property color penColor: "white"
|
||||||
property real penWidth: 4
|
property real penWidth: 4
|
||||||
property var points: []
|
property var pendingSegments: []
|
||||||
|
property bool strokeActive: false
|
||||||
|
property var strokes: []
|
||||||
|
|
||||||
function clear(): void {
|
function appendPoint(x, y) {
|
||||||
var ctx = getContext('2d');
|
if (!strokeActive || strokes.length === 0)
|
||||||
root.points = [];
|
|
||||||
ctx.reset();
|
|
||||||
root.requestPaint();
|
|
||||||
}
|
|
||||||
|
|
||||||
renderStrategy: Canvas.Cooperative
|
|
||||||
|
|
||||||
onPaint: {
|
|
||||||
if (points.length < 2)
|
|
||||||
return;
|
return;
|
||||||
var ctx = root.getContext('2d');
|
const dx = x - lastPoint.x;
|
||||||
ctx.save();
|
const dy = y - lastPoint.y;
|
||||||
ctx.lineWidth = root.penWidth;
|
|
||||||
ctx.strokeStyle = root.penColor;
|
if ((dx * dx + dy * dy) < (minPointDistance * minPointDistance))
|
||||||
ctx.lineCap = "round";
|
return;
|
||||||
ctx.beginPath();
|
const x1 = lastPoint.x;
|
||||||
ctx.moveTo(points[0].x, points[0].y);
|
const y1 = lastPoint.y;
|
||||||
for (var i = 1; i < points.length; i++)
|
const x2 = x;
|
||||||
ctx.lineTo(points[i].x, points[i].y);
|
const y2 = y;
|
||||||
ctx.stroke();
|
|
||||||
points = points.slice(points.length - 2);
|
strokes[strokes.length - 1].push(Qt.point(x2, y2));
|
||||||
ctx.restore();
|
|
||||||
|
pendingSegments.push({
|
||||||
|
dot: false,
|
||||||
|
x1: x1,
|
||||||
|
y1: y1,
|
||||||
|
x2: x2,
|
||||||
|
y2: y2
|
||||||
|
});
|
||||||
|
|
||||||
|
lastPoint = Qt.point(x2, y2);
|
||||||
|
queueDirty(segmentDirtyRect(x1, y1, x2, y2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function beginStroke(x, y) {
|
||||||
|
const p = Qt.point(x, y);
|
||||||
|
strokes.push([p]);
|
||||||
|
lastPoint = p;
|
||||||
|
strokeActive = true;
|
||||||
|
|
||||||
|
pendingSegments.push({
|
||||||
|
dot: true,
|
||||||
|
x: x,
|
||||||
|
y: y
|
||||||
|
});
|
||||||
|
|
||||||
|
queueDirty(pointDirtyRect(x, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
function clear() {
|
||||||
|
strokes = [];
|
||||||
|
pendingSegments = [];
|
||||||
|
dirtyRect = Qt.rect(0, 0, 0, 0);
|
||||||
|
fullRepaintPending = true;
|
||||||
|
markDirty(Qt.rect(0, 0, width, height));
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawDot(ctx, x, y) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(x, y, penWidth / 2, 0, Math.PI * 2);
|
||||||
|
ctx.fill();
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawSegment(ctx, x1, y1, x2, y2) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(x1, y1);
|
||||||
|
ctx.lineTo(x2, y2);
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
|
||||||
|
function endStroke() {
|
||||||
|
strokeActive = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function pointDirtyRect(x, y) {
|
||||||
|
const pad = penWidth + 2;
|
||||||
|
return Qt.rect(x - pad, y - pad, pad * 2, pad * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
function queueDirty(r) {
|
||||||
|
dirtyRect = unionRects(dirtyRect, r);
|
||||||
|
|
||||||
|
if (frameQueued)
|
||||||
|
return;
|
||||||
|
frameQueued = true;
|
||||||
|
|
||||||
|
requestAnimationFrame(function () {
|
||||||
|
frameQueued = false;
|
||||||
|
|
||||||
|
if (dirtyRect.width > 0 && dirtyRect.height > 0) {
|
||||||
|
markDirty(dirtyRect);
|
||||||
|
dirtyRect = Qt.rect(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function replayAll(ctx) {
|
||||||
|
ctx.clearRect(0, 0, width, height);
|
||||||
|
|
||||||
|
for (const stroke of strokes) {
|
||||||
|
if (!stroke || stroke.length === 0)
|
||||||
|
continue;
|
||||||
|
if (stroke.length === 1) {
|
||||||
|
const p = stroke[0];
|
||||||
|
drawDot(ctx, p.x, p.y);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(stroke[0].x, stroke[0].y);
|
||||||
|
for (let i = 1; i < stroke.length; ++i)
|
||||||
|
ctx.lineTo(stroke[i].x, stroke[i].y);
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function requestFullRepaint() {
|
||||||
|
fullRepaintPending = true;
|
||||||
|
markDirty(Qt.rect(0, 0, width, height));
|
||||||
|
}
|
||||||
|
|
||||||
|
function segmentDirtyRect(x1, y1, x2, y2) {
|
||||||
|
const pad = penWidth + 2;
|
||||||
|
const left = Math.min(x1, x2) - pad;
|
||||||
|
const top = Math.min(y1, y2) - pad;
|
||||||
|
const right = Math.max(x1, x2) + pad;
|
||||||
|
const bottom = Math.max(y1, y2) + pad;
|
||||||
|
return Qt.rect(left, top, right - left, bottom - top);
|
||||||
|
}
|
||||||
|
|
||||||
|
function unionRects(a, b) {
|
||||||
|
if (a.width <= 0 || a.height <= 0)
|
||||||
|
return b;
|
||||||
|
if (b.width <= 0 || b.height <= 0)
|
||||||
|
return a;
|
||||||
|
|
||||||
|
const left = Math.min(a.x, b.x);
|
||||||
|
const top = Math.min(a.y, b.y);
|
||||||
|
const right = Math.max(a.x + a.width, b.x + b.width);
|
||||||
|
const bottom = Math.max(a.y + a.height, b.y + b.height);
|
||||||
|
|
||||||
|
return Qt.rect(left, top, right - left, bottom - top);
|
||||||
|
}
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
contextType: "2d"
|
||||||
|
renderStrategy: Canvas.Threaded
|
||||||
|
renderTarget: Canvas.Image
|
||||||
|
|
||||||
|
onHeightChanged: requestFullRepaint()
|
||||||
|
onPaint: region => {
|
||||||
|
const ctx = getContext("2d");
|
||||||
|
|
||||||
|
ctx.lineCap = "round";
|
||||||
|
ctx.lineJoin = "round";
|
||||||
|
ctx.lineWidth = penWidth;
|
||||||
|
ctx.strokeStyle = penColor;
|
||||||
|
ctx.fillStyle = penColor;
|
||||||
|
|
||||||
|
if (fullRepaintPending) {
|
||||||
|
fullRepaintPending = false;
|
||||||
|
replayAll(ctx);
|
||||||
|
pendingSegments = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const seg of pendingSegments) {
|
||||||
|
if (seg.dot)
|
||||||
|
drawDot(ctx, seg.x, seg.y);
|
||||||
|
else
|
||||||
|
drawSegment(ctx, seg.x1, seg.y1, seg.x2, seg.y2);
|
||||||
|
}
|
||||||
|
|
||||||
|
pendingSegments = [];
|
||||||
|
}
|
||||||
|
onWidthChanged: requestFullRepaint()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,10 +30,8 @@ CustomMouseArea {
|
|||||||
const x = event.x;
|
const x = event.x;
|
||||||
const y = event.y;
|
const y = event.y;
|
||||||
|
|
||||||
if (root.visibilities.isDrawing && (event.buttons & Qt.LeftButton)) {
|
if (event.buttons & Qt.LeftButton)
|
||||||
root.drawing.points.push(Qt.point(x, y));
|
root.drawing.appendPoint(x, y);
|
||||||
root.drawing.requestPaint();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (root.inLeftPanel(root.popout, x, y)) {
|
if (root.inLeftPanel(root.popout, x, y)) {
|
||||||
root.z = -2;
|
root.z = -2;
|
||||||
@@ -46,8 +44,7 @@ CustomMouseArea {
|
|||||||
|
|
||||||
if (root.visibilities.isDrawing && (event.buttons & Qt.LeftButton)) {
|
if (root.visibilities.isDrawing && (event.buttons & Qt.LeftButton)) {
|
||||||
root.panels.drawing.expanded = false;
|
root.panels.drawing.expanded = false;
|
||||||
root.drawing.points.push(Qt.point(x, y));
|
root.drawing.beginStroke(x, y);
|
||||||
root.drawing.requestPaint();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,6 +52,7 @@ CustomMouseArea {
|
|||||||
root.drawing.clear();
|
root.drawing.clear();
|
||||||
}
|
}
|
||||||
onReleased: {
|
onReleased: {
|
||||||
root.drawing.points = [];
|
if (root.visibilities.isDrawing)
|
||||||
|
root.drawing.endStroke();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,37 +12,22 @@ Scope {
|
|||||||
required property ShellScreen screen
|
required property ShellScreen screen
|
||||||
|
|
||||||
ExclusionZone {
|
ExclusionZone {
|
||||||
id: top
|
|
||||||
|
|
||||||
anchors.top: true
|
anchors.top: true
|
||||||
exclusiveZone: root.bar.exclusiveZone
|
exclusiveZone: root.bar.exclusiveZone
|
||||||
}
|
}
|
||||||
|
|
||||||
ExclusionZone {
|
ExclusionZone {
|
||||||
id: left
|
|
||||||
|
|
||||||
anchors.left: true
|
anchors.left: true
|
||||||
}
|
}
|
||||||
|
|
||||||
ExclusionZone {
|
ExclusionZone {
|
||||||
id: right
|
|
||||||
|
|
||||||
anchors.right: true
|
anchors.right: true
|
||||||
}
|
}
|
||||||
|
|
||||||
ExclusionZone {
|
ExclusionZone {
|
||||||
id: bottom
|
|
||||||
|
|
||||||
anchors.bottom: true
|
anchors.bottom: true
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer {
|
|
||||||
interval: 5000
|
|
||||||
running: true
|
|
||||||
|
|
||||||
onTriggered: console.log("top height:", top.exclusiveZone, "left width:", left.exclusiveZone, "right width:", right.exclusiveZone, "bottom height:", bottom.exclusiveZone)
|
|
||||||
}
|
|
||||||
|
|
||||||
component ExclusionZone: CustomWindow {
|
component ExclusionZone: CustomWindow {
|
||||||
exclusiveZone: Config.barConfig.border
|
exclusiveZone: Config.barConfig.border
|
||||||
implicitHeight: 1
|
implicitHeight: 1
|
||||||
|
|||||||
+17
-17
@@ -78,7 +78,7 @@ CustomMouseArea {
|
|||||||
const dragY = y - dragStart.y;
|
const dragY = y - dragStart.y;
|
||||||
|
|
||||||
if (root.visibilities.isDrawing && !root.inLeftPanel(root.panels.drawing, x, y)) {
|
if (root.visibilities.isDrawing && !root.inLeftPanel(root.panels.drawing, x, y)) {
|
||||||
// root.input.z = 2;
|
root.input.z = 2;
|
||||||
root.panels.drawing.expanded = false;
|
root.panels.drawing.expanded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,25 +96,25 @@ CustomMouseArea {
|
|||||||
if (dragY < -10)
|
if (dragY < -10)
|
||||||
visibilities.dock = true;
|
visibilities.dock = true;
|
||||||
|
|
||||||
if (panels.sidebar.width === 0) {
|
if (panels.sidebar.width === 0) {
|
||||||
const showOsd = inRightPanel(panels.osdWrapper, x, y);
|
const showOsd = inRightPanel(panels.osdWrapper, x, y);
|
||||||
|
|
||||||
if (showOsd) {
|
if (showOsd) {
|
||||||
osdShortcutActive = false;
|
osdShortcutActive = false;
|
||||||
root.panels.osd.hovered = true;
|
root.panels.osd.hovered = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const outOfSidebar = x < width - panels.sidebar.width;
|
const outOfSidebar = x < width - panels.sidebar.width;
|
||||||
const showOsd = outOfSidebar && inRightPanel(panels.osdWrapper, x, y);
|
const showOsd = outOfSidebar && inRightPanel(panels.osdWrapper, x, y);
|
||||||
|
|
||||||
if (!osdShortcutActive) {
|
if (!osdShortcutActive) {
|
||||||
visibilities.osd = showOsd;
|
visibilities.osd = showOsd;
|
||||||
root.panels.osd.hovered = showOsd;
|
root.panels.osd.hovered = showOsd;
|
||||||
} else if (showOsd) {
|
} else if (showOsd) {
|
||||||
osdShortcutActive = false;
|
osdShortcutActive = false;
|
||||||
root.panels.osd.hovered = true;
|
root.panels.osd.hovered = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (Config.dock.enable && !Config.dock.hoverToReveal && !visibilities.dock && !visibilities.launcher && inBottomPanel(panels.dock, x, y))
|
if (Config.dock.enable && !Config.dock.hoverToReveal && !visibilities.dock && !visibilities.launcher && inBottomPanel(panels.dock, x, y))
|
||||||
visibilities.dock = true;
|
visibilities.dock = true;
|
||||||
|
|||||||
+6
-92
@@ -13,7 +13,6 @@ import qs.Modules.Resources as Resources
|
|||||||
import qs.Modules.Settings as Settings
|
import qs.Modules.Settings as Settings
|
||||||
import qs.Modules.Drawing as Drawing
|
import qs.Modules.Drawing as Drawing
|
||||||
import qs.Modules.Dock as Dock
|
import qs.Modules.Dock as Dock
|
||||||
import qs.Modules.SysTray.Popouts as SysPopouts
|
|
||||||
import qs.Config
|
import qs.Config
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
@@ -35,10 +34,8 @@ Item {
|
|||||||
readonly property alias resourcesWrapper: resourcesWrapper
|
readonly property alias resourcesWrapper: resourcesWrapper
|
||||||
required property ShellScreen screen
|
required property ShellScreen screen
|
||||||
readonly property alias settings: settings
|
readonly property alias settings: settings
|
||||||
readonly property alias settingsWrapper: settingsWrapper
|
|
||||||
readonly property alias sidebar: sidebar
|
readonly property alias sidebar: sidebar
|
||||||
readonly property alias toasts: toasts
|
readonly property alias toasts: toasts
|
||||||
readonly property alias traySubmenus: traySubmenus
|
|
||||||
readonly property alias utilities: utilities
|
readonly property alias utilities: utilities
|
||||||
required property PersistentProperties visibilities
|
required property PersistentProperties visibilities
|
||||||
|
|
||||||
@@ -95,79 +92,6 @@ Item {
|
|||||||
visibilities: root.visibilities
|
visibilities: root.visibilities
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
|
||||||
id: traySubmenus
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
model: popouts.content.state.submenus
|
|
||||||
|
|
||||||
CustomClippingRect {
|
|
||||||
id: subMenuWrapper
|
|
||||||
|
|
||||||
required property int index
|
|
||||||
required property var modelData
|
|
||||||
property real targetX: 0
|
|
||||||
property real targetY: 0
|
|
||||||
|
|
||||||
function updatePosition() {
|
|
||||||
let sourceItem = modelData.sourceItem;
|
|
||||||
if (!sourceItem || !sourceItem.parent)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let mapped = sourceItem.mapToItem(root, 0, -Appearance.padding.small);
|
|
||||||
|
|
||||||
let rightX = mapped.x + modelData.sourceWidth + Config.barConfig.border;
|
|
||||||
let leftX = mapped.x - implicitWidth - Config.barConfig.border;
|
|
||||||
|
|
||||||
if (rightX + implicitWidth > root.width) {
|
|
||||||
targetX = leftX;
|
|
||||||
} else {
|
|
||||||
targetX = rightX;
|
|
||||||
}
|
|
||||||
|
|
||||||
targetY = mapped.y;
|
|
||||||
|
|
||||||
if (targetY + implicitHeight > root.height) {
|
|
||||||
targetY = root.height - implicitHeight;
|
|
||||||
}
|
|
||||||
if (targetY < 0)
|
|
||||||
targetY = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
implicitHeight: subMenuContent.implicitHeight + Appearance.padding.small * 2
|
|
||||||
implicitWidth: subMenuContent.implicitWidth + Appearance.padding.small * 2
|
|
||||||
radius: Appearance.rounding.normal
|
|
||||||
x: targetX
|
|
||||||
y: targetY
|
|
||||||
|
|
||||||
Behavior on implicitHeight {
|
|
||||||
Anim {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Behavior on implicitWidth {
|
|
||||||
Anim {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
updatePosition();
|
|
||||||
}
|
|
||||||
onImplicitHeightChanged: updatePosition()
|
|
||||||
onImplicitWidthChanged: updatePosition()
|
|
||||||
|
|
||||||
SysPopouts.SubMenu {
|
|
||||||
id: subMenuContent
|
|
||||||
|
|
||||||
anchors.centerIn: parent
|
|
||||||
handle: subMenuWrapper.modelData.handle
|
|
||||||
level: subMenuWrapper.index + 1
|
|
||||||
popouts: root.popouts.state
|
|
||||||
screen: root.screen
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Modules.ClipWrapper {
|
Modules.ClipWrapper {
|
||||||
id: popouts
|
id: popouts
|
||||||
|
|
||||||
@@ -252,25 +176,15 @@ Item {
|
|||||||
visibilities: root.visibilities
|
visibilities: root.visibilities
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Settings.Wrapper {
|
||||||
id: settingsWrapper
|
id: settings
|
||||||
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
clip: true
|
// anchors.centerIn: parent
|
||||||
implicitHeight: settings.implicitHeight * (1 - settings.offsetScale)
|
panels: root
|
||||||
implicitWidth: settings.implicitWidth
|
screen: root.screen
|
||||||
|
visibilities: root.visibilities
|
||||||
Settings.Wrapper {
|
|
||||||
id: settings
|
|
||||||
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
anchors.top: parent.top
|
|
||||||
// anchors.centerIn: parent
|
|
||||||
panels: root
|
|
||||||
screen: root.screen
|
|
||||||
visibilities: root.visibilities
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Dock.Wrapper {
|
Dock.Wrapper {
|
||||||
|
|||||||
+19
-69
@@ -3,7 +3,6 @@ pragma ComponentBehavior: Bound
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Effects
|
import QtQuick.Effects
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Io
|
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import Quickshell.Hyprland
|
import Quickshell.Hyprland
|
||||||
import ZShell.Blobs
|
import ZShell.Blobs
|
||||||
@@ -64,7 +63,7 @@ Variants {
|
|||||||
|
|
||||||
height: win.height - bar.implicitHeight - Config.barConfig.border
|
height: win.height - bar.implicitHeight - Config.barConfig.border
|
||||||
intersection: Intersection.Xor
|
intersection: Intersection.Xor
|
||||||
regions: [...popoutRegions.instances, ...subMenuRegions.instances]
|
regions: popoutRegions.instances
|
||||||
width: win.width - Config.barConfig.border * 2
|
width: win.width - Config.barConfig.border * 2
|
||||||
x: Config.barConfig.border
|
x: Config.barConfig.border
|
||||||
y: bar.implicitHeight
|
y: bar.implicitHeight
|
||||||
@@ -93,22 +92,6 @@ Variants {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Variants {
|
|
||||||
id: subMenuRegions
|
|
||||||
|
|
||||||
model: panels.traySubmenus.children
|
|
||||||
|
|
||||||
Region {
|
|
||||||
required property Item modelData
|
|
||||||
|
|
||||||
height: modelData.height
|
|
||||||
intersection: Intersection.Subtract
|
|
||||||
width: modelData.width
|
|
||||||
x: modelData.x + panels.traySubmenus.x + Config.barConfig.border
|
|
||||||
y: modelData.y + panels.traySubmenus.y + bar.implicitHeight
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HyprlandFocusGrab {
|
HyprlandFocusGrab {
|
||||||
id: focusGrab
|
id: focusGrab
|
||||||
|
|
||||||
@@ -144,14 +127,6 @@ Variants {
|
|||||||
Component.onCompleted: Visibilities.load(scope.modelData, this)
|
Component.onCompleted: Visibilities.load(scope.modelData, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
IpcHandler {
|
|
||||||
function toggleLauncher(fix: string): void {
|
|
||||||
visibilities.launcher = !visibilities.launcher;
|
|
||||||
}
|
|
||||||
|
|
||||||
target: "visibilities"
|
|
||||||
}
|
|
||||||
|
|
||||||
Binding {
|
Binding {
|
||||||
property: "bar"
|
property: "bar"
|
||||||
target: visibilities
|
target: visibilities
|
||||||
@@ -174,7 +149,6 @@ Variants {
|
|||||||
id: blobGroup
|
id: blobGroup
|
||||||
|
|
||||||
color: DynamicColors.palette.m3surface
|
color: DynamicColors.palette.m3surface
|
||||||
smoothing: Config.barConfig.smoothing
|
|
||||||
|
|
||||||
Behavior on color {
|
Behavior on color {
|
||||||
CAnim {
|
CAnim {
|
||||||
@@ -196,34 +170,28 @@ Variants {
|
|||||||
PanelBg {
|
PanelBg {
|
||||||
id: dashBg
|
id: dashBg
|
||||||
|
|
||||||
property real extraHeight: 0.2
|
deformAmount: 0.08 * Config.appearance.deform.scale
|
||||||
|
implicitHeight: panels.dashboard.height
|
||||||
deformAmount: 0.06
|
|
||||||
implicitHeight: panels.dashboard.height * (1 + extraHeight)
|
|
||||||
implicitWidth: panels.dashboard.width
|
implicitWidth: panels.dashboard.width
|
||||||
panel: panels.dashboardWrapper
|
panel: panels.dashboard
|
||||||
radius: Appearance.rounding.normal
|
radius: Appearance.rounding.normal
|
||||||
x: panels.dashboardWrapper.x + panels.dashboard.x + Config.barConfig.border
|
x: panels.dashboardWrapper.x + panels.dashboard.x + Config.barConfig.border
|
||||||
y: panels.dashboardWrapper.y + panels.dashboard.y + bar.implicitHeight - panels.dashboard.height * extraHeight
|
y: panels.dashboardWrapper.y + panels.dashboard.y + bar.implicitHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
PanelBg {
|
PanelBg {
|
||||||
id: launcherBg
|
id: launcherBg
|
||||||
|
|
||||||
property real extraHeight: 0.2
|
deformAmount: 0.08 * Config.appearance.deform.scale
|
||||||
|
|
||||||
deformAmount: 0.06
|
|
||||||
implicitHeight: panels.launcher.height * (1 + extraHeight)
|
|
||||||
panel: panels.launcher
|
panel: panels.launcher
|
||||||
radius: Appearance.rounding.smallest + 5
|
radius: Appearance.rounding.smallest + 5
|
||||||
y: panels.launcher.y + bar.implicitHeight
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PanelBg {
|
PanelBg {
|
||||||
id: sidebarBg
|
id: sidebarBg
|
||||||
|
|
||||||
bottomLeftRadius: 0
|
bottomLeftRadius: 0
|
||||||
deformAmount: 0.04
|
deformAmount: 0.08 * Config.appearance.deform.scale
|
||||||
exclude: panels.sidebar.offsetScale > 0.08 ? [] : [utilsBg]
|
exclude: panels.sidebar.offsetScale > 0.08 ? [] : [utilsBg]
|
||||||
implicitHeight: panel.height * (1 / rawDeformMatrix.m22) + 2
|
implicitHeight: panel.height * (1 / rawDeformMatrix.m22) + 2
|
||||||
panel: panels.sidebar
|
panel: panels.sidebar
|
||||||
@@ -232,10 +200,10 @@ Variants {
|
|||||||
PanelBg {
|
PanelBg {
|
||||||
id: osdBg
|
id: osdBg
|
||||||
|
|
||||||
deformAmount: 0.1
|
deformAmount: 0.1 * Config.appearance.deform.scale
|
||||||
implicitHeight: panels.osd.height
|
implicitHeight: panels.osd.height
|
||||||
implicitWidth: panels.osd.width
|
implicitWidth: panels.osd.width
|
||||||
panel: panels.osdWrapper
|
panel: panels.osd
|
||||||
radius: 20
|
radius: 20
|
||||||
x: panels.osdWrapper.x + panels.osd.x + Config.barConfig.border
|
x: panels.osdWrapper.x + panels.osd.x + Config.barConfig.border
|
||||||
y: panels.osdWrapper.y + panels.osd.y + bar.implicitHeight
|
y: panels.osdWrapper.y + panels.osd.y + bar.implicitHeight
|
||||||
@@ -250,7 +218,7 @@ Variants {
|
|||||||
PanelBg {
|
PanelBg {
|
||||||
id: utilsBg
|
id: utilsBg
|
||||||
|
|
||||||
deformAmount: panels.sidebar.visible ? (0.1) : (0.1)
|
deformAmount: panels.sidebar.visible ? (0.1 * Config.appearance.deform.scale) : (0.1 * Config.appearance.deform.scale)
|
||||||
exclude: panels.sidebar.offsetScale > 0.08 ? [] : [sidebarBg]
|
exclude: panels.sidebar.offsetScale > 0.08 ? [] : [sidebarBg]
|
||||||
panel: panels.utilities
|
panel: panels.utilities
|
||||||
topLeftRadius: 0
|
topLeftRadius: 0
|
||||||
@@ -261,11 +229,11 @@ Variants {
|
|||||||
|
|
||||||
property real extraHeight: panels.popouts.isDetached ? 0 : 0.2
|
property real extraHeight: panels.popouts.isDetached ? 0 : 0.2
|
||||||
|
|
||||||
deformAmount: panels.popouts.isDetached ? 0.05 : panels.popouts.hasCurrent ? 0.15 : 0.1
|
deformAmount: panels.popouts.isDetached ? 0.05 * Config.appearance.deform.scale : panels.popouts.hasCurrent ? 0.15 * Config.appearance.deform.scale : 0.1 * Config.appearance.deform.scale
|
||||||
implicitHeight: panels.popouts.height * (1 + extraHeight)
|
implicitHeight: panels.popouts.height * (1 + extraHeight)
|
||||||
implicitWidth: panels.popouts.width
|
implicitWidth: panels.popouts.width
|
||||||
panel: panels.popoutsWrapper
|
panel: panels.popouts
|
||||||
radius: (panels.popouts.currentName.startsWith("audio") || panels.popouts.currentName.startsWith("updates")) ? Appearance.rounding.normal : 20 * Appearance.rounding.scale
|
radius: (panels.popouts.currentName.startsWith("audio") || panels.popouts.currentName.startsWith("updates")) ? Appearance.rounding.normal : Appearance.rounding.smallest
|
||||||
x: panels.popoutsWrapper.x + panels.popouts.x + Config.barConfig.border
|
x: panels.popoutsWrapper.x + panels.popouts.x + Config.barConfig.border
|
||||||
y: panels.popoutsWrapper.y + panels.popouts.y + bar.implicitHeight - panels.popouts.height * extraHeight
|
y: panels.popoutsWrapper.y + panels.popouts.y + bar.implicitHeight - panels.popouts.height * extraHeight
|
||||||
|
|
||||||
@@ -278,10 +246,10 @@ Variants {
|
|||||||
PanelBg {
|
PanelBg {
|
||||||
id: resourcesBg
|
id: resourcesBg
|
||||||
|
|
||||||
deformAmount: 0.05
|
deformAmount: 0.08 * Config.appearance.deform.scale
|
||||||
implicitHeight: panels.resources.height
|
implicitHeight: panels.resources.height
|
||||||
implicitWidth: panels.resources.width
|
implicitWidth: panels.resources.width
|
||||||
panel: panels.resourcesWrapper
|
panel: panels.resources
|
||||||
radius: Appearance.rounding.normal
|
radius: Appearance.rounding.normal
|
||||||
x: panels.resourcesWrapper.x + panels.resources.x + Config.barConfig.border
|
x: panels.resourcesWrapper.x + panels.resources.x + Config.barConfig.border
|
||||||
y: panels.resourcesWrapper.y + panels.resources.y + bar.implicitHeight
|
y: panels.resourcesWrapper.y + panels.resources.y + bar.implicitHeight
|
||||||
@@ -290,23 +258,17 @@ Variants {
|
|||||||
PanelBg {
|
PanelBg {
|
||||||
id: settingsBg
|
id: settingsBg
|
||||||
|
|
||||||
property real extraHeight: 0.2
|
deformAmount: 0.08 * Config.appearance.deform.scale
|
||||||
|
|
||||||
deformAmount: 0.03
|
|
||||||
implicitHeight: panels.settings.height * (1 + extraHeight)
|
|
||||||
implicitWidth: panels.settings.width
|
|
||||||
panel: panels.settings
|
panel: panels.settings
|
||||||
radius: Appearance.rounding.large
|
radius: Appearance.rounding.large
|
||||||
topLeftRadius: Appearance.rounding.large + Appearance.padding.smaller
|
topLeftRadius: Appearance.rounding.large + Appearance.padding.smaller
|
||||||
topRightRadius: Appearance.rounding.large + Appearance.padding.smaller
|
topRightRadius: Appearance.rounding.large + Appearance.padding.smaller
|
||||||
x: panels.settingsWrapper.x + panels.settings.x + Config.barConfig.border
|
|
||||||
y: panels.settingsWrapper.y + panels.settings.y + bar.implicitHeight - panels.settings.height * extraHeight
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PanelBg {
|
PanelBg {
|
||||||
id: dockBg
|
id: dockBg
|
||||||
|
|
||||||
deformAmount: 0.08
|
deformAmount: 0.08 * Config.appearance.deform.scale
|
||||||
panel: panels.dock
|
panel: panels.dock
|
||||||
radius: Appearance.rounding.normal
|
radius: Appearance.rounding.normal
|
||||||
}
|
}
|
||||||
@@ -314,22 +276,10 @@ Variants {
|
|||||||
PanelBg {
|
PanelBg {
|
||||||
id: drawingBg
|
id: drawingBg
|
||||||
|
|
||||||
deformAmount: 0.08
|
deformAmount: 0.08 * Config.appearance.deform.scale
|
||||||
panel: panels.drawing
|
panel: panels.drawing
|
||||||
radius: Appearance.rounding.normal
|
radius: Appearance.rounding.normal
|
||||||
}
|
}
|
||||||
|
|
||||||
Repeater {
|
|
||||||
model: panels.traySubmenus.children
|
|
||||||
|
|
||||||
PanelBg {
|
|
||||||
required property Item modelData
|
|
||||||
|
|
||||||
deformAmount: 0.1
|
|
||||||
panel: modelData
|
|
||||||
radius: 20 * Appearance.rounding.scale
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Drawing {
|
Drawing {
|
||||||
@@ -421,7 +371,7 @@ Variants {
|
|||||||
property real deformAmount: 0.15
|
property real deformAmount: 0.15
|
||||||
required property Item panel
|
required property Item panel
|
||||||
|
|
||||||
deformScale: (deformAmount * Config.appearance.deform.scale) / 10000
|
deformScale: deformAmount / 10000
|
||||||
group: blobGroup
|
group: blobGroup
|
||||||
implicitHeight: panel.height
|
implicitHeight: panel.height
|
||||||
implicitWidth: panel.width
|
implicitWidth: panel.width
|
||||||
|
|||||||
@@ -346,6 +346,7 @@ Singleton {
|
|||||||
|
|
||||||
stdout: StdioCollector {
|
stdout: StdioCollector {
|
||||||
onStreamFinished: {
|
onStreamFinished: {
|
||||||
|
console.log("this is running");
|
||||||
if (root.gpuType === "GENERIC") {
|
if (root.gpuType === "GENERIC") {
|
||||||
const percs = text.trim().split("\n");
|
const percs = text.trim().split("\n");
|
||||||
const sum = percs.reduce((acc, d) => acc + parseInt(d, 10), 0);
|
const sum = percs.reduce((acc, d) => acc + parseInt(d, 10), 0);
|
||||||
|
|||||||
+44
-20
@@ -7,30 +7,23 @@ import QtQuick
|
|||||||
Singleton {
|
Singleton {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
readonly property string defaultUserFile: "/etc/zshell-greeter/default-user"
|
// The list of users that can log in graphically
|
||||||
property int selectedIndex: 0
|
// Each user object has: username, uid, home, shell, gecos (full name), face (avatar path)
|
||||||
readonly property var selectedUser: selectedIndex >= 0 && selectedIndex < users.length ? users[selectedIndex] : null
|
|
||||||
readonly property string selectedUsername: selectedUser ? selectedUser.username : ""
|
|
||||||
property var users: []
|
property var users: []
|
||||||
|
|
||||||
function saveDefaultUser(): void {
|
// The currently selected user index
|
||||||
if (selectedUser) {
|
property int selectedIndex: 0
|
||||||
defaultUserStorage.setText(selectedUser.username);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function selectNext(): void {
|
// The currently selected user object (or null if none)
|
||||||
if (users.length === 0)
|
readonly property var selectedUser: selectedIndex >= 0 && selectedIndex < users.length ? users[selectedIndex] : null
|
||||||
return;
|
|
||||||
selectedIndex = (selectedIndex + 1) % users.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
function selectPrevious(): void {
|
// Convenience property for the selected username
|
||||||
if (users.length === 0)
|
readonly property string selectedUsername: selectedUser ? selectedUser.username : ""
|
||||||
return;
|
|
||||||
selectedIndex = (selectedIndex - 1 + users.length) % users.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Path to store the default user preference
|
||||||
|
readonly property string defaultUserFile: "/etc/zshell-greeter/default-user"
|
||||||
|
|
||||||
|
// Select a user by username
|
||||||
function selectUser(username: string): bool {
|
function selectUser(username: string): bool {
|
||||||
for (let i = 0; i < users.length; i++) {
|
for (let i = 0; i < users.length; i++) {
|
||||||
if (users[i].username === username) {
|
if (users[i].username === username) {
|
||||||
@@ -41,6 +34,28 @@ Singleton {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Select the next user in the list (wraps around)
|
||||||
|
function selectNext(): void {
|
||||||
|
if (users.length === 0)
|
||||||
|
return;
|
||||||
|
selectedIndex = (selectedIndex + 1) % users.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select the previous user in the list (wraps around)
|
||||||
|
function selectPrevious(): void {
|
||||||
|
if (users.length === 0)
|
||||||
|
return;
|
||||||
|
selectedIndex = (selectedIndex - 1 + users.length) % users.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the current user as the default for next login
|
||||||
|
function saveDefaultUser(): void {
|
||||||
|
if (selectedUser) {
|
||||||
|
defaultUserStorage.setText(selectedUser.username);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process to fetch the list of graphical users
|
||||||
Process {
|
Process {
|
||||||
id: userLister
|
id: userLister
|
||||||
|
|
||||||
@@ -52,10 +67,13 @@ Singleton {
|
|||||||
try {
|
try {
|
||||||
root.users = JSON.parse(text);
|
root.users = JSON.parse(text);
|
||||||
|
|
||||||
|
// If we have users and no selection yet, try to select the default user
|
||||||
if (root.users.length > 0) {
|
if (root.users.length > 0) {
|
||||||
|
// Try to load the default user
|
||||||
if (defaultUserStorage.loaded) {
|
if (defaultUserStorage.loaded) {
|
||||||
const defaultUsername = defaultUserStorage.text().trim();
|
const defaultUsername = defaultUserStorage.text().trim();
|
||||||
if (defaultUsername && !root.selectUser(defaultUsername)) {
|
if (defaultUsername && !root.selectUser(defaultUsername)) {
|
||||||
|
// Default user not found, select first user
|
||||||
root.selectedIndex = 0;
|
root.selectedIndex = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -69,14 +87,15 @@ Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FileView for persisting the default user
|
||||||
FileView {
|
FileView {
|
||||||
id: defaultUserStorage
|
id: defaultUserStorage
|
||||||
|
|
||||||
path: root.defaultUserFile
|
path: root.defaultUserFile
|
||||||
preload: true
|
preload: true
|
||||||
|
|
||||||
onLoadFailed: {}
|
|
||||||
onLoaded: {
|
onLoaded: {
|
||||||
|
// If users are already loaded, try to select the default user
|
||||||
if (root.users.length > 0) {
|
if (root.users.length > 0) {
|
||||||
const defaultUsername = text().trim();
|
const defaultUsername = text().trim();
|
||||||
if (defaultUsername) {
|
if (defaultUsername) {
|
||||||
@@ -84,5 +103,10 @@ Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onLoadFailed: {
|
||||||
|
// File doesn't exist yet, that's fine - we'll create it on first save
|
||||||
|
console.log("No default user file found, will use first user");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,72 +0,0 @@
|
|||||||
pragma Singleton
|
|
||||||
|
|
||||||
import QtQuick
|
|
||||||
import Quickshell
|
|
||||||
import Quickshell.Io
|
|
||||||
import ZShell
|
|
||||||
import qs.Config
|
|
||||||
|
|
||||||
Singleton {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property alias enabled: props.enabled
|
|
||||||
|
|
||||||
function setHyprConf(): void {
|
|
||||||
Hypr.extras.applyOptions({
|
|
||||||
"animations.enabled": 0,
|
|
||||||
"decoration.shadow.enabled": 0,
|
|
||||||
"decoration.blur.enabled": 0,
|
|
||||||
"general.border_size": 0,
|
|
||||||
"decoration.rounding": 0
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onEnabledChanged: {
|
|
||||||
if (enabled) {
|
|
||||||
setHyprConf();
|
|
||||||
if (Config.utilities.toasts.gameModeChanged)
|
|
||||||
Toaster.toast(qsTr("Game mode enabled"), qsTr("Disabled Hyprland animations, blur, shadows and corner radius"), "gamepad");
|
|
||||||
} else {
|
|
||||||
Hypr.extras.message("reload");
|
|
||||||
if (Config.utilities.toasts.gameModeChanged)
|
|
||||||
Toaster.toast(qsTr("Game mode disabled"), qsTr("Hyprland settings restored"), "gamepad");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PersistentProperties {
|
|
||||||
id: props
|
|
||||||
|
|
||||||
property bool enabled: Hypr.options["animations:enabled"] === 0
|
|
||||||
|
|
||||||
reloadableId: "gamemode"
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
function onConfigReloaded(): void {
|
|
||||||
if (props.enabled)
|
|
||||||
root.setHyprConf();
|
|
||||||
}
|
|
||||||
|
|
||||||
target: Hypr
|
|
||||||
}
|
|
||||||
|
|
||||||
IpcHandler {
|
|
||||||
function disable(): void {
|
|
||||||
props.enabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function enable(): void {
|
|
||||||
props.enabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isEnabled(): bool {
|
|
||||||
return props.enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggle(): void {
|
|
||||||
props.enabled = !props.enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
target: "gameMode"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
pragma Singleton
|
||||||
|
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Networking
|
||||||
|
|
||||||
|
Singleton {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property NetworkDevice activeDevice: devices.find(d => d.connected)
|
||||||
|
property list<NetworkDevice> devices: Networking.devices.values
|
||||||
|
}
|
||||||
+1
-2
@@ -66,8 +66,7 @@ MouseArea {
|
|||||||
|
|
||||||
function save(): void {
|
function save(): void {
|
||||||
const tmpfile = Qt.resolvedUrl(`/tmp/zshell-picker-${Quickshell.processId}-${Date.now()}.png`);
|
const tmpfile = Qt.resolvedUrl(`/tmp/zshell-picker-${Quickshell.processId}-${Date.now()}.png`);
|
||||||
const cmd = Config.screenshot.enable_pp ? ["zshell-img-tools", "--image"] : ["swappy", "-f"];
|
ZShellIo.saveItem(screencopy, tmpfile, Qt.rect(Math.ceil(rsx), Math.ceil(rsy), Math.floor(sw), Math.floor(sh)), path => Quickshell.execDetached(["swappy", "-f", path]));
|
||||||
ZShellIo.saveItem(screencopy, tmpfile, Qt.rect(Math.ceil(rsx), Math.ceil(rsy), Math.floor(sw), Math.floor(sh)), path => Quickshell.execDetached([...cmd, path]));
|
|
||||||
closeAnim.start();
|
closeAnim.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-7
@@ -1,23 +1,18 @@
|
|||||||
pragma Singleton
|
pragma Singleton
|
||||||
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import QtQuick
|
|
||||||
import qs.Config
|
|
||||||
|
|
||||||
Singleton {
|
Singleton {
|
||||||
id: root
|
readonly property string amPmStr: timeComponents[2] ?? ""
|
||||||
|
|
||||||
readonly property date date: clock.date
|
readonly property date date: clock.date
|
||||||
readonly property string dateStr: format(Config.general.dateFormat)
|
|
||||||
property alias enabled: clock.enabled
|
property alias enabled: clock.enabled
|
||||||
readonly property string hourStr: timeComponents[0] ?? ""
|
readonly property string hourStr: timeComponents[0] ?? ""
|
||||||
readonly property int hours: clock.hours
|
readonly property int hours: clock.hours
|
||||||
readonly property string minuteStr: timeComponents[1] ?? ""
|
readonly property string minuteStr: timeComponents[1] ?? ""
|
||||||
readonly property int minutes: clock.minutes
|
readonly property int minutes: clock.minutes
|
||||||
readonly property string secondStr: timeComponents[2] ?? ""
|
|
||||||
readonly property int seconds: clock.seconds
|
readonly property int seconds: clock.seconds
|
||||||
readonly property list<string> timeComponents: timeStr.split(":")
|
readonly property list<string> timeComponents: timeStr.split(":")
|
||||||
readonly property string timeStr: format("hh:mm:ss")
|
readonly property string timeStr: format("hh:mm")
|
||||||
|
|
||||||
function format(fmt: string): string {
|
function format(fmt: string): string {
|
||||||
return Qt.formatDateTime(clock.date, fmt);
|
return Qt.formatDateTime(clock.date, fmt);
|
||||||
|
|||||||
@@ -11,13 +11,10 @@ Singleton {
|
|||||||
id: root
|
id: root
|
||||||
|
|
||||||
property int availableUpdates: 0
|
property int availableUpdates: 0
|
||||||
property string cmd: ""
|
|
||||||
property bool commandReady
|
property bool commandReady
|
||||||
property bool loaded
|
property bool loaded
|
||||||
property double now: Date.now()
|
property double now: Date.now()
|
||||||
property var updates: ({})
|
property var updates: ({})
|
||||||
property bool updating
|
|
||||||
property string updatingPackage: ""
|
|
||||||
|
|
||||||
function formatUpdateTime(timestamp) {
|
function formatUpdateTime(timestamp) {
|
||||||
const diffMs = root.now - timestamp;
|
const diffMs = root.now - timestamp;
|
||||||
@@ -37,22 +34,6 @@ Singleton {
|
|||||||
return Qt.formatDateTime(new Date(timestamp), "dd hh:mm");
|
return Qt.formatDateTime(new Date(timestamp), "dd hh:mm");
|
||||||
}
|
}
|
||||||
|
|
||||||
function performPackageUpdate(pkg: string): void {
|
|
||||||
if (root.cmd === "pacman")
|
|
||||||
pkgUpdateProc.command = ["pkexec", root.cmd, "--noconfirm", "-Sy", pkg];
|
|
||||||
else
|
|
||||||
pkgUpdateProc.command = [root.cmd, "--noconfirm", "--sudo", "pkexec", "-Sy", pkg];
|
|
||||||
pkgUpdateProc.running = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function performSystemUpdate(): void {
|
|
||||||
if (root.cmd === "pacman")
|
|
||||||
sysUpdateProc.command = ["pkexec", root.cmd, "--noconfirm", "-Syu"];
|
|
||||||
else
|
|
||||||
sysUpdateProc.command = [root.cmd, "--noconfirm", "--sudo", "pkexec", "-Syu"];
|
|
||||||
sysUpdateProc.running = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
onUpdatesChanged: {
|
onUpdatesChanged: {
|
||||||
if (!root.loaded)
|
if (!root.loaded)
|
||||||
return;
|
return;
|
||||||
@@ -111,28 +92,6 @@ Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Process {
|
|
||||||
id: updateCmdDetect
|
|
||||||
|
|
||||||
command: ["sh", "-c", "command -v yay || command -v paru"]
|
|
||||||
running: true
|
|
||||||
|
|
||||||
stdout: StdioCollector {
|
|
||||||
onStreamFinished: {
|
|
||||||
const cmd = this.text.trim();
|
|
||||||
let helper;
|
|
||||||
|
|
||||||
if (cmd.length > 0) {
|
|
||||||
helper = cmd.split("/").pop();
|
|
||||||
} else {
|
|
||||||
helper = "pacman";
|
|
||||||
}
|
|
||||||
|
|
||||||
root.cmd = helper;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Process {
|
Process {
|
||||||
id: updatesProc
|
id: updatesProc
|
||||||
|
|
||||||
@@ -156,44 +115,6 @@ Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Process {
|
|
||||||
id: sysUpdateProc
|
|
||||||
|
|
||||||
command: []
|
|
||||||
running: false
|
|
||||||
|
|
||||||
stdout: StdioCollector {
|
|
||||||
onStreamFinished: {
|
|
||||||
root.updating = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onRunningChanged: {
|
|
||||||
if (running)
|
|
||||||
root.updating = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Process {
|
|
||||||
id: pkgUpdateProc
|
|
||||||
|
|
||||||
command: []
|
|
||||||
running: false
|
|
||||||
|
|
||||||
stdout: StdioCollector {
|
|
||||||
onStreamFinished: {
|
|
||||||
root.updating = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onRunningChanged: {
|
|
||||||
if (running) {
|
|
||||||
root.updatingPackage = command[command.length - 1];
|
|
||||||
root.updating = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
id: saveTimer
|
id: saveTimer
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ Searcher {
|
|||||||
property string actualCurrent: WallpaperPath.currentWallpaperPath
|
property string actualCurrent: WallpaperPath.currentWallpaperPath
|
||||||
readonly property string current: showPreview ? previewPath : actualCurrent
|
readonly property string current: showPreview ? previewPath : actualCurrent
|
||||||
property string previewPath
|
property string previewPath
|
||||||
property bool recentlyChanged
|
|
||||||
property bool showPreview: false
|
property bool showPreview: false
|
||||||
|
|
||||||
function preview(path: string): void {
|
function preview(path: string): void {
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ import QtQuick
|
|||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import qs.Config
|
import qs.Config
|
||||||
import qs.Modules
|
import qs.Modules
|
||||||
import qs.Helpers
|
import qs.Helpers as Helpers
|
||||||
import qs.Components
|
import qs.Components
|
||||||
|
|
||||||
CustomRect {
|
CustomRect {
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ Item {
|
|||||||
readonly property Item current: currentPopout?.item ?? null
|
readonly property Item current: currentPopout?.item ?? null
|
||||||
readonly property Popout currentPopout: content.children.find(c => c.shouldBeActive) ?? null
|
readonly property Popout currentPopout: content.children.find(c => c.shouldBeActive) ?? null
|
||||||
required property PopoutState popouts
|
required property PopoutState popouts
|
||||||
required property ShellScreen screen
|
|
||||||
|
|
||||||
implicitHeight: (currentPopout?.implicitHeight ?? 0) + 5 * 2
|
implicitHeight: (currentPopout?.implicitHeight ?? 0) + 5 * 2
|
||||||
implicitWidth: (currentPopout?.implicitWidth ?? 0) + 5 * 2
|
implicitWidth: (currentPopout?.implicitWidth ?? 0) + 5 * 2
|
||||||
@@ -64,7 +63,6 @@ Item {
|
|||||||
|
|
||||||
TrayMenuPopout {
|
TrayMenuPopout {
|
||||||
popouts: root.popouts
|
popouts: root.popouts
|
||||||
screen: root.screen
|
|
||||||
trayItem: trayMenu.modelData.menu
|
trayItem: trayMenu.modelData.menu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import Quickshell
|
||||||
|
import QtQuick
|
||||||
|
import qs.Config
|
||||||
|
import qs.Helpers
|
||||||
|
import qs.Components
|
||||||
|
|
||||||
|
CustomRect {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property PersistentProperties visibilities
|
||||||
|
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.bottomMargin: 6
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: 6
|
||||||
|
color: DynamicColors.tPalette.m3surfaceContainer
|
||||||
|
implicitWidth: 40
|
||||||
|
radius: Appearance.rounding.full
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
onClicked: {
|
||||||
|
root.visibilities.dashboard = !root.visibilities.dashboard;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
color: DynamicColors.palette.m3onSurface
|
||||||
|
text: "widgets"
|
||||||
|
}
|
||||||
|
}
|
||||||
+77
-25
@@ -12,29 +12,90 @@ Item {
|
|||||||
|
|
||||||
required property Canvas drawing
|
required property Canvas drawing
|
||||||
property bool expanded: true
|
property bool expanded: true
|
||||||
property real offsetScale: shouldBeActive ? 0 : 1
|
|
||||||
required property ShellScreen screen
|
required property ShellScreen screen
|
||||||
readonly property bool shouldBeActive: visibilities.isDrawing
|
readonly property bool shouldBeActive: visibilities.isDrawing
|
||||||
required property var visibilities
|
required property var visibilities
|
||||||
|
|
||||||
anchors.leftMargin: (-implicitWidth - 5) * offsetScale
|
|
||||||
implicitHeight: content.implicitHeight
|
implicitHeight: content.implicitHeight
|
||||||
implicitWidth: root.expanded ? content.implicitWidth : icon.implicitWidth
|
implicitWidth: 0
|
||||||
opacity: 1 - offsetScale
|
visible: width > 0
|
||||||
visible: offsetScale < 1
|
|
||||||
|
|
||||||
Behavior on implicitWidth {
|
states: [
|
||||||
Anim {
|
State {
|
||||||
duration: Appearance.anim.durations.expressiveDefaultSpatial
|
name: "hidden"
|
||||||
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
|
when: !root.shouldBeActive
|
||||||
|
|
||||||
|
PropertyChanges {
|
||||||
|
root.implicitWidth: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertyChanges {
|
||||||
|
icon.opacity: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertyChanges {
|
||||||
|
content.opacity: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: "collapsed"
|
||||||
|
when: root.shouldBeActive && !root.expanded
|
||||||
|
|
||||||
|
PropertyChanges {
|
||||||
|
root.implicitWidth: icon.implicitWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertyChanges {
|
||||||
|
icon.opacity: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertyChanges {
|
||||||
|
content.opacity: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: "visible"
|
||||||
|
when: root.shouldBeActive && root.expanded
|
||||||
|
|
||||||
|
PropertyChanges {
|
||||||
|
root.implicitWidth: content.implicitWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertyChanges {
|
||||||
|
icon.opacity: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertyChanges {
|
||||||
|
content.opacity: 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
]
|
||||||
Behavior on offsetScale {
|
transitions: [
|
||||||
Anim {
|
Transition {
|
||||||
duration: Appearance.anim.durations.expressiveDefaultSpatial
|
from: "*"
|
||||||
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
|
to: "*"
|
||||||
|
|
||||||
|
ParallelAnimation {
|
||||||
|
Anim {
|
||||||
|
easing.bezierCurve: MaterialEasing.expressiveEffects
|
||||||
|
property: "implicitWidth"
|
||||||
|
target: root
|
||||||
|
}
|
||||||
|
|
||||||
|
Anim {
|
||||||
|
duration: Appearance.anim.durations.small
|
||||||
|
property: "opacity"
|
||||||
|
target: icon
|
||||||
|
}
|
||||||
|
|
||||||
|
Anim {
|
||||||
|
duration: Appearance.anim.durations.small
|
||||||
|
property: "opacity"
|
||||||
|
target: content
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
]
|
||||||
|
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (!visible)
|
if (!visible)
|
||||||
@@ -48,12 +109,8 @@ Item {
|
|||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
height: content.contentItem.height
|
height: content.contentItem.height
|
||||||
opacity: root.expanded ? 0 : 1
|
opacity: 1
|
||||||
|
|
||||||
Behavior on opacity {
|
|
||||||
Anim {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sourceComponent: MaterialIcon {
|
sourceComponent: MaterialIcon {
|
||||||
font.pointSize: Appearance.font.size.larger
|
font.pointSize: Appearance.font.size.larger
|
||||||
text: "arrow_forward_ios"
|
text: "arrow_forward_ios"
|
||||||
@@ -65,12 +122,7 @@ Item {
|
|||||||
|
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
opacity: root.expanded ? 1 : 0
|
|
||||||
|
|
||||||
Behavior on opacity {
|
|
||||||
Anim {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sourceComponent: Content {
|
sourceComponent: Content {
|
||||||
drawing: root.drawing
|
drawing: root.drawing
|
||||||
visibilities: root.visibilities
|
visibilities: root.visibilities
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ Searcher {
|
|||||||
|
|
||||||
function launch(entry: DesktopEntry): void {
|
function launch(entry: DesktopEntry): void {
|
||||||
appDb.incrementFrequency(entry.id);
|
appDb.incrementFrequency(entry.id);
|
||||||
|
console.log(root.command);
|
||||||
|
|
||||||
if (entry.runInTerminal)
|
if (entry.runInTerminal)
|
||||||
Quickshell.execDetached({
|
Quickshell.execDetached({
|
||||||
|
|||||||
@@ -8,25 +8,21 @@ import qs.Helpers
|
|||||||
Scope {
|
Scope {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
readonly property bool enabled: !Players.list.some(p => p.isPlaying)
|
|
||||||
required property Lock lock
|
required property Lock lock
|
||||||
|
readonly property bool enabled: !Players.list.some( p => p.isPlaying )
|
||||||
|
|
||||||
function handleIdleAction(action: var): void {
|
function handleIdleAction( action: var ): void {
|
||||||
if (!action)
|
if ( !action )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (action === "lock")
|
if ( action === "lock" )
|
||||||
lock.lock.locked = true;
|
lock.lock.locked = true;
|
||||||
else if (action === "unlock")
|
else if ( action === "unlock" )
|
||||||
lock.lock.locked = false;
|
lock.lock.locked = false;
|
||||||
else if (action === "dpms on")
|
else if ( typeof action === "string" )
|
||||||
Hypr.dispatch('hl.dsp.dpms({ action = "enable" })');
|
Hypr.dispatch( action );
|
||||||
else if (action === "dpms off")
|
|
||||||
Hypr.dispatch('hl.dsp.dpms({ action = "disable" })');
|
|
||||||
else if (typeof action === "string")
|
|
||||||
Hypr.dispatch(action);
|
|
||||||
else
|
else
|
||||||
Quickshell.execDetached(action);
|
Quickshell.execDetached( action );
|
||||||
}
|
}
|
||||||
|
|
||||||
Variants {
|
Variants {
|
||||||
@@ -37,8 +33,7 @@ Scope {
|
|||||||
|
|
||||||
enabled: root.enabled && modelData.timeout > 0 ? true : false
|
enabled: root.enabled && modelData.timeout > 0 ? true : false
|
||||||
timeout: modelData.timeout
|
timeout: modelData.timeout
|
||||||
|
onIsIdleChanged: root.handleIdleAction( isIdle ? modelData.idleAction : modelData.activeAction )
|
||||||
onIsIdleChanged: root.handleIdleAction(isIdle ? modelData.idleAction : modelData.activeAction)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -284,8 +284,6 @@ CustomRect {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
color: root.urgency === "critical" ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onSurface
|
color: root.urgency === "critical" ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onSurface
|
||||||
text: {
|
text: {
|
||||||
if (!Config.lock.showNotifContent)
|
|
||||||
return "Unlock to view";
|
|
||||||
const summary = modelData.summary.replace(/\n/g, " ");
|
const summary = modelData.summary.replace(/\n/g, " ");
|
||||||
const body = modelData.body.replace(/\n/g, " ");
|
const body = modelData.body.replace(/\n/g, " ");
|
||||||
const color = root.urgency === "critical" ? DynamicColors.palette.m3secondary : DynamicColors.palette.m3outline;
|
const color = root.urgency === "critical" ? DynamicColors.palette.m3secondary : DynamicColors.palette.m3outline;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ Item {
|
|||||||
|
|
||||||
readonly property int padding: 6
|
readonly property int padding: 6
|
||||||
required property Item panels
|
required property Item panels
|
||||||
|
required property Item sidebarPanel
|
||||||
required property PersistentProperties visibilities
|
required property PersistentProperties visibilities
|
||||||
|
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
@@ -43,7 +44,7 @@ Item {
|
|||||||
|
|
||||||
return Math.min((QsWindow.window?.screen?.height ?? 0) - 1 * 2, height + padding * 2);
|
return Math.min((QsWindow.window?.screen?.height ?? 0) - 1 * 2, height + padding * 2);
|
||||||
}
|
}
|
||||||
implicitWidth: Config.notifs.sizes.width + padding * 2
|
implicitWidth: Math.max(sidebarPanel.width * (1 - sidebarPanel.offsetScale), Config.notifs.sizes.width + padding * 2)
|
||||||
|
|
||||||
Behavior on implicitHeight {
|
Behavior on implicitHeight {
|
||||||
Anim {
|
Anim {
|
||||||
@@ -72,8 +73,9 @@ Item {
|
|||||||
required property NotifServer.Notif modelData
|
required property NotifServer.Notif modelData
|
||||||
readonly property alias nonAnimHeight: notif.nonAnimHeight
|
readonly property alias nonAnimHeight: notif.nonAnimHeight
|
||||||
|
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
implicitHeight: notif.implicitHeight + (idx === 0 ? 0 : 8)
|
implicitHeight: notif.implicitHeight + (idx === 0 ? 0 : 8)
|
||||||
implicitWidth: notif.implicitWidth
|
|
||||||
|
|
||||||
ListView.onRemove: removeAnim.start()
|
ListView.onRemove: removeAnim.start()
|
||||||
onIndexChanged: {
|
onIndexChanged: {
|
||||||
@@ -124,16 +126,20 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ClippingRectangle {
|
ClippingRectangle {
|
||||||
|
// implicitWidth: notif.implicitWidth
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.topMargin: wrapper.idx === 0 ? 0 : 8
|
anchors.topMargin: wrapper.idx === 0 ? 0 : 8
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
implicitHeight: notif.implicitHeight
|
implicitHeight: notif.implicitHeight
|
||||||
implicitWidth: notif.implicitWidth
|
|
||||||
radius: Appearance.rounding.smallest / 2
|
radius: Appearance.rounding.smallest / 2
|
||||||
|
|
||||||
Notification {
|
Notification {
|
||||||
id: notif
|
id: notif
|
||||||
|
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
modelData: wrapper.modelData
|
modelData: wrapper.modelData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ CustomRect {
|
|||||||
required property NotifServer.Notif modelData
|
required property NotifServer.Notif modelData
|
||||||
readonly property int nonAnimHeight: summary.implicitHeight + (root.expanded ? appName.height + body.height + actions.height + actions.anchors.topMargin : bodyPreview.height) + inner.anchors.margins * 2
|
readonly property int nonAnimHeight: summary.implicitHeight + (root.expanded ? appName.height + body.height + actions.height + actions.anchors.topMargin : bodyPreview.height) + inner.anchors.margins * 2
|
||||||
|
|
||||||
|
// implicitWidth: Config.notifs.sizes.width
|
||||||
color: root.modelData.urgency === NotificationUrgency.Critical ? DynamicColors.palette.m3secondaryContainer : DynamicColors.tPalette.m3surfaceContainer
|
color: root.modelData.urgency === NotificationUrgency.Critical ? DynamicColors.palette.m3secondaryContainer : DynamicColors.tPalette.m3surfaceContainer
|
||||||
implicitHeight: inner.implicitHeight
|
implicitHeight: inner.implicitHeight
|
||||||
implicitWidth: Config.notifs.sizes.width
|
|
||||||
radius: 6
|
radius: 6
|
||||||
x: Config.notifs.sizes.width
|
x: Config.notifs.sizes.width
|
||||||
|
|
||||||
|
|||||||
@@ -78,10 +78,6 @@ LazyListView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onDoubleClicked: event => {
|
|
||||||
if (event.button === Qt.LeftButton)
|
|
||||||
notifInner.toggleExpand(!notifInner.expanded);
|
|
||||||
}
|
|
||||||
onPositionChanged: event => {
|
onPositionChanged: event => {
|
||||||
if (pressed) {
|
if (pressed) {
|
||||||
const diffY = event.y - startY;
|
const diffY = event.y - startY;
|
||||||
|
|||||||
@@ -79,10 +79,6 @@ LazyListView {
|
|||||||
|
|
||||||
Component.onCompleted: modelData?.lock(this)
|
Component.onCompleted: modelData?.lock(this)
|
||||||
Component.onDestruction: modelData?.unlock(this)
|
Component.onDestruction: modelData?.unlock(this)
|
||||||
onDoubleClicked: event => {
|
|
||||||
if (event.button === Qt.LeftButton)
|
|
||||||
root.requestToggleExpand(!root.expanded);
|
|
||||||
}
|
|
||||||
onPositionChanged: event => {
|
onPositionChanged: event => {
|
||||||
if (pressed && !root.expanded) {
|
if (pressed && !root.expanded) {
|
||||||
const diffY = event.y - startY;
|
const diffY = event.y - startY;
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import QtQuick.Layouts
|
|||||||
import qs.Components
|
import qs.Components
|
||||||
import qs.Config
|
import qs.Config
|
||||||
import qs.Modules
|
import qs.Modules
|
||||||
import qs.Helpers
|
|
||||||
import qs.Daemons
|
import qs.Daemons
|
||||||
|
|
||||||
CustomRect {
|
CustomRect {
|
||||||
@@ -33,7 +32,7 @@ CustomRect {
|
|||||||
Toggle {
|
Toggle {
|
||||||
checked: Network.wifiEnabled
|
checked: Network.wifiEnabled
|
||||||
icon: Network.wifiEnabled ? "wifi" : "wifi_off"
|
icon: Network.wifiEnabled ? "wifi" : "wifi_off"
|
||||||
visible: QSNetwork.Networking.devices.values.some(n => n.type === QSNetwork.DeviceType.Wifi)
|
visible: QSNetwork.Networking.devices.values.length > 0
|
||||||
|
|
||||||
onClicked: Network.toggleWifi()
|
onClicked: Network.toggleWifi()
|
||||||
}
|
}
|
||||||
@@ -80,13 +79,6 @@ CustomRect {
|
|||||||
adapter.enabled = !adapter.enabled;
|
adapter.enabled = !adapter.enabled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Toggle {
|
|
||||||
checked: GameMode.enabled
|
|
||||||
icon: GameMode.enabled ? "videogame_asset" : "videogame_asset_off"
|
|
||||||
|
|
||||||
onClicked: GameMode.enabled = !GameMode.enabled
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ Item {
|
|||||||
id: content
|
id: content
|
||||||
|
|
||||||
panels: root.panels
|
panels: root.panels
|
||||||
|
sidebarPanel: root.sidebarPanel
|
||||||
visibilities: root.visibilities
|
visibilities: root.visibilities
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +1,8 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
id: root
|
|
||||||
|
|
||||||
property string currentName
|
property string currentName
|
||||||
property bool hasCurrent
|
property bool hasCurrent
|
||||||
property var submenus: []
|
|
||||||
|
|
||||||
signal detachRequested(mode: string)
|
signal detachRequested(mode: string)
|
||||||
|
|
||||||
function clearSubmenus(): void {
|
|
||||||
submenus = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeSubmenus(level: int): void {
|
|
||||||
submenus = submenus.slice(0, level);
|
|
||||||
}
|
|
||||||
|
|
||||||
function pushSubmenu(level: int, handle: var, sourceItem: var, sourceWidth: int): void {
|
|
||||||
let newSubmenus = submenus.slice(0, level);
|
|
||||||
newSubmenus.push({
|
|
||||||
"handle": handle,
|
|
||||||
"sourceItem": sourceItem,
|
|
||||||
"sourceWidth": sourceWidth
|
|
||||||
});
|
|
||||||
submenus = newSubmenus;
|
|
||||||
}
|
|
||||||
|
|
||||||
onCurrentNameChanged: {
|
|
||||||
root.clearSubmenus();
|
|
||||||
}
|
|
||||||
onHasCurrentChanged: {
|
|
||||||
root.clearSubmenus();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ CustomRect {
|
|||||||
color: visibilities.resources ? DynamicColors.palette.m3primary : DynamicColors.tPalette.m3surfaceContainer
|
color: visibilities.resources ? DynamicColors.palette.m3primary : DynamicColors.tPalette.m3surfaceContainer
|
||||||
implicitHeight: Config.barConfig.height + Appearance.padding.smallest * 2
|
implicitHeight: Config.barConfig.height + Appearance.padding.smallest * 2
|
||||||
implicitWidth: rowLayout.implicitWidth + Appearance.padding.normal * 2
|
implicitWidth: rowLayout.implicitWidth + Appearance.padding.normal * 2
|
||||||
radius: Appearance.rounding.full
|
radius: height / 2
|
||||||
|
|
||||||
StateLayer {
|
StateLayer {
|
||||||
onClicked: root.visibilities.resources = !root.visibilities.resources
|
onClicked: root.visibilities.resources = !root.visibilities.resources
|
||||||
|
|||||||
@@ -104,18 +104,6 @@ Item {
|
|||||||
key: "launcher"
|
key: "launcher"
|
||||||
name: "Launcher"
|
name: "Launcher"
|
||||||
}
|
}
|
||||||
|
|
||||||
ListElement {
|
|
||||||
icon: "screenshot_region"
|
|
||||||
key: "screenshot"
|
|
||||||
name: "Screenshot"
|
|
||||||
}
|
|
||||||
|
|
||||||
ListElement {
|
|
||||||
icon: "cached"
|
|
||||||
key: "updates"
|
|
||||||
name: "Updates"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomClippingRect {
|
CustomClippingRect {
|
||||||
@@ -183,15 +171,9 @@ Item {
|
|||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
Layout.preferredWidth: icon.contentWidth
|
Layout.preferredWidth: icon.contentWidth
|
||||||
color: categoryItem.index === clayout.currentIndex ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSurface
|
color: categoryItem.index === clayout.currentIndex ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSurface
|
||||||
fill: categoryItem.index === clayout.currentIndex ? 1 : 0
|
|
||||||
font.pointSize: Appearance.font.size.small * 2
|
font.pointSize: Appearance.font.size.small * 2
|
||||||
text: categoryItem.icon
|
text: categoryItem.icon
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
|
||||||
Behavior on fill {
|
|
||||||
Anim {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomText {
|
CustomText {
|
||||||
|
|||||||
@@ -29,13 +29,13 @@ SettingsPage {
|
|||||||
step: 50
|
step: 50
|
||||||
}
|
}
|
||||||
|
|
||||||
Separator {
|
// Separator {
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
WallpaperCropper {
|
// WallpaperCropper {
|
||||||
Layout.fillWidth: true
|
// Layout.fillWidth: true
|
||||||
Layout.preferredHeight: 600
|
// Layout.preferredHeight: 300
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsSection {
|
SettingsSection {
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ SettingsPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SettingSpinBox {
|
SettingSpinBox {
|
||||||
min: 1
|
|
||||||
name: "Height"
|
name: "Height"
|
||||||
|
min: 1
|
||||||
object: Config.barConfig
|
object: Config.barConfig
|
||||||
setting: "height"
|
setting: "height"
|
||||||
}
|
}
|
||||||
@@ -29,8 +29,8 @@ SettingsPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SettingSpinBox {
|
SettingSpinBox {
|
||||||
min: 0
|
|
||||||
name: "Rounding"
|
name: "Rounding"
|
||||||
|
min: 0
|
||||||
object: Config.barConfig
|
object: Config.barConfig
|
||||||
setting: "rounding"
|
setting: "rounding"
|
||||||
}
|
}
|
||||||
@@ -39,21 +39,11 @@ SettingsPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SettingSpinBox {
|
SettingSpinBox {
|
||||||
min: 0
|
|
||||||
name: "Border"
|
name: "Border"
|
||||||
|
min: 0
|
||||||
object: Config.barConfig
|
object: Config.barConfig
|
||||||
setting: "border"
|
setting: "border"
|
||||||
}
|
}
|
||||||
|
|
||||||
Separator {
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingSpinBox {
|
|
||||||
min: 0
|
|
||||||
name: "Smoothing"
|
|
||||||
object: Config.barConfig
|
|
||||||
setting: "smoothing"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsSection {
|
SettingsSection {
|
||||||
@@ -155,8 +145,8 @@ SettingsPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SettingSpinBox {
|
SettingSpinBox {
|
||||||
min: 1
|
|
||||||
name: "Dock height"
|
name: "Dock height"
|
||||||
|
min: 1
|
||||||
object: Config.dock
|
object: Config.dock
|
||||||
setting: "height"
|
setting: "height"
|
||||||
}
|
}
|
||||||
@@ -183,8 +173,8 @@ SettingsPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SettingStringList {
|
SettingStringList {
|
||||||
addLabel: qsTr("Add pinned app")
|
|
||||||
name: "Pinned apps"
|
name: "Pinned apps"
|
||||||
|
addLabel: qsTr("Add pinned app")
|
||||||
object: Config.dock
|
object: Config.dock
|
||||||
setting: "pinnedApps"
|
setting: "pinnedApps"
|
||||||
}
|
}
|
||||||
@@ -193,8 +183,8 @@ SettingsPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SettingStringList {
|
SettingStringList {
|
||||||
addLabel: qsTr("Add ignored regex")
|
|
||||||
name: "Ignored app regexes"
|
name: "Ignored app regexes"
|
||||||
|
addLabel: qsTr("Add ignored regex")
|
||||||
object: Config.dock
|
object: Config.dock
|
||||||
setting: "ignoredAppRegexes"
|
setting: "ignoredAppRegexes"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,15 +47,6 @@ SettingsPage {
|
|||||||
object: Config.general
|
object: Config.general
|
||||||
setting: "desktopIcons"
|
setting: "desktopIcons"
|
||||||
}
|
}
|
||||||
|
|
||||||
Separator {
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingInput {
|
|
||||||
name: "Date format"
|
|
||||||
object: Config.general
|
|
||||||
setting: "dateFormat"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsSection {
|
SettingsSection {
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ SettingsPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SettingSpinBox {
|
SettingSpinBox {
|
||||||
min: 1
|
|
||||||
name: "Max fingerprint tries"
|
name: "Max fingerprint tries"
|
||||||
|
min: 1
|
||||||
object: Config.lock
|
object: Config.lock
|
||||||
setting: "maxFprintTries"
|
setting: "maxFprintTries"
|
||||||
step: 1
|
step: 1
|
||||||
@@ -41,18 +41,9 @@ SettingsPage {
|
|||||||
Separator {
|
Separator {
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingSwitch {
|
|
||||||
name: "Show notification details"
|
|
||||||
object: Config.lock
|
|
||||||
setting: "showNotifContent"
|
|
||||||
}
|
|
||||||
|
|
||||||
Separator {
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingSpinBox {
|
SettingSpinBox {
|
||||||
min: 0
|
|
||||||
name: "Blur amount"
|
name: "Blur amount"
|
||||||
|
min: 0
|
||||||
object: Config.lock
|
object: Config.lock
|
||||||
setting: "blurAmount"
|
setting: "blurAmount"
|
||||||
step: 1
|
step: 1
|
||||||
@@ -62,9 +53,9 @@ SettingsPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SettingSpinBox {
|
SettingSpinBox {
|
||||||
|
name: "Height multiplier"
|
||||||
max: 2
|
max: 2
|
||||||
min: 0.1
|
min: 0.1
|
||||||
name: "Height multiplier"
|
|
||||||
object: Config.lock.sizes
|
object: Config.lock.sizes
|
||||||
setting: "heightMult"
|
setting: "heightMult"
|
||||||
step: 0.05
|
step: 0.05
|
||||||
@@ -74,9 +65,9 @@ SettingsPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SettingSpinBox {
|
SettingSpinBox {
|
||||||
|
name: "Aspect ratio"
|
||||||
max: 4
|
max: 4
|
||||||
min: 0.5
|
min: 0.5
|
||||||
name: "Aspect ratio"
|
|
||||||
object: Config.lock.sizes
|
object: Config.lock.sizes
|
||||||
setting: "ratio"
|
setting: "ratio"
|
||||||
step: 0.05
|
step: 0.05
|
||||||
@@ -86,8 +77,8 @@ SettingsPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SettingSpinBox {
|
SettingSpinBox {
|
||||||
min: 100
|
|
||||||
name: "Center width"
|
name: "Center width"
|
||||||
|
min: 100
|
||||||
object: Config.lock.sizes
|
object: Config.lock.sizes
|
||||||
setting: "centerWidth"
|
setting: "centerWidth"
|
||||||
step: 10
|
step: 10
|
||||||
|
|||||||
@@ -22,13 +22,6 @@ ColumnLayout {
|
|||||||
Config.save();
|
Config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteTimeoutEntry(index) {
|
|
||||||
let list = [...Config.general.idle.timeouts];
|
|
||||||
list.splice(index, 1);
|
|
||||||
Config.general.idle.timeouts = list;
|
|
||||||
Config.save();
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateTimeoutEntry(i, key, value) {
|
function updateTimeoutEntry(i, key, value) {
|
||||||
const list = [...Config.general.idle.timeouts];
|
const list = [...Config.general.idle.timeouts];
|
||||||
let entry = list[i];
|
let entry = list[i];
|
||||||
@@ -56,9 +49,6 @@ ColumnLayout {
|
|||||||
onAddActiveActionRequested: {
|
onAddActiveActionRequested: {
|
||||||
root.updateTimeoutEntry(index, "activeAction", "");
|
root.updateTimeoutEntry(index, "activeAction", "");
|
||||||
}
|
}
|
||||||
onDeleteRequested: function (index) {
|
|
||||||
root.deleteTimeoutEntry(index);
|
|
||||||
}
|
|
||||||
onFieldEdited: function (key, value) {
|
onFieldEdited: function (key, value) {
|
||||||
root.updateTimeoutEntry(index, key, value);
|
root.updateTimeoutEntry(index, key, value);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,130 +0,0 @@
|
|||||||
import qs.Modules.Settings.Controls
|
|
||||||
import qs.Config
|
|
||||||
import qs.Components
|
|
||||||
|
|
||||||
SettingsPage {
|
|
||||||
SettingsSection {
|
|
||||||
sectionId: "Screenshot"
|
|
||||||
|
|
||||||
SettingsHeader {
|
|
||||||
name: "Screenshot"
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingSwitch {
|
|
||||||
name: "Enable effects"
|
|
||||||
object: Config.screenshot
|
|
||||||
setting: "enable_pp"
|
|
||||||
}
|
|
||||||
|
|
||||||
Separator {
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomSplitButtonRow {
|
|
||||||
// active: true
|
|
||||||
label: qsTr("Effects mode")
|
|
||||||
|
|
||||||
menuItems: [
|
|
||||||
MenuItem {
|
|
||||||
icon: "build"
|
|
||||||
text: qsTr("Manual")
|
|
||||||
value: "manual"
|
|
||||||
},
|
|
||||||
MenuItem {
|
|
||||||
icon: "rotate_auto"
|
|
||||||
text: qsTr("Auto")
|
|
||||||
value: "auto"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
onSelected: item => {
|
|
||||||
Config.screenshot.mode = item.value;
|
|
||||||
Config.save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Separator {
|
|
||||||
visible: Config.screenshot.mode === "manual"
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingSpinBox {
|
|
||||||
min: 0
|
|
||||||
name: "Corner radius"
|
|
||||||
object: Config.screenshot
|
|
||||||
setting: "corner_radius"
|
|
||||||
step: 1
|
|
||||||
visible: Config.screenshot.mode === "manual"
|
|
||||||
}
|
|
||||||
|
|
||||||
Separator {
|
|
||||||
visible: Config.screenshot.mode === "manual"
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingSwitch {
|
|
||||||
name: "Enable drop shadow"
|
|
||||||
object: Config.screenshot
|
|
||||||
setting: "drop_shadow"
|
|
||||||
visible: Config.screenshot.mode === "manual"
|
|
||||||
}
|
|
||||||
|
|
||||||
Separator {
|
|
||||||
visible: Config.screenshot.mode === "manual"
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingSwitch {
|
|
||||||
name: "Enable rounded corners"
|
|
||||||
object: Config.screenshot
|
|
||||||
setting: "rounded_corners"
|
|
||||||
visible: Config.screenshot.mode === "manual"
|
|
||||||
}
|
|
||||||
|
|
||||||
Separator {
|
|
||||||
visible: Config.screenshot.mode === "manual"
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingSpinBox {
|
|
||||||
min: 0
|
|
||||||
name: "Shadow blur radius"
|
|
||||||
object: Config.screenshot
|
|
||||||
setting: "shadow_blur_radius"
|
|
||||||
step: 1
|
|
||||||
visible: Config.screenshot.mode === "manual"
|
|
||||||
}
|
|
||||||
|
|
||||||
Separator {
|
|
||||||
visible: Config.screenshot.mode === "manual"
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingSwitch {
|
|
||||||
name: "Shadow color broken atm"
|
|
||||||
object: Config.Screenshot
|
|
||||||
setting: "shadow_color"
|
|
||||||
visible: Config.screenshot.mode === "manual"
|
|
||||||
}
|
|
||||||
|
|
||||||
Separator {
|
|
||||||
visible: Config.screenshot.mode === "manual"
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingSpinBox {
|
|
||||||
min: 0
|
|
||||||
name: "Shadow offset X"
|
|
||||||
object: Config.screenshot
|
|
||||||
setting: "shadow_offset_x"
|
|
||||||
step: 1
|
|
||||||
visible: Config.screenshot.mode === "manual"
|
|
||||||
}
|
|
||||||
|
|
||||||
Separator {
|
|
||||||
visible: Config.screenshot.mode === "manual"
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingSpinBox {
|
|
||||||
min: 0
|
|
||||||
name: "Shadow offset Y"
|
|
||||||
object: Config.screenshot
|
|
||||||
setting: "shadow_offset_y"
|
|
||||||
step: 1
|
|
||||||
visible: Config.screenshot.mode === "manual"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,197 +0,0 @@
|
|||||||
pragma ComponentBehavior: Bound
|
|
||||||
|
|
||||||
import Quickshell
|
|
||||||
import QtQuick.Layouts
|
|
||||||
import QtQuick
|
|
||||||
import qs.Config
|
|
||||||
import qs.Helpers
|
|
||||||
import qs.Components
|
|
||||||
import qs.Modules.Settings.Controls
|
|
||||||
|
|
||||||
CustomClippingRect {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
radius: Appearance.rounding.normal - Appearance.padding.smaller
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.margins: Appearance.padding.large
|
|
||||||
spacing: Appearance.spacing.large
|
|
||||||
|
|
||||||
MaterialIcon {
|
|
||||||
font.pointSize: Appearance.font.size.larger * 4
|
|
||||||
text: "update"
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
CustomText {
|
|
||||||
font.pointSize: Appearance.font.size.large * 2
|
|
||||||
text: "System updates"
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
id: row
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
CustomText {
|
|
||||||
id: text
|
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
|
|
||||||
Layout.fillWidth: true
|
|
||||||
font.pointSize: Appearance.font.size.larger
|
|
||||||
text: `${Updates.availableUpdates} available updates`
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomRect {
|
|
||||||
Layout.preferredHeight: 40
|
|
||||||
Layout.preferredWidth: 150
|
|
||||||
color: Updates.updating ? DynamicColors.layer(DynamicColors.palette.m3outline, 2) : DynamicColors.palette.m3primary
|
|
||||||
radius: Appearance.rounding.full
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
|
|
||||||
MaterialIcon {
|
|
||||||
animate: true
|
|
||||||
color: DynamicColors.palette.m3onPrimary
|
|
||||||
font.pointSize: Appearance.font.size.large
|
|
||||||
text: Updates.updating ? "update" : "download"
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomText {
|
|
||||||
color: Updates.updating ? DynamicColors.palette.m3onSurface : DynamicColors.palette.m3onPrimary
|
|
||||||
text: "Update all"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StateLayer {
|
|
||||||
color: DynamicColors.palette.m3onPrimary
|
|
||||||
disabled: Updates.updating
|
|
||||||
|
|
||||||
onClicked: Updates.performSystemUpdate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomListView {
|
|
||||||
id: view
|
|
||||||
|
|
||||||
readonly property int itemHeight: 50 + Appearance.padding.smaller * 2
|
|
||||||
|
|
||||||
Layout.fillHeight: true
|
|
||||||
Layout.fillWidth: true
|
|
||||||
clip: true
|
|
||||||
contentHeight: height
|
|
||||||
spacing: Appearance.spacing.normal
|
|
||||||
|
|
||||||
delegate: CustomRect {
|
|
||||||
id: update
|
|
||||||
|
|
||||||
required property var modelData
|
|
||||||
readonly property list<string> sections: modelData.update.split(" ")
|
|
||||||
|
|
||||||
color: DynamicColors.tPalette.m3surfaceContainer
|
|
||||||
implicitHeight: view.itemHeight
|
|
||||||
implicitWidth: parent.width
|
|
||||||
radius: Appearance.rounding.small - Appearance.padding.small
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.leftMargin: Appearance.padding.smaller
|
|
||||||
anchors.rightMargin: Appearance.padding.smaller
|
|
||||||
|
|
||||||
MaterialIcon {
|
|
||||||
font.pointSize: Appearance.font.size.large * 2
|
|
||||||
text: "package_2"
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
CustomText {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.preferredHeight: 25
|
|
||||||
elide: Text.ElideRight
|
|
||||||
font.pointSize: Appearance.font.size.large
|
|
||||||
text: update.sections[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomText {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
color: DynamicColors.palette.m3onSurfaceVariant
|
|
||||||
text: Updates.formatUpdateTime(update.modelData.timestamp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
Layout.fillHeight: true
|
|
||||||
Layout.preferredWidth: 500
|
|
||||||
|
|
||||||
MarqueeText {
|
|
||||||
id: versionFrom
|
|
||||||
|
|
||||||
Layout.fillHeight: true
|
|
||||||
Layout.preferredWidth: 225
|
|
||||||
animate: true
|
|
||||||
color: DynamicColors.palette.m3tertiary
|
|
||||||
font.pointSize: Appearance.font.size.large
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
marqueeEnabled: true
|
|
||||||
pauseMs: 4000
|
|
||||||
text: update.sections[1]
|
|
||||||
width: 225
|
|
||||||
}
|
|
||||||
|
|
||||||
MaterialIcon {
|
|
||||||
Layout.fillHeight: true
|
|
||||||
color: DynamicColors.palette.m3secondary
|
|
||||||
font.pointSize: Appearance.font.size.extraLarge
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
text: "arrow_right_alt"
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
MarqueeText {
|
|
||||||
id: versionTo
|
|
||||||
|
|
||||||
Layout.fillHeight: true
|
|
||||||
Layout.preferredWidth: 225
|
|
||||||
animate: true
|
|
||||||
color: DynamicColors.palette.m3primary
|
|
||||||
font.pointSize: Appearance.font.size.large
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
marqueeEnabled: true
|
|
||||||
pauseMs: 4000
|
|
||||||
text: update.sections[3]
|
|
||||||
width: 225
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IconButton {
|
|
||||||
Layout.preferredHeight: width
|
|
||||||
icon: "download"
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
Updates.performPackageUpdate(update.sections[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
model: ScriptModel {
|
|
||||||
id: script
|
|
||||||
|
|
||||||
objectProp: "update"
|
|
||||||
values: Object.entries(Updates.updates).sort((a, b) => b[1] - a[1]).map(([update, timestamp]) => ({
|
|
||||||
update,
|
|
||||||
timestamp
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -74,10 +74,6 @@ Item {
|
|||||||
stack.push(osd);
|
stack.push(osd);
|
||||||
else if (currentCategory === "launcher")
|
else if (currentCategory === "launcher")
|
||||||
stack.push(launcher);
|
stack.push(launcher);
|
||||||
else if (currentCategory === "screenshot")
|
|
||||||
stack.push(screenshot);
|
|
||||||
else if (currentCategory === "updates")
|
|
||||||
stack.push(updates);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
target: root
|
target: root
|
||||||
@@ -229,18 +225,4 @@ Item {
|
|||||||
Cat.Launcher {
|
Cat.Launcher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
|
||||||
id: screenshot
|
|
||||||
|
|
||||||
Cat.Screenshot {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: updates
|
|
||||||
|
|
||||||
Cat.SystemUpdates {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,11 +28,72 @@ Item {
|
|||||||
property int uidCounter: 0
|
property int uidCounter: 0
|
||||||
property var visualEntries: []
|
property var visualEntries: []
|
||||||
|
|
||||||
|
function beginVisualDrag(uid, modelData, item) {
|
||||||
|
const pos = item.mapToItem(root, 0, 0);
|
||||||
|
|
||||||
|
root.draggedUid = uid;
|
||||||
|
root.draggedModelData = modelData;
|
||||||
|
root.dragHeight = item.height;
|
||||||
|
root.dragStartX = pos.x;
|
||||||
|
root.dragStartY = pos.y;
|
||||||
|
root.dragX = pos.x;
|
||||||
|
root.dragY = pos.y;
|
||||||
|
root.dragActive = true;
|
||||||
|
root.dropAnimating = false;
|
||||||
|
root.pendingCommitEntries = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function commitVisualOrder(entries) {
|
||||||
|
const list = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < entries.length; i++)
|
||||||
|
list.push(entries[i].entry);
|
||||||
|
|
||||||
|
root.object[root.setting] = list;
|
||||||
|
Config.save();
|
||||||
|
root.rebuildVisualEntries();
|
||||||
|
}
|
||||||
|
|
||||||
|
function endVisualDrag() {
|
||||||
|
const entries = root.visualEntries.slice();
|
||||||
|
const finalIndex = root.indexForUid(root.draggedUid);
|
||||||
|
const finalItem = listView.itemAtIndex(finalIndex);
|
||||||
|
|
||||||
|
root.dragActive = false;
|
||||||
|
|
||||||
|
if (!finalItem) {
|
||||||
|
root.pendingCommitEntries = entries;
|
||||||
|
root.finishVisualDrag();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pos = finalItem.mapToItem(root, 0, 0);
|
||||||
|
|
||||||
|
root.pendingCommitEntries = entries;
|
||||||
|
root.dropAnimating = true;
|
||||||
|
settleX.to = pos.x;
|
||||||
|
settleY.to = pos.y;
|
||||||
|
settleAnim.start();
|
||||||
|
}
|
||||||
|
|
||||||
function ensureVisualEntries() {
|
function ensureVisualEntries() {
|
||||||
if (!root.dragActive && !root.dropAnimating)
|
if (!root.dragActive && !root.dropAnimating)
|
||||||
root.rebuildVisualEntries();
|
root.rebuildVisualEntries();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function finishVisualDrag() {
|
||||||
|
const entries = root.pendingCommitEntries.slice();
|
||||||
|
|
||||||
|
root.dragActive = false;
|
||||||
|
root.dropAnimating = false;
|
||||||
|
root.draggedUid = "";
|
||||||
|
root.draggedModelData = null;
|
||||||
|
root.pendingCommitEntries = [];
|
||||||
|
root.dragHeight = 0;
|
||||||
|
|
||||||
|
root.commitVisualOrder(entries);
|
||||||
|
}
|
||||||
|
|
||||||
function iconForId(id) {
|
function iconForId(id) {
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case "workspaces":
|
case "workspaces":
|
||||||
@@ -92,7 +153,7 @@ Item {
|
|||||||
case "spacer":
|
case "spacer":
|
||||||
return qsTr("Spacer");
|
return qsTr("Spacer");
|
||||||
case "activeWindow":
|
case "activeWindow":
|
||||||
return qsTr("Title");
|
return qsTr("Active window");
|
||||||
case "tray":
|
case "tray":
|
||||||
return qsTr("Tray");
|
return qsTr("Tray");
|
||||||
case "upower":
|
case "upower":
|
||||||
@@ -102,14 +163,34 @@ Item {
|
|||||||
case "clock":
|
case "clock":
|
||||||
return qsTr("Clock");
|
return qsTr("Clock");
|
||||||
case "notifBell":
|
case "notifBell":
|
||||||
return qsTr("Notifs");
|
return qsTr("Notification bell");
|
||||||
case "hyprsunset":
|
|
||||||
return qsTr("Night light");
|
|
||||||
default:
|
default:
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function moveArrayItem(list, from, to) {
|
||||||
|
const next = list.slice();
|
||||||
|
const [item] = next.splice(from, 1);
|
||||||
|
next.splice(to, 0, item);
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
function previewVisualMove(from, hovered, before) {
|
||||||
|
let to = hovered + (before ? 0 : 1);
|
||||||
|
|
||||||
|
if (to > from)
|
||||||
|
to -= 1;
|
||||||
|
|
||||||
|
to = Math.max(0, Math.min(visualModel.items.count - 1, to));
|
||||||
|
|
||||||
|
if (from === to)
|
||||||
|
return;
|
||||||
|
|
||||||
|
visualModel.items.move(from, to);
|
||||||
|
root.visualEntries = root.moveArrayItem(root.visualEntries, from, to);
|
||||||
|
}
|
||||||
|
|
||||||
function rebuildVisualEntries() {
|
function rebuildVisualEntries() {
|
||||||
const entries = root.object[root.setting] ?? [];
|
const entries = root.object[root.setting] ?? [];
|
||||||
const next = [];
|
const next = [];
|
||||||
@@ -144,6 +225,7 @@ Item {
|
|||||||
list[index] = entry;
|
list[index] = entry;
|
||||||
root.object[root.setting] = list;
|
root.object[root.setting] = list;
|
||||||
Config.save();
|
Config.save();
|
||||||
|
root.ensureVisualEntries();
|
||||||
}
|
}
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
@@ -151,7 +233,7 @@ Item {
|
|||||||
|
|
||||||
Component.onCompleted: root.rebuildVisualEntries()
|
Component.onCompleted: root.rebuildVisualEntries()
|
||||||
|
|
||||||
CustomRect {
|
Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: -Appearance.padding.smaller
|
anchors.margins: -Appearance.padding.smaller
|
||||||
color: DynamicColors.palette.m3primaryContainer
|
color: DynamicColors.palette.m3primaryContainer
|
||||||
@@ -166,12 +248,39 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
ParallelAnimation {
|
||||||
|
id: settleAnim
|
||||||
|
|
||||||
|
onFinished: root.finishVisualDrag()
|
||||||
|
|
||||||
|
Anim {
|
||||||
|
id: settleX
|
||||||
|
|
||||||
|
duration: Appearance.anim.durations.normal
|
||||||
|
property: "dragX"
|
||||||
|
target: root
|
||||||
|
}
|
||||||
|
|
||||||
|
Anim {
|
||||||
|
id: settleY
|
||||||
|
|
||||||
|
duration: Appearance.anim.durations.normal
|
||||||
|
property: "dragY"
|
||||||
|
target: root
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
id: layout
|
id: layout
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
spacing: Appearance.spacing.smaller
|
||||||
|
|
||||||
// spacing: Appearance.spacing.smaller
|
CustomText {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
font.pointSize: Appearance.font.size.larger
|
||||||
|
text: root.name
|
||||||
|
}
|
||||||
|
|
||||||
DelegateModel {
|
DelegateModel {
|
||||||
id: visualModel
|
id: visualModel
|
||||||
@@ -184,40 +293,248 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Repeater {
|
ListView {
|
||||||
delegate: entryDelegate
|
id: listView
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: contentHeight
|
||||||
|
boundsBehavior: Flickable.StopAtBounds
|
||||||
|
clip: false
|
||||||
|
implicitHeight: contentHeight
|
||||||
|
implicitWidth: width
|
||||||
|
interactive: !(root.dragActive || root.dropAnimating)
|
||||||
model: visualModel
|
model: visualModel
|
||||||
|
spacing: Appearance.spacing.small
|
||||||
|
|
||||||
|
add: Transition {
|
||||||
|
Anim {
|
||||||
|
properties: "opacity,scale"
|
||||||
|
to: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addDisplaced: Transition {
|
||||||
|
Anim {
|
||||||
|
duration: Appearance.anim.durations.normal
|
||||||
|
property: "y"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
displaced: Transition {
|
||||||
|
Anim {
|
||||||
|
duration: Appearance.anim.durations.normal
|
||||||
|
property: "y"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
move: Transition {
|
||||||
|
Anim {
|
||||||
|
duration: Appearance.anim.durations.normal
|
||||||
|
property: "y"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
removeDisplaced: Transition {
|
||||||
|
Anim {
|
||||||
|
duration: Appearance.anim.durations.normal
|
||||||
|
property: "y"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
active: root.dragActive || root.dropAnimating
|
||||||
|
asynchronous: false
|
||||||
|
|
||||||
|
sourceComponent: Item {
|
||||||
|
Drag.active: root.dragActive
|
||||||
|
Drag.hotSpot.x: width / 2
|
||||||
|
Drag.hotSpot.y: height / 2
|
||||||
|
height: proxyRect.implicitHeight
|
||||||
|
implicitHeight: proxyRect.implicitHeight
|
||||||
|
implicitWidth: listView.width
|
||||||
|
visible: root.draggedModelData !== null
|
||||||
|
width: listView.width
|
||||||
|
x: root.dragX
|
||||||
|
y: root.dragY
|
||||||
|
z: 100
|
||||||
|
|
||||||
|
Drag.source: QtObject {
|
||||||
|
property string uid: root.draggedUid
|
||||||
|
property int visualIndex: root.indexForUid(root.draggedUid)
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomRect {
|
||||||
|
id: proxyRect
|
||||||
|
|
||||||
|
color: DynamicColors.tPalette.m3surface
|
||||||
|
implicitHeight: proxyRow.implicitHeight + Appearance.padding.small * 2
|
||||||
|
implicitWidth: parent.width
|
||||||
|
opacity: 0.95
|
||||||
|
radius: Appearance.rounding.normal
|
||||||
|
width: parent.width
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: proxyRow
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Appearance.padding.small
|
||||||
|
spacing: Appearance.spacing.normal
|
||||||
|
|
||||||
|
CustomRect {
|
||||||
|
color: Qt.alpha(DynamicColors.palette.m3onSurface, 0.12)
|
||||||
|
implicitHeight: 32
|
||||||
|
implicitWidth: implicitHeight
|
||||||
|
radius: Appearance.rounding.small
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
color: DynamicColors.palette.m3onSurfaceVariant
|
||||||
|
text: "drag_indicator"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
color: DynamicColors.palette.m3onSurfaceVariant
|
||||||
|
text: root.iconForId(root.draggedModelData?.entry?.id ?? "")
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
font.pointSize: Appearance.font.size.larger
|
||||||
|
text: root.labelForId(root.draggedModelData?.entry?.id ?? "")
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomSwitch {
|
||||||
|
checked: root.draggedModelData?.entry?.enabled ?? true
|
||||||
|
enabled: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: entryDelegate
|
id: entryDelegate
|
||||||
|
|
||||||
IconButton {
|
DropArea {
|
||||||
required property int index
|
id: slot
|
||||||
|
|
||||||
|
readonly property var entryData: modelData.entry
|
||||||
required property var modelData
|
required property var modelData
|
||||||
|
readonly property string uid: modelData.uid
|
||||||
|
|
||||||
Layout.fillWidth: true
|
function previewReorder(drag) {
|
||||||
Layout.preferredWidth: implicitWidth + (stateLayer.pressed ? 18 : internalChecked ? 7 : 0)
|
const source = drag.source;
|
||||||
checked: modelData.entry.enabled ?? true
|
if (!source || !source.uid || source.uid === slot.uid)
|
||||||
font: Appearance.font.family.sans
|
return;
|
||||||
// icon: root.iconForId(modelData.entry.id)
|
|
||||||
icon: root.labelForId(modelData.entry.id)
|
|
||||||
inactiveColour: DynamicColors.layer(DynamicColors.palette.m3surfaceContainerHighest, 2)
|
|
||||||
radius: stateLayer.pressed ? 6 / 2 : internalChecked ? 6 : 8
|
|
||||||
radiusAnim.duration: MaterialEasing.expressiveEffectsTime
|
|
||||||
radiusAnim.easing.bezierCurve: MaterialEasing.expressiveEffects
|
|
||||||
toggle: true
|
|
||||||
visible: !["spacer", "upower", "dash", "audio"].some(prefix => modelData.entry.id.startsWith(prefix))
|
|
||||||
|
|
||||||
Behavior on Layout.preferredWidth {
|
const from = source.visualIndex;
|
||||||
Anim {
|
const hovered = slot.DelegateModel.itemsIndex;
|
||||||
duration: MaterialEasing.expressiveEffectsTime
|
|
||||||
easing.bezierCurve: MaterialEasing.expressiveEffects
|
if (from < 0 || hovered < 0)
|
||||||
}
|
return;
|
||||||
|
|
||||||
|
root.previewVisualMove(from, hovered, drag.y < height / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: root.updateEntry(index, internalChecked)
|
height: entryRow.implicitHeight
|
||||||
|
implicitHeight: entryRow.implicitHeight
|
||||||
|
implicitWidth: listView.width
|
||||||
|
width: ListView.view ? ListView.view.width : listView.width
|
||||||
|
|
||||||
|
onEntered: drag => previewReorder(drag)
|
||||||
|
onPositionChanged: drag => previewReorder(drag)
|
||||||
|
|
||||||
|
CustomRect {
|
||||||
|
id: entryRow
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
color: DynamicColors.tPalette.m3surface
|
||||||
|
implicitHeight: entryLayout.implicitHeight + Appearance.padding.small * 2
|
||||||
|
implicitWidth: parent.width
|
||||||
|
opacity: root.draggedUid === slot.uid ? 0 : 1
|
||||||
|
radius: Appearance.rounding.full
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
Anim {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: entryLayout
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Appearance.padding.small
|
||||||
|
spacing: Appearance.spacing.normal
|
||||||
|
|
||||||
|
CustomRect {
|
||||||
|
id: handle
|
||||||
|
|
||||||
|
color: Qt.alpha(DynamicColors.palette.m3onSurface, handleDrag.active ? 0.12 : handleHover.hovered ? 0.09 : 0.06)
|
||||||
|
implicitHeight: 32
|
||||||
|
implicitWidth: implicitHeight
|
||||||
|
radius: Appearance.rounding.full
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
CAnim {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
color: DynamicColors.palette.m3onSurfaceVariant
|
||||||
|
text: "drag_indicator"
|
||||||
|
}
|
||||||
|
|
||||||
|
HoverHandler {
|
||||||
|
id: handleHover
|
||||||
|
|
||||||
|
cursorShape: handleDrag.active ? Qt.ClosedHandCursor : Qt.OpenHandCursor
|
||||||
|
}
|
||||||
|
|
||||||
|
DragHandler {
|
||||||
|
id: handleDrag
|
||||||
|
|
||||||
|
enabled: true
|
||||||
|
grabPermissions: PointerHandler.CanTakeOverFromAnything
|
||||||
|
target: null
|
||||||
|
xAxis.enabled: false
|
||||||
|
yAxis.enabled: true
|
||||||
|
|
||||||
|
onActiveChanged: {
|
||||||
|
if (active) {
|
||||||
|
root.beginVisualDrag(slot.uid, slot.modelData, entryRow);
|
||||||
|
} else if (root.draggedUid === slot.uid) {
|
||||||
|
root.endVisualDrag();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onActiveTranslationChanged: {
|
||||||
|
if (!active || root.draggedUid !== slot.uid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
root.dragX = root.dragStartX;
|
||||||
|
root.dragY = root.dragStartY + activeTranslation.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
color: DynamicColors.palette.m3onSurfaceVariant
|
||||||
|
text: root.iconForId(slot.entryData.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
font.pointSize: Appearance.font.size.larger
|
||||||
|
text: root.labelForId(slot.entryData.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomSwitch {
|
||||||
|
Layout.rightMargin: Appearance.padding.small
|
||||||
|
checked: slot.entryData.enabled ?? true
|
||||||
|
|
||||||
|
onToggled: root.updateEntry(slot.DelegateModel.itemsIndex, checked)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ Item {
|
|||||||
required property var modelData
|
required property var modelData
|
||||||
|
|
||||||
signal addActiveActionRequested
|
signal addActiveActionRequested
|
||||||
signal deleteRequested(int index)
|
|
||||||
signal fieldEdited(string key, var value)
|
signal fieldEdited(string key, var value)
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
@@ -66,64 +65,42 @@ Item {
|
|||||||
|
|
||||||
HoverHandler {
|
HoverHandler {
|
||||||
id: nameHover
|
id: nameHover
|
||||||
}
|
|
||||||
|
|
||||||
HoverIconButton {
|
|
||||||
id: editButton
|
|
||||||
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
font.pointSize: Appearance.font.size.large
|
|
||||||
icon: "edit"
|
|
||||||
shouldBeVisible: nameHover.hovered && !nameCell.editing
|
|
||||||
|
|
||||||
onClicked: nameCell.beginEdit()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomText {
|
CustomText {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.leftMargin: nameHover.hovered ? editButton.width + Appearance.spacing.smaller * 2 : 0
|
anchors.right: editButton.left
|
||||||
anchors.right: deleteButton.left
|
|
||||||
anchors.rightMargin: Appearance.spacing.small
|
anchors.rightMargin: Appearance.spacing.small
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
elide: Text.ElideRight // enable if CustomText supports it
|
elide: Text.ElideRight // enable if CustomText supports it
|
||||||
font.pointSize: Appearance.font.size.larger
|
font.pointSize: Appearance.font.size.larger
|
||||||
text: root.modelData.name
|
text: root.modelData.name
|
||||||
visible: !nameCell.editing
|
visible: !nameCell.editing
|
||||||
|
|
||||||
Behavior on anchors.leftMargin {
|
|
||||||
Anim {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HoverIconButton {
|
IconButton {
|
||||||
id: deleteButton
|
id: editButton
|
||||||
|
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
font.pointSize: Appearance.font.size.large
|
font.pointSize: Appearance.font.size.large
|
||||||
icon: "delete"
|
icon: "edit"
|
||||||
shouldBeVisible: nameHover.hovered && !nameCell.editing
|
visible: nameHover.hovered && !nameCell.editing
|
||||||
|
|
||||||
onClicked: root.deleteRequested(root.index)
|
onClicked: nameCell.beginEdit()
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomRect {
|
CustomRect {
|
||||||
anchors.left: parent.left
|
anchors.fill: parent
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
color: DynamicColors.tPalette.m3surface
|
color: DynamicColors.tPalette.m3surface
|
||||||
implicitHeight: nameEditor.implicitHeight + (Appearance.padding.normal * 2)
|
|
||||||
implicitWidth: Math.min(nameEditor.contentWidth + (Appearance.padding.normal * 2), parent.width - Appearance.padding.normal)
|
|
||||||
radius: Appearance.rounding.small
|
radius: Appearance.rounding.small
|
||||||
visible: nameCell.editing
|
visible: nameCell.editing
|
||||||
|
|
||||||
CustomTextField {
|
CustomTextField {
|
||||||
id: nameEditor
|
id: nameEditor
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.fill: parent
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
implicitWidth: Math.min(contentWidth + Appearance.padding.normal * 2, nameCell.width - Appearance.padding.normal)
|
|
||||||
text: nameCell.draftName
|
text: nameCell.draftName
|
||||||
|
|
||||||
Keys.onEscapePressed: {
|
Keys.onEscapePressed: {
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ Item {
|
|||||||
Layout.preferredHeight: 42 * 6 + Appearance.padding.normal * 2 + Appearance.spacing.small * 5
|
Layout.preferredHeight: 42 * 6 + Appearance.padding.normal * 2 + Appearance.spacing.small * 5
|
||||||
Layout.preferredWidth: 500
|
Layout.preferredWidth: 500
|
||||||
color: DynamicColors.tPalette.m3surfaceContainer
|
color: DynamicColors.tPalette.m3surfaceContainer
|
||||||
radius: (21 + Appearance.padding.normal) * Appearance.rounding.scale
|
radius: 21 + Appearance.padding.normal
|
||||||
|
|
||||||
CustomRect {
|
CustomRect {
|
||||||
id: searchBox
|
id: searchBox
|
||||||
|
|||||||
@@ -6,109 +6,97 @@ import qs.Config
|
|||||||
import qs.Components
|
import qs.Components
|
||||||
import qs.Helpers
|
import qs.Helpers
|
||||||
|
|
||||||
Item {
|
ColumnLayout {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
Image {
|
spacing: 15
|
||||||
id: imageView
|
width: Math.min(parent ? parent.width : 600, 600)
|
||||||
|
|
||||||
property real displayH: paintedHeight
|
Rectangle {
|
||||||
property real displayW: paintedWidth
|
id: previewContainer
|
||||||
property real displayX: (width - paintedWidth) * 0.5
|
|
||||||
property real displayY: (height - paintedHeight) * 0.5
|
|
||||||
property real scaleX: sourceW / displayW
|
|
||||||
property real scaleY: sourceH / displayH
|
|
||||||
property real sourceH: Quickshell.screens[0].height
|
|
||||||
property real sourceW: Quickshell.screens[0].width
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
fillMode: Image.PreserveAspectFit
|
|
||||||
smooth: true
|
|
||||||
source: Wallpapers.current
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: overlay
|
|
||||||
|
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.preferredWidth: height * (Quickshell.screens.length > 0 ? (Quickshell.screens[0].height / Math.max(1, Quickshell.screens[0].width)) : 16 / 9)
|
||||||
clip: true
|
clip: true
|
||||||
height: imageView.displayH
|
color: DynamicColors.palette.m3surfaceContainer
|
||||||
width: imageView.displayW
|
radius: Config.appearance.rounding.scale * 10
|
||||||
x: imageView.displayX
|
|
||||||
y: imageView.displayY
|
|
||||||
|
|
||||||
CustomRect {
|
Image {
|
||||||
id: cropRect
|
id: img
|
||||||
|
|
||||||
property real aspectRatio: Quickshell.screens[0].width / Quickshell.screens[0].height
|
|
||||||
readonly property rect sourceRect: Qt.rect(x * imageView.scaleX, y * imageView.scaleY, width * imageView.scaleX, height * imageView.scaleY)
|
|
||||||
property real zoom: Config.background.zoom
|
|
||||||
|
|
||||||
function clampToBounds() {
|
|
||||||
x = Math.max(0, Math.min(x, overlay.width - width));
|
|
||||||
|
|
||||||
y = Math.max(0, Math.min(y, overlay.height - height));
|
|
||||||
}
|
|
||||||
|
|
||||||
border.color: DynamicColors.palette.m3primary
|
|
||||||
border.width: 2
|
|
||||||
color: DynamicColors.tPalette.m3primary
|
|
||||||
height: width / aspectRatio
|
|
||||||
radius: Appearance.rounding.small
|
|
||||||
visible: imageView.status === Image.Ready
|
|
||||||
width: Math.min(overlay.width / zoom, overlay.height * aspectRatio / zoom)
|
|
||||||
x: Config.background.sourceClipX / imageView.scaleX
|
|
||||||
y: Config.background.sourceClipY / imageView.scaleY
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
function updateCrop(mouseX, mouseY) {
|
|
||||||
let nx = mouseX - cropRect.width * 0.5;
|
|
||||||
let ny = mouseY - cropRect.height * 0.5;
|
|
||||||
|
|
||||||
nx = Math.max(0, Math.min(nx, overlay.width - cropRect.width));
|
|
||||||
|
|
||||||
ny = Math.max(0, Math.min(ny, overlay.height - cropRect.height));
|
|
||||||
|
|
||||||
cropRect.x = nx;
|
|
||||||
cropRect.y = ny;
|
|
||||||
}
|
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
asynchronous: true
|
||||||
preventStealing: true
|
fillMode: Image.PreserveAspectFit
|
||||||
|
source: Wallpapers.current
|
||||||
|
|
||||||
onPositionChanged: mouse => {
|
Rectangle {
|
||||||
if (pressed)
|
id: cropRect
|
||||||
updateCrop(mouse.x, mouse.y);
|
|
||||||
}
|
|
||||||
onPressed: mouse => {
|
|
||||||
updateCrop(mouse.x, mouse.y);
|
|
||||||
}
|
|
||||||
onReleased: {
|
|
||||||
Wallpapers.recentlyChanged = false;
|
|
||||||
Config.background.sourceClipX = cropRect.sourceRect.x;
|
|
||||||
Config.background.sourceClipY = cropRect.sourceRect.y;
|
|
||||||
Config.background.sourceClipW = cropRect.sourceRect.width;
|
|
||||||
Config.background.sourceClipH = cropRect.sourceRect.height;
|
|
||||||
Config.save();
|
|
||||||
}
|
|
||||||
onWheel: wheel => {
|
|
||||||
let oldCenterX = cropRect.x + cropRect.width * 0.5;
|
|
||||||
let oldCenterY = cropRect.y + cropRect.height * 0.5;
|
|
||||||
|
|
||||||
if (wheel.angleDelta.y > 0)
|
property real cropHeight: (imageAspect > screenAspect ? paintedHeight : paintedWidth / screenAspect) / Config.background.zoom
|
||||||
cropRect.zoom *= 1.1;
|
property real cropWidth: (imageAspect > screenAspect ? paintedHeight * screenAspect : paintedWidth) / Config.background.zoom
|
||||||
else
|
property real imageAspect: Math.max(1, paintedWidth) / Math.max(1, paintedHeight)
|
||||||
cropRect.zoom /= 1.1;
|
property real paintedHeight: img.paintedHeight > 0 ? img.paintedHeight : img.height
|
||||||
|
property real paintedWidth: img.paintedWidth > 0 ? img.paintedWidth : img.width
|
||||||
|
property real paintedX: (img.width - paintedWidth) / 2
|
||||||
|
property real paintedY: (img.height - paintedHeight) / 2
|
||||||
|
property real screenAspect: Quickshell.screens.length > 0 ? (Quickshell.screens[0].width / Math.max(1, Quickshell.screens[0].height)) : 16 / 9
|
||||||
|
|
||||||
cropRect.zoom = Math.max(1.0, Math.min(cropRect.zoom, 10.0));
|
border.color: DynamicColors.palette.m3primary
|
||||||
Config.background.zoom = cropRect.zoom;
|
border.width: 2
|
||||||
|
color: Qt.alpha(DynamicColors.palette.m3primaryContainer, 0.3)
|
||||||
|
height: cropHeight
|
||||||
|
width: cropWidth
|
||||||
|
x: paintedX + (paintedWidth - width) * Config.background.alignX
|
||||||
|
y: paintedY + (paintedHeight - height) * Config.background.alignY
|
||||||
|
|
||||||
cropRect.x = oldCenterX - cropRect.width * 0.5;
|
DragHandler {
|
||||||
cropRect.y = oldCenterY - cropRect.height * 0.5;
|
target: null
|
||||||
|
|
||||||
cropRect.clampToBounds();
|
onActiveTranslationChanged: {
|
||||||
|
if (active) {
|
||||||
|
let newX = cropRect.x - cropRect.paintedX + translation.x;
|
||||||
|
let newY = cropRect.y - cropRect.paintedY + translation.y;
|
||||||
|
|
||||||
|
let rangeX = cropRect.paintedWidth - cropRect.width;
|
||||||
|
let rangeY = cropRect.paintedHeight - cropRect.height;
|
||||||
|
|
||||||
|
if (rangeX > 0) {
|
||||||
|
let valX = newX / rangeX;
|
||||||
|
Config.background.alignX = Math.max(0.0, Math.min(1.0, valX));
|
||||||
|
Config.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rangeY > 0) {
|
||||||
|
let valY = newY / rangeY;
|
||||||
|
Config.background.alignY = Math.max(0.0, Math.min(1.0, valY));
|
||||||
|
Config.save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PinchHandler {
|
||||||
|
maximumScale: 5.0
|
||||||
|
minimumScale: 1.0
|
||||||
|
target: null
|
||||||
|
|
||||||
|
onActiveScaleChanged: {
|
||||||
|
if (active) {
|
||||||
|
let newZoom = Config.background.zoom * (1 / (1 + (activeScale - 1) * 0.1));
|
||||||
|
Config.background.zoom = Math.max(1.0, Math.min(newZoom, 5.0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SettingSpinBox {
|
||||||
|
max: 5.0
|
||||||
|
min: 1.0
|
||||||
|
name: "Zoom"
|
||||||
|
object: Config.background
|
||||||
|
setting: "zoom"
|
||||||
|
step: 0.1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@ import QtQuick.Controls
|
|||||||
import qs.Components
|
import qs.Components
|
||||||
import qs.Config
|
import qs.Config
|
||||||
import "../../scripts/fuzzysort.js" as Fuzzy
|
import "../../scripts/fuzzysort.js" as Fuzzy
|
||||||
import "../../scripts/SettingsIndex.mjs" as SettingsIndex
|
import "./SettingsIndex.mjs" as SettingsIndex
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
@@ -53,10 +53,11 @@ Item {
|
|||||||
|
|
||||||
Shortcut {
|
Shortcut {
|
||||||
sequence: "/"
|
sequence: "/"
|
||||||
|
|
||||||
onActivated: searchField.forceActiveFocus()
|
onActivated: searchField.forceActiveFocus()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: console.log(root.height)
|
||||||
|
|
||||||
ListModel {
|
ListModel {
|
||||||
id: resultsModel
|
id: resultsModel
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,24 +7,45 @@ import qs.Helpers
|
|||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property real offsetScale: shouldBeActive ? 0 : 1
|
|
||||||
required property var panels
|
required property var panels
|
||||||
required property ShellScreen screen
|
required property ShellScreen screen
|
||||||
readonly property bool shouldBeActive: visibilities.settings
|
|
||||||
required property PersistentProperties visibilities
|
required property PersistentProperties visibilities
|
||||||
|
|
||||||
anchors.topMargin: (-implicitHeight - 5) * offsetScale
|
implicitHeight: 0
|
||||||
implicitHeight: content.implicitHeight
|
|
||||||
implicitWidth: content.implicitWidth
|
implicitWidth: content.implicitWidth
|
||||||
opacity: 1 - offsetScale
|
visible: height > 0
|
||||||
visible: offsetScale < 1
|
|
||||||
|
|
||||||
Behavior on offsetScale {
|
states: State {
|
||||||
Anim {
|
name: "visible"
|
||||||
duration: Appearance.anim.durations.expressiveDefaultSpatial
|
when: root.visibilities.settings
|
||||||
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
|
|
||||||
|
PropertyChanges {
|
||||||
|
root.implicitHeight: content.implicitHeight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
transitions: [
|
||||||
|
Transition {
|
||||||
|
from: ""
|
||||||
|
to: "visible"
|
||||||
|
|
||||||
|
Anim {
|
||||||
|
duration: MaterialEasing.expressiveEffectsTime
|
||||||
|
easing.bezierCurve: MaterialEasing.expressiveEffects
|
||||||
|
property: "implicitHeight"
|
||||||
|
target: root
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Transition {
|
||||||
|
from: "visible"
|
||||||
|
to: ""
|
||||||
|
|
||||||
|
Anim {
|
||||||
|
easing.bezierCurve: MaterialEasing.expressiveEffects
|
||||||
|
property: "implicitHeight"
|
||||||
|
target: root
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
CustomClippingRect {
|
CustomClippingRect {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ Scope {
|
|||||||
description: "Toggle launcher"
|
description: "Toggle launcher"
|
||||||
name: "toggle-launcher"
|
name: "toggle-launcher"
|
||||||
|
|
||||||
onPressed: {
|
onPressed: root.launcherInterrupted = false
|
||||||
root.launcherInterrupted = false;
|
onReleased: {
|
||||||
if (!root.launcherInterrupted && !root.hasFullscreen) {
|
if (!root.launcherInterrupted && !root.hasFullscreen) {
|
||||||
const visibilities = Visibilities.getForActive();
|
const visibilities = Visibilities.getForActive();
|
||||||
visibilities.launcher = !visibilities.launcher;
|
visibilities.launcher = !visibilities.launcher;
|
||||||
|
|||||||
@@ -1,158 +0,0 @@
|
|||||||
pragma ComponentBehavior: Bound
|
|
||||||
|
|
||||||
import Quickshell
|
|
||||||
import Quickshell.Widgets
|
|
||||||
import QtQuick
|
|
||||||
import QtQuick.Controls
|
|
||||||
import QtQuick.Effects
|
|
||||||
import qs.Components
|
|
||||||
import qs.Modules
|
|
||||||
import qs.Config
|
|
||||||
|
|
||||||
Column {
|
|
||||||
id: menu
|
|
||||||
|
|
||||||
property int biggestWidth: 0
|
|
||||||
required property QsMenuHandle handle
|
|
||||||
required property int level
|
|
||||||
required property PopoutState popouts
|
|
||||||
required property ShellScreen screen
|
|
||||||
property bool shown: true
|
|
||||||
|
|
||||||
height: childrenRect.height
|
|
||||||
opacity: shown ? 1 : 0
|
|
||||||
padding: 0
|
|
||||||
scale: shown ? 1 : 0.8
|
|
||||||
spacing: 4
|
|
||||||
width: biggestWidth
|
|
||||||
|
|
||||||
Behavior on opacity {
|
|
||||||
Anim {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Behavior on scale {
|
|
||||||
Anim {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QsMenuOpener {
|
|
||||||
id: menuOpener
|
|
||||||
|
|
||||||
menu: menu.handle
|
|
||||||
}
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
model: menuOpener.children
|
|
||||||
|
|
||||||
CustomRect {
|
|
||||||
id: item
|
|
||||||
|
|
||||||
required property int index
|
|
||||||
required property QsMenuEntry modelData
|
|
||||||
|
|
||||||
color: modelData.isSeparator ? DynamicColors.palette.m3outlineVariant : "transparent"
|
|
||||||
implicitHeight: modelData.isSeparator ? 1 : children.implicitHeight
|
|
||||||
implicitWidth: menu.biggestWidth
|
|
||||||
radius: Appearance.rounding.full
|
|
||||||
visible: index !== (menuOpener.children.values.length - 1) ? true : (modelData.isSeparator ? false : true)
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
id: children
|
|
||||||
|
|
||||||
active: !item.modelData.isSeparator
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
asynchronous: true
|
|
||||||
|
|
||||||
sourceComponent: Item {
|
|
||||||
implicitHeight: 30
|
|
||||||
|
|
||||||
StateLayer {
|
|
||||||
function onClicked(): void {
|
|
||||||
const entry = item.modelData;
|
|
||||||
if (entry.hasChildren) {
|
|
||||||
menu.popouts.pushSubmenu(menu.level, entry, item, menu.biggestWidth);
|
|
||||||
} else {
|
|
||||||
entry.triggered();
|
|
||||||
menu.popouts.hasCurrent = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
disabled: !item.modelData.enabled
|
|
||||||
radius: item.radius
|
|
||||||
}
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
id: icon
|
|
||||||
|
|
||||||
active: item.modelData.icon !== ""
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: 10
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
asynchronous: true
|
|
||||||
|
|
||||||
sourceComponent: Item {
|
|
||||||
implicitHeight: label.implicitHeight
|
|
||||||
implicitWidth: label.implicitHeight
|
|
||||||
|
|
||||||
IconImage {
|
|
||||||
id: iconImage
|
|
||||||
|
|
||||||
implicitSize: parent.implicitHeight
|
|
||||||
source: item.modelData.icon
|
|
||||||
visible: false
|
|
||||||
}
|
|
||||||
|
|
||||||
MultiEffect {
|
|
||||||
anchors.fill: iconImage
|
|
||||||
colorization: 1.0
|
|
||||||
colorizationColor: item.modelData.enabled ? DynamicColors.palette.m3onSurface : DynamicColors.palette.m3outline
|
|
||||||
source: iconImage
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomText {
|
|
||||||
id: label
|
|
||||||
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: 10
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
color: item.modelData.enabled ? DynamicColors.palette.m3onSurface : DynamicColors.palette.m3outline
|
|
||||||
text: labelMetrics.elidedText
|
|
||||||
}
|
|
||||||
|
|
||||||
TextMetrics {
|
|
||||||
id: labelMetrics
|
|
||||||
|
|
||||||
font.family: label.font.family
|
|
||||||
font.pointSize: label.font.pointSize
|
|
||||||
text: item.modelData.text
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
var biggestWidth = menu.biggestWidth;
|
|
||||||
var currentWidth = labelMetrics.width + (item.modelData.icon ?? "" ? 30 : 0) + (item.modelData.hasChildren ? 30 : 0) + 20;
|
|
||||||
if (currentWidth > biggestWidth) {
|
|
||||||
menu.biggestWidth = currentWidth;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
id: expand
|
|
||||||
|
|
||||||
active: item.modelData.hasChildren
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
asynchronous: true
|
|
||||||
|
|
||||||
sourceComponent: MaterialIcon {
|
|
||||||
color: item.modelData.enabled ? DynamicColors.palette.m3onSurface : DynamicColors.palette.m3outline
|
|
||||||
text: "chevron_right"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +1,249 @@
|
|||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
|
import Quickshell.Widgets
|
||||||
import QtQuick
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Effects
|
||||||
import qs.Components
|
import qs.Components
|
||||||
import qs.Modules
|
import qs.Modules
|
||||||
import qs.Config
|
import qs.Config
|
||||||
|
|
||||||
SubMenu {
|
StackView {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
handle: trayItem
|
property int biggestWidth: 0
|
||||||
level: 0
|
required property PopoutState popouts
|
||||||
|
property int rootWidth: 0
|
||||||
required property QsMenuHandle trayItem
|
required property QsMenuHandle trayItem
|
||||||
}
|
|
||||||
|
implicitHeight: currentItem.implicitHeight
|
||||||
|
implicitWidth: currentItem.implicitWidth
|
||||||
|
|
||||||
|
initialItem: SubMenu {
|
||||||
|
handle: root.trayItem
|
||||||
|
}
|
||||||
|
popEnter: NoAnim {
|
||||||
|
}
|
||||||
|
popExit: NoAnim {
|
||||||
|
}
|
||||||
|
pushEnter: NoAnim {
|
||||||
|
}
|
||||||
|
pushExit: NoAnim {
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: subMenuComp
|
||||||
|
|
||||||
|
SubMenu {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component NoAnim: Transition {
|
||||||
|
NumberAnimation {
|
||||||
|
duration: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
component SubMenu: Column {
|
||||||
|
id: menu
|
||||||
|
|
||||||
|
required property QsMenuHandle handle
|
||||||
|
property bool isSubMenu
|
||||||
|
property bool shown
|
||||||
|
|
||||||
|
opacity: shown ? 1 : 0
|
||||||
|
padding: 0
|
||||||
|
scale: shown ? 1 : 0.8
|
||||||
|
spacing: 4
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
Anim {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Behavior on scale {
|
||||||
|
Anim {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: shown = true
|
||||||
|
StackView.onActivating: shown = true
|
||||||
|
StackView.onDeactivating: shown = false
|
||||||
|
StackView.onRemoved: destroy()
|
||||||
|
|
||||||
|
QsMenuOpener {
|
||||||
|
id: menuOpener
|
||||||
|
|
||||||
|
menu: menu.handle
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: menuOpener.children
|
||||||
|
|
||||||
|
CustomRect {
|
||||||
|
id: item
|
||||||
|
|
||||||
|
required property QsMenuEntry modelData
|
||||||
|
|
||||||
|
color: modelData.isSeparator ? DynamicColors.palette.m3outlineVariant : "transparent"
|
||||||
|
implicitHeight: modelData.isSeparator ? 1 : children.implicitHeight
|
||||||
|
implicitWidth: root.biggestWidth
|
||||||
|
radius: Appearance.rounding.smallest / 2
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: children
|
||||||
|
|
||||||
|
active: !item.modelData.isSeparator
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
asynchronous: true
|
||||||
|
|
||||||
|
sourceComponent: Item {
|
||||||
|
implicitHeight: 30
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
function onClicked(): void {
|
||||||
|
const entry = item.modelData;
|
||||||
|
if (entry.hasChildren) {
|
||||||
|
root.rootWidth = root.biggestWidth;
|
||||||
|
root.biggestWidth = 0;
|
||||||
|
root.push(subMenuComp.createObject(null, {
|
||||||
|
handle: entry,
|
||||||
|
isSubMenu: true
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
item.modelData.triggered();
|
||||||
|
root.popouts.hasCurrent = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
disabled: !item.modelData.enabled
|
||||||
|
radius: item.radius
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: icon
|
||||||
|
|
||||||
|
active: item.modelData.icon !== ""
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: 10
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
asynchronous: true
|
||||||
|
|
||||||
|
sourceComponent: Item {
|
||||||
|
implicitHeight: label.implicitHeight
|
||||||
|
implicitWidth: label.implicitHeight
|
||||||
|
|
||||||
|
IconImage {
|
||||||
|
id: iconImage
|
||||||
|
|
||||||
|
implicitSize: parent.implicitHeight
|
||||||
|
source: item.modelData.icon
|
||||||
|
visible: false
|
||||||
|
}
|
||||||
|
|
||||||
|
MultiEffect {
|
||||||
|
anchors.fill: iconImage
|
||||||
|
colorization: 1.0
|
||||||
|
colorizationColor: item.modelData.enabled ? DynamicColors.palette.m3onSurface : DynamicColors.palette.m3outline
|
||||||
|
source: iconImage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
id: label
|
||||||
|
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: 10
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
color: item.modelData.enabled ? DynamicColors.palette.m3onSurface : DynamicColors.palette.m3outline
|
||||||
|
text: labelMetrics.elidedText
|
||||||
|
}
|
||||||
|
|
||||||
|
TextMetrics {
|
||||||
|
id: labelMetrics
|
||||||
|
|
||||||
|
font.family: label.font.family
|
||||||
|
font.pointSize: label.font.pointSize
|
||||||
|
text: item.modelData.text
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
var biggestWidth = root.biggestWidth;
|
||||||
|
var currentWidth = labelMetrics.width + (item.modelData.icon ?? "" ? 30 : 0) + (item.modelData.hasChildren ? 30 : 0) + 20;
|
||||||
|
if (currentWidth > biggestWidth) {
|
||||||
|
root.biggestWidth = currentWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: expand
|
||||||
|
|
||||||
|
active: item.modelData.hasChildren
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
asynchronous: true
|
||||||
|
|
||||||
|
sourceComponent: MaterialIcon {
|
||||||
|
color: item.modelData.enabled ? DynamicColors.palette.m3onSurface : DynamicColors.palette.m3outline
|
||||||
|
text: "chevron_right"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: loader
|
||||||
|
|
||||||
|
active: menu.isSubMenu
|
||||||
|
asynchronous: true
|
||||||
|
|
||||||
|
sourceComponent: Item {
|
||||||
|
implicitHeight: back.implicitHeight + 2 / 2
|
||||||
|
implicitWidth: back.implicitWidth
|
||||||
|
|
||||||
|
Item {
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
implicitHeight: back.implicitHeight
|
||||||
|
implicitWidth: back.implicitWidth + 10
|
||||||
|
|
||||||
|
CustomRect {
|
||||||
|
anchors.fill: parent
|
||||||
|
color: DynamicColors.palette.m3secondaryContainer
|
||||||
|
radius: Appearance.rounding.smallest / 2
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
function onClicked(): void {
|
||||||
|
root.pop();
|
||||||
|
root.biggestWidth = root.rootWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
color: DynamicColors.palette.m3onSecondaryContainer
|
||||||
|
radius: parent.radius
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
id: back
|
||||||
|
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
color: DynamicColors.palette.m3onSecondaryContainer
|
||||||
|
text: "chevron_left"
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
color: DynamicColors.palette.m3onSecondaryContainer
|
||||||
|
text: qsTr("Back")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ Item {
|
|||||||
implicitHeight: Math.max(saver.implicitHeight, balance.implicitHeight, perf.implicitHeight) + 5 * 2 + saverLabel.contentHeight
|
implicitHeight: Math.max(saver.implicitHeight, balance.implicitHeight, perf.implicitHeight) + 5 * 2 + saverLabel.contentHeight
|
||||||
implicitWidth: saver.implicitHeight + balance.implicitHeight + perf.implicitHeight + 8 * 2 + saverLabel.contentWidth
|
implicitWidth: saver.implicitHeight + balance.implicitHeight + perf.implicitHeight + 8 * 2 + saverLabel.contentWidth
|
||||||
// color: "transparent"
|
// color: "transparent"
|
||||||
radius: (20 - Appearance.padding.small) * Appearance.rounding.scale
|
radius: 6
|
||||||
|
|
||||||
CustomRect {
|
CustomRect {
|
||||||
id: indicator
|
id: indicator
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
pragma Singleton
|
||||||
|
|
||||||
|
import Quickshell
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
Singleton {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
readonly property date date: clock.date
|
||||||
|
readonly property string dateStr: format("ddd d MMM - hh:mm:ss")
|
||||||
|
property alias enabled: clock.enabled
|
||||||
|
readonly property string hourStr: timeComponents[0] ?? ""
|
||||||
|
readonly property int hours: clock.hours
|
||||||
|
readonly property string minuteStr: timeComponents[1] ?? ""
|
||||||
|
readonly property int minutes: clock.minutes
|
||||||
|
readonly property string secondStr: timeComponents[2] ?? ""
|
||||||
|
readonly property int seconds: clock.seconds
|
||||||
|
readonly property list<string> timeComponents: timeStr.split(":")
|
||||||
|
readonly property string timeStr: format("hh:mm:ss")
|
||||||
|
|
||||||
|
function format(fmt: string): string {
|
||||||
|
return Qt.formatDateTime(clock.date, fmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemClock {
|
||||||
|
id: clock
|
||||||
|
|
||||||
|
precision: SystemClock.Seconds
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -54,8 +54,6 @@ CustomClippingRect {
|
|||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
contentHeight: childrenRect.height
|
contentHeight: childrenRect.height
|
||||||
contentWidth: 600
|
contentWidth: 600
|
||||||
displayMarginBeginning: root.itemHeight
|
|
||||||
displayMarginEnd: root.itemHeight
|
|
||||||
implicitHeight: Math.min(contentHeight, (root.itemHeight + spacing) * 5 - spacing)
|
implicitHeight: Math.min(contentHeight, (root.itemHeight + spacing) * 5 - spacing)
|
||||||
implicitWidth: contentWidth
|
implicitWidth: contentWidth
|
||||||
spacing: Appearance.spacing.normal
|
spacing: Appearance.spacing.normal
|
||||||
@@ -67,11 +65,10 @@ CustomClippingRect {
|
|||||||
required property var modelData
|
required property var modelData
|
||||||
readonly property list<string> sections: modelData.update.split(" ")
|
readonly property list<string> sections: modelData.update.split(" ")
|
||||||
|
|
||||||
// anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
// anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
color: DynamicColors.tPalette.m3surfaceContainer
|
color: DynamicColors.tPalette.m3surfaceContainer
|
||||||
implicitHeight: root.itemHeight
|
implicitHeight: root.itemHeight
|
||||||
implicitWidth: 600
|
|
||||||
radius: Appearance.rounding.small - Appearance.padding.small
|
radius: Appearance.rounding.small - Appearance.padding.small
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ CustomRect {
|
|||||||
color: DynamicColors.tPalette.m3surfaceContainer
|
color: DynamicColors.tPalette.m3surfaceContainer
|
||||||
implicitHeight: Config.barConfig.height + Appearance.padding.smallest * 2
|
implicitHeight: Config.barConfig.height + Appearance.padding.smallest * 2
|
||||||
implicitWidth: contentRow.implicitWidth + Appearance.spacing.small * 2
|
implicitWidth: contentRow.implicitWidth + Appearance.spacing.small * 2
|
||||||
radius: Appearance.rounding.full
|
radius: height / 2
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
id: contentRow
|
id: contentRow
|
||||||
|
|||||||
@@ -1,80 +0,0 @@
|
|||||||
pragma ComponentBehavior: Bound
|
|
||||||
|
|
||||||
import QtQuick
|
|
||||||
import qs.Components
|
|
||||||
import qs.Helpers
|
|
||||||
import qs.Config
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property Image current: one
|
|
||||||
property string source: Wallpapers.current
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
if (source)
|
|
||||||
Qt.callLater(() => one.update());
|
|
||||||
}
|
|
||||||
onSourceChanged: {
|
|
||||||
if (!source) {
|
|
||||||
current = null;
|
|
||||||
} else if (current === one) {
|
|
||||||
two.update();
|
|
||||||
} else {
|
|
||||||
one.update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Img {
|
|
||||||
id: one
|
|
||||||
}
|
|
||||||
|
|
||||||
Img {
|
|
||||||
id: two
|
|
||||||
}
|
|
||||||
|
|
||||||
component Img: Image {
|
|
||||||
id: img
|
|
||||||
|
|
||||||
function update(): void {
|
|
||||||
if (source === root.source) {
|
|
||||||
root.current = this;
|
|
||||||
} else {
|
|
||||||
source = root.source;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
asynchronous: true
|
|
||||||
fillMode: Image.PreserveAspectCrop
|
|
||||||
opacity: 0
|
|
||||||
retainWhileLoading: true
|
|
||||||
scale: Wallpapers.showPreview ? 1 : 0.8
|
|
||||||
sourceClipRect: Qt.rect(Config.background.sourceClipX, Config.background.sourceClipY, Config.background.sourceClipW, Config.background.sourceClipH)
|
|
||||||
|
|
||||||
states: State {
|
|
||||||
name: "visible"
|
|
||||||
when: root.current === img
|
|
||||||
|
|
||||||
PropertyChanges {
|
|
||||||
img.opacity: 1
|
|
||||||
img.scale: 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
transitions: Transition {
|
|
||||||
Anim {
|
|
||||||
duration: Config.background.wallFadeDuration
|
|
||||||
properties: "opacity,scale"
|
|
||||||
target: img
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onStatusChanged: {
|
|
||||||
if (status === Image.Ready) {
|
|
||||||
root.current = this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import Quickshell
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import qs.Components
|
import qs.Components
|
||||||
import qs.Helpers
|
import qs.Helpers
|
||||||
@@ -9,34 +8,79 @@ import qs.Config
|
|||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
required property ShellScreen screen
|
property Image current: one
|
||||||
property string source: Wallpapers.current
|
property string source: Wallpapers.current
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
Image {
|
Component.onCompleted: {
|
||||||
|
if (source)
|
||||||
|
Qt.callLater(() => one.update());
|
||||||
|
}
|
||||||
|
onSourceChanged: {
|
||||||
|
if (!source) {
|
||||||
|
current = null;
|
||||||
|
} else if (current === one) {
|
||||||
|
two.update();
|
||||||
|
} else {
|
||||||
|
one.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Img {
|
||||||
|
id: one
|
||||||
|
}
|
||||||
|
|
||||||
|
Img {
|
||||||
|
id: two
|
||||||
|
}
|
||||||
|
|
||||||
|
component Img: CachingImage {
|
||||||
id: img
|
id: img
|
||||||
|
|
||||||
anchors.fill: parent
|
property real imageRatio: Math.max(1, sourceSize.width) / Math.max(1, sourceSize.height)
|
||||||
|
property bool isValid: sourceSize.width > 0 && sourceSize.height > 0 && root.width > 0 && root.height > 0
|
||||||
|
property real windowRatio: root.width / Math.max(1, root.height)
|
||||||
|
|
||||||
|
function update(): void {
|
||||||
|
if (path === root.source) {
|
||||||
|
root.current = this;
|
||||||
|
} else {
|
||||||
|
path = root.source;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
anchors.fill: undefined
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
fillMode: Image.PreserveAspectCrop
|
fillMode: Image.PreserveAspectCrop
|
||||||
opacity: 1
|
height: isValid ? (imageRatio > windowRatio ? root.height : root.width / imageRatio) * Config.background.zoom : root.height
|
||||||
retainWhileLoading: true
|
opacity: 0
|
||||||
source: root.source
|
scale: Wallpapers.showPreview ? 1 : 0.8
|
||||||
sourceClipRect: Wallpapers.recentlyChanged ? null : Qt.rect(Config.background.sourceClipX, Config.background.sourceClipY, Config.background.sourceClipW, Config.background.sourceClipH)
|
width: isValid ? (imageRatio > windowRatio ? root.height * imageRatio : root.width) * Config.background.zoom : root.width
|
||||||
sourceSize.height: root.screen.height
|
x: isValid ? (root.width - width) * Config.background.alignX : 0
|
||||||
sourceSize.width: root.screen.width
|
y: isValid ? (root.height - height) * Config.background.alignY : 0
|
||||||
|
|
||||||
onSourceChanged: {
|
states: State {
|
||||||
if (Wallpapers.recentlyChanged) {
|
name: "visible"
|
||||||
Config.background.sourceClipH = 0;
|
when: root.current === img
|
||||||
Config.background.sourceClipW = 0;
|
|
||||||
Config.background.sourceClipY = 0;
|
PropertyChanges {
|
||||||
Config.background.sourceClipX = 0;
|
img.opacity: 1
|
||||||
Config.background.zoom = 1.0;
|
img.scale: 1
|
||||||
Config.save();
|
}
|
||||||
|
}
|
||||||
|
transitions: Transition {
|
||||||
|
Anim {
|
||||||
|
duration: Config.background.wallFadeDuration
|
||||||
|
properties: "opacity,scale"
|
||||||
|
target: img
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onStatusChanged: {
|
||||||
|
if (status === Image.Ready) {
|
||||||
|
root.current = this;
|
||||||
}
|
}
|
||||||
Wallpapers.recentlyChanged = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ Loader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
WallBackground {
|
WallBackground {
|
||||||
screen: root.screen
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
|
|||||||
@@ -79,8 +79,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onPressed: {
|
onPressed: {
|
||||||
const ws = button.modelData.name;
|
Hyprland.dispatch(`workspace ${button.modelData.name}`);
|
||||||
Hyprland.dispatch(Hyprland.usingLua ? `hl.dsp.focus({ workspace= "${ws}"})` : `workspace ${ws}`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-3
@@ -15,14 +15,13 @@ Item {
|
|||||||
property real currentCenter
|
property real currentCenter
|
||||||
property alias currentName: popoutState.currentName
|
property alias currentName: popoutState.currentName
|
||||||
property string detachedMode
|
property string detachedMode
|
||||||
property alias hasCurrent: popoutState.hasCurrent
|
|
||||||
readonly property bool isDetached: detachedMode.length > 0
|
readonly property bool isDetached: detachedMode.length > 0
|
||||||
|
property alias hasCurrent: popoutState.hasCurrent
|
||||||
readonly property real nonAnimHeight: children.find(c => c.shouldBeActive)?.implicitHeight ?? content.implicitHeight
|
readonly property real nonAnimHeight: children.find(c => c.shouldBeActive)?.implicitHeight ?? content.implicitHeight
|
||||||
readonly property real nonAnimWidth: children.find(c => c.shouldBeActive)?.implicitWidth ?? content.implicitWidth
|
readonly property real nonAnimWidth: children.find(c => c.shouldBeActive)?.implicitWidth ?? content.implicitWidth
|
||||||
required property real offsetScale
|
required property real offsetScale
|
||||||
property string queuedMode
|
property string queuedMode
|
||||||
required property ShellScreen screen
|
required property ShellScreen screen
|
||||||
property alias state: popoutState
|
|
||||||
|
|
||||||
function close(): void {
|
function close(): void {
|
||||||
hasCurrent = false;
|
hasCurrent = false;
|
||||||
@@ -80,7 +79,6 @@ Item {
|
|||||||
|
|
||||||
sourceComponent: Content {
|
sourceComponent: Content {
|
||||||
popouts: popoutState
|
popouts: popoutState
|
||||||
screen: root.screen
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ qml_module(ZShell-blobs
|
|||||||
|
|
||||||
qt_add_shaders(ZShell-blobs "blob_shaders"
|
qt_add_shaders(ZShell-blobs "blob_shaders"
|
||||||
BATCHABLE OPTIMIZED NOHLSL NOMSL
|
BATCHABLE OPTIMIZED NOHLSL NOMSL
|
||||||
GLSL "300es,330"
|
|
||||||
PREFIX "/"
|
PREFIX "/"
|
||||||
FILES
|
FILES
|
||||||
shaders/blob.frag
|
shaders/blob.frag
|
||||||
|
|||||||
@@ -2,9 +2,6 @@
|
|||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
static_assert(sizeof(decltype(BlobRectData::excludeMask)) == sizeof(float),
|
|
||||||
"BlobMaterial packs excludeMask into a float slot via memcpy");
|
|
||||||
|
|
||||||
QSGMaterialType* BlobMaterial::type() const {
|
QSGMaterialType* BlobMaterial::type() const {
|
||||||
static QSGMaterialType s_type;
|
static QSGMaterialType s_type;
|
||||||
return &s_type;
|
return &s_type;
|
||||||
@@ -85,11 +82,8 @@ bool BlobMaterialShader::updateUniformData(RenderState& state, QSGMaterial* newM
|
|||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
const auto& r = mat->m_rects[i];
|
const auto& r = mat->m_rects[i];
|
||||||
const int base = 160 + i * 80;
|
const int base = 160 + i * 80;
|
||||||
// Pack excludeMask into props.x via bit-cast (read in shader with floatBitsToInt)
|
|
||||||
float maskAsFloat;
|
|
||||||
memcpy(&maskAsFloat, &r.excludeMask, sizeof(float));
|
|
||||||
const float d0[4] = { r.cx, r.cy, r.hw, r.hh };
|
const float d0[4] = { r.cx, r.cy, r.hw, r.hh };
|
||||||
const float d1[4] = { maskAsFloat, r.offsetX, r.offsetY, r.minEig };
|
const float d1[4] = { 0.0f, r.offsetX, r.offsetY, r.minEig };
|
||||||
const float d3[4] = { r.screenHalfX, r.screenHalfY, 0.0f, 0.0f };
|
const float d3[4] = { r.screenHalfX, r.screenHalfY, 0.0f, 0.0f };
|
||||||
memcpy(buf->data() + base, d0, 16);
|
memcpy(buf->data() + base, d0, 16);
|
||||||
memcpy(buf->data() + base + 16, d1, 16);
|
memcpy(buf->data() + base + 16, d1, 16);
|
||||||
|
|||||||
@@ -14,9 +14,6 @@ struct BlobRectData {
|
|||||||
float screenHalfX = 0, screenHalfY = 0;
|
float screenHalfX = 0, screenHalfY = 0;
|
||||||
// Effective per-corner radii (tr, br, bl, tl), pre-computed on CPU
|
// Effective per-corner radii (tr, br, bl, tl), pre-computed on CPU
|
||||||
float radius[4] = { 0, 0, 0, 0 };
|
float radius[4] = { 0, 0, 0, 0 };
|
||||||
// Bitmask of indices in this rect's m_cachedRects that mutually exclude (or are excluded by) this rect.
|
|
||||||
// Used by the shader to skip smin between excluded pairs.
|
|
||||||
int excludeMask = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class BlobMaterial : public QSGMaterial {
|
class BlobMaterial : public QSGMaterial {
|
||||||
|
|||||||
@@ -72,17 +72,11 @@ void BlobShape::geometryChange(const QRectF& newGeometry, const QRectF& oldGeome
|
|||||||
// Accumulate sub-pixel drift so slow movements don't desync the shader
|
// Accumulate sub-pixel drift so slow movements don't desync the shader
|
||||||
m_pendingDx += static_cast<float>(newGeometry.x() - oldGeometry.x());
|
m_pendingDx += static_cast<float>(newGeometry.x() - oldGeometry.x());
|
||||||
m_pendingDy += static_cast<float>(newGeometry.y() - oldGeometry.y());
|
m_pendingDy += static_cast<float>(newGeometry.y() - oldGeometry.y());
|
||||||
// Accumulate size delta across multiple frames so incremental size
|
const auto dw = std::abs(newGeometry.width() - oldGeometry.width());
|
||||||
// changes that are each below the threshold still trigger a dirty
|
const auto dh = std::abs(newGeometry.height() - oldGeometry.height());
|
||||||
// mark once their accumulated delta exceeds it.
|
if (std::abs(m_pendingDx) > 0.5f || std::abs(m_pendingDy) > 0.5f || dw > 0.5 || dh > 0.5) {
|
||||||
m_pendingDw += static_cast<float>(newGeometry.width() - oldGeometry.width());
|
|
||||||
m_pendingDh += static_cast<float>(newGeometry.height() - oldGeometry.height());
|
|
||||||
if (std::abs(m_pendingDx) > 0.5f || std::abs(m_pendingDy) > 0.5f ||
|
|
||||||
std::abs(m_pendingDw) > 0.5f || std::abs(m_pendingDh) > 0.5f) {
|
|
||||||
m_pendingDx = 0;
|
m_pendingDx = 0;
|
||||||
m_pendingDy = 0;
|
m_pendingDy = 0;
|
||||||
m_pendingDw = 0;
|
|
||||||
m_pendingDh = 0;
|
|
||||||
m_group->markShapeDirty(this);
|
m_group->markShapeDirty(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,10 +149,6 @@ void BlobShape::updatePolish() {
|
|||||||
const QRectF myPadded(static_cast<double>(m_cachedPaddedX), static_cast<double>(m_cachedPaddedY),
|
const QRectF myPadded(static_cast<double>(m_cachedPaddedX), static_cast<double>(m_cachedPaddedY),
|
||||||
static_cast<double>(m_cachedPaddedW), static_cast<double>(m_cachedPaddedH));
|
static_cast<double>(m_cachedPaddedW), static_cast<double>(m_cachedPaddedH));
|
||||||
|
|
||||||
// Track shape pointers parallel to m_cachedRects for pairwise exclusion lookups
|
|
||||||
QVector<BlobShape*> rectShapes;
|
|
||||||
rectShapes.reserve(m_group->shapes().size());
|
|
||||||
|
|
||||||
for (BlobShape* other : m_group->shapes()) {
|
for (BlobShape* other : m_group->shapes()) {
|
||||||
if (other->isInvertedRect())
|
if (other->isInvertedRect())
|
||||||
continue;
|
continue;
|
||||||
@@ -220,29 +210,12 @@ void BlobShape::updatePolish() {
|
|||||||
r.screenHalfY = std::abs(b) * r.hw + std::abs(d) * r.hh;
|
r.screenHalfY = std::abs(b) * r.hw + std::abs(d) * r.hh;
|
||||||
|
|
||||||
m_cachedRects.append(r);
|
m_cachedRects.append(r);
|
||||||
rectShapes.append(other);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isInvertedRect())
|
if (isInvertedRect())
|
||||||
m_cachedMyIndex = -1;
|
m_cachedMyIndex = -1;
|
||||||
|
|
||||||
// Compute pairwise exclude masks. Bit j in entry i is set iff rect i excludes rect j
|
|
||||||
// or rect j excludes rect i. The shader uses this to avoid smin between excluded pairs.
|
|
||||||
const auto cachedCount = m_cachedRects.size();
|
|
||||||
for (qsizetype i = 0; i < cachedCount; ++i) {
|
|
||||||
int mask = 0;
|
|
||||||
BlobShape* si = rectShapes[i];
|
|
||||||
for (qsizetype j = 0; j < cachedCount; ++j) {
|
|
||||||
if (j == i)
|
|
||||||
continue;
|
|
||||||
BlobShape* sj = rectShapes[j];
|
|
||||||
if (si->isExcluded(sj) || sj->isExcluded(si))
|
|
||||||
mask |= (1 << j);
|
|
||||||
}
|
|
||||||
m_cachedRects[i].excludeMask = mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cache inverted rect data
|
// Cache inverted rect data
|
||||||
m_cachedHasInverted = false;
|
m_cachedHasInverted = false;
|
||||||
m_cachedInvertedRadius = 0;
|
m_cachedInvertedRadius = 0;
|
||||||
@@ -297,7 +270,6 @@ void BlobShape::updatePolish() {
|
|||||||
const auto rectCount = m_cachedRects.size();
|
const auto rectCount = m_cachedRects.size();
|
||||||
for (qsizetype i = 0; i < rectCount; ++i) {
|
for (qsizetype i = 0; i < rectCount; ++i) {
|
||||||
auto& ri = m_cachedRects[i];
|
auto& ri = m_cachedRects[i];
|
||||||
const int riExcludeMask = ri.excludeMask;
|
|
||||||
float fTr = 1.0f, fBr = 1.0f, fBl = 1.0f, fTl = 1.0f;
|
float fTr = 1.0f, fBr = 1.0f, fBl = 1.0f, fTl = 1.0f;
|
||||||
|
|
||||||
const float cTrX = ri.cx + ri.hw, cTrY = ri.cy - ri.hh;
|
const float cTrX = ri.cx + ri.hw, cTrY = ri.cy - ri.hh;
|
||||||
@@ -308,8 +280,6 @@ void BlobShape::updatePolish() {
|
|||||||
for (qsizetype j = 0; j < rectCount; ++j) {
|
for (qsizetype j = 0; j < rectCount; ++j) {
|
||||||
if (j == i)
|
if (j == i)
|
||||||
continue;
|
continue;
|
||||||
if (riExcludeMask & (1 << j))
|
|
||||||
continue;
|
|
||||||
const auto& rj = m_cachedRects[j];
|
const auto& rj = m_cachedRects[j];
|
||||||
fTr = std::min(fTr, cpuSmoothstep(0.0f, smoothFactor, cpuSdBox(cTrX, cTrY, rj.cx, rj.cy, rj.hw, rj.hh)));
|
fTr = std::min(fTr, cpuSmoothstep(0.0f, smoothFactor, cpuSdBox(cTrX, cTrY, rj.cx, rj.cy, rj.hw, rj.hh)));
|
||||||
fBr = std::min(fBr, cpuSmoothstep(0.0f, smoothFactor, cpuSdBox(cBrX, cBrY, rj.cx, rj.cy, rj.hw, rj.hh)));
|
fBr = std::min(fBr, cpuSmoothstep(0.0f, smoothFactor, cpuSdBox(cBrX, cBrY, rj.cx, rj.cy, rj.hw, rj.hh)));
|
||||||
|
|||||||
@@ -84,10 +84,8 @@ QRectF m_localPaddedRect;
|
|||||||
QVector<BlobRectData> m_cachedRects;
|
QVector<BlobRectData> m_cachedRects;
|
||||||
int m_cachedMyIndex = -2;
|
int m_cachedMyIndex = -2;
|
||||||
float m_pendingDx = 0;
|
float m_pendingDx = 0;
|
||||||
float m_pendingDy = 0;
|
float m_pendingDy = 0;
|
||||||
float m_pendingDw = 0;
|
bool m_cachedHasInverted = false;
|
||||||
float m_pendingDh = 0;
|
|
||||||
bool m_cachedHasInverted = false;
|
|
||||||
float m_cachedInvertedRadius = 0;
|
float m_cachedInvertedRadius = 0;
|
||||||
float m_cachedInvertedOuter[4] = {};
|
float m_cachedInvertedOuter[4] = {};
|
||||||
float m_cachedInvertedInner[4] = {};
|
float m_cachedInvertedInner[4] = {};
|
||||||
|
|||||||
@@ -63,17 +63,13 @@ float smaxSharpA(float a, float b, float k) {
|
|||||||
void main() {
|
void main() {
|
||||||
vec2 pixel = vec2(paddedX, paddedY) + qt_TexCoord0 * vec2(paddedW, paddedH);
|
vec2 pixel = vec2(paddedX, paddedY) + qt_TexCoord0 * vec2(paddedW, paddedH);
|
||||||
|
|
||||||
// Phase 1: compute per-rect SDF, track owner. We can't smin yet because
|
float mergedSdf = 1e10;
|
||||||
// excluded pairs need to skip the smooth blend, which requires pairwise pass
|
|
||||||
// below.
|
|
||||||
float dArr[16];
|
|
||||||
int owner = -2;
|
int owner = -2;
|
||||||
float minDist = 1e10;
|
float minDist = 1e10;
|
||||||
|
|
||||||
for (int i = 0; i < rectCount; i++) {
|
for (int i = 0; i < rectCount; i++) {
|
||||||
vec4 rect = rectData[i * 5]; // cx, cy, hw, hh
|
vec4 rect = rectData[i * 5]; // cx, cy, hw, hh
|
||||||
vec4 props =
|
vec4 props = rectData[i * 5 + 1]; // radius, offsetX, offsetY, minEig
|
||||||
rectData[i * 5 + 1]; // excludeMask(int bits), offsetX, offsetY, minEig
|
|
||||||
vec4 invDm = rectData[i * 5 + 2]; // inverse deform matrix
|
vec4 invDm = rectData[i * 5 + 2]; // inverse deform matrix
|
||||||
vec4 sh = rectData[i * 5 + 3]; // screenHalfX, screenHalfY, 0, 0
|
vec4 sh = rectData[i * 5 + 3]; // screenHalfX, screenHalfY, 0, 0
|
||||||
vec4 radii =
|
vec4 radii =
|
||||||
@@ -85,10 +81,8 @@ void main() {
|
|||||||
// AABB early-out: skip rects far from this pixel
|
// AABB early-out: skip rects far from this pixel
|
||||||
vec2 extent = sh.xy + vec2(smoothFactor * 1.5);
|
vec2 extent = sh.xy + vec2(smoothFactor * 1.5);
|
||||||
if (abs(pixel.x - center.x) > extent.x ||
|
if (abs(pixel.x - center.x) > extent.x ||
|
||||||
abs(pixel.y - center.y) > extent.y) {
|
abs(pixel.y - center.y) > extent.y)
|
||||||
dArr[i] = 1e10;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
// Apply pre-computed inverse deformation to the evaluation point
|
// Apply pre-computed inverse deformation to the evaluation point
|
||||||
mat2 invDeform = mat2(invDm.xy, invDm.zw);
|
mat2 invDeform = mat2(invDm.xy, invDm.zw);
|
||||||
@@ -144,38 +138,13 @@ void main() {
|
|||||||
d *= scale;
|
d *= scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
dArr[i] = d;
|
mergedSdf = smin(mergedSdf, d, smoothFactor);
|
||||||
if (d < smoothFactor && d < minDist) {
|
if (d < smoothFactor && d < minDist) {
|
||||||
minDist = d;
|
minDist = d;
|
||||||
owner = i;
|
owner = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Phase 2: hard-min baseline over all rects.
|
|
||||||
float mergedSdf = 1e10;
|
|
||||||
for (int i = 0; i < rectCount; i++) {
|
|
||||||
mergedSdf = min(mergedSdf, dArr[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Phase 3: pair-wise smin contributions, skipping excluded pairs. Pair smin
|
|
||||||
// <= min, so taking the min over all non-excluded pair smins gives the
|
|
||||||
// smoothly-merged SDF.
|
|
||||||
for (int i = 0; i < rectCount; i++) {
|
|
||||||
if (dArr[i] >= 1e9)
|
|
||||||
continue;
|
|
||||||
int excludeMask = floatBitsToInt(rectData[i * 5 + 1].x);
|
|
||||||
for (int j = i + 1; j < rectCount; j++) {
|
|
||||||
if (dArr[j] >= 1e9)
|
|
||||||
continue;
|
|
||||||
if ((excludeMask & (1 << j)) != 0)
|
|
||||||
continue;
|
|
||||||
// smin only deviates from min within smoothFactor
|
|
||||||
if (abs(dArr[i] - dArr[j]) >= smoothFactor)
|
|
||||||
continue;
|
|
||||||
mergedSdf = min(mergedSdf, smin(dArr[i], dArr[j], smoothFactor));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasInverted != 0) {
|
if (hasInverted != 0) {
|
||||||
float dOuter = sdBox(pixel, invertedOuter.xy, invertedOuter.zw) - 1.0;
|
float dOuter = sdBox(pixel, invertedOuter.xy, invertedOuter.zw) - 1.0;
|
||||||
float dInner =
|
float dInner =
|
||||||
|
|||||||
@@ -1,384 +1,217 @@
|
|||||||
#include "hyprextras.hpp"
|
#include "hyprextras.hpp"
|
||||||
#include "hyprdevices.hpp"
|
|
||||||
|
|
||||||
#include <qdir.h>
|
#include <qdir.h>
|
||||||
#include <qjsonarray.h>
|
#include <qjsonarray.h>
|
||||||
#include <qlocalsocket.h>
|
#include <qlocalsocket.h>
|
||||||
#include <qloggingcategory.h>
|
|
||||||
#include <qmetatype.h>
|
|
||||||
#include <qregularexpression.h>
|
|
||||||
#include <qvariant.h>
|
#include <qvariant.h>
|
||||||
|
|
||||||
Q_LOGGING_CATEGORY(lcHypr, "ZShell.internal.hypr", QtInfoMsg)
|
|
||||||
|
|
||||||
namespace ZShell::internal::hypr {
|
namespace ZShell::internal::hypr {
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
static QString luaEscapeString(const QString& s) {
|
|
||||||
QString out;
|
|
||||||
out.reserve(s.size() + 2);
|
|
||||||
out += QLatin1Char('"');
|
|
||||||
|
|
||||||
for (const QChar c : s) {
|
|
||||||
switch (c.unicode()) {
|
|
||||||
case '\\':
|
|
||||||
out += QLatin1String(R"(\\)");
|
|
||||||
break;
|
|
||||||
case '"':
|
|
||||||
out += QLatin1String(R"(\")");
|
|
||||||
break;
|
|
||||||
case '\n':
|
|
||||||
out += QLatin1String(R"(\n)");
|
|
||||||
break;
|
|
||||||
case '\r':
|
|
||||||
out += QLatin1String(R"(\r)");
|
|
||||||
break;
|
|
||||||
case '\t':
|
|
||||||
out += QLatin1String(R"(\t)");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
out += c;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out += QLatin1Char('"');
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
static QString luaValue(const QVariant& v);
|
|
||||||
|
|
||||||
static QString luaArray(const QVariantList& list) {
|
|
||||||
QStringList parts;
|
|
||||||
parts.reserve(list.size());
|
|
||||||
|
|
||||||
for (const auto& item : list) {
|
|
||||||
parts << luaValue(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return QLatin1String("{ ") + parts.join(QLatin1String(", ")) + QLatin1String(" }");
|
|
||||||
}
|
|
||||||
|
|
||||||
static QString luaArray(const QStringList& list) {
|
|
||||||
QStringList parts;
|
|
||||||
parts.reserve(list.size());
|
|
||||||
|
|
||||||
for (const auto& item : list) {
|
|
||||||
parts << luaEscapeString(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return QLatin1String("{ ") + parts.join(QLatin1String(", ")) + QLatin1String(" }");
|
|
||||||
}
|
|
||||||
|
|
||||||
static QString luaMapFromHash(const QVariantHash& hash) {
|
|
||||||
QStringList parts;
|
|
||||||
parts.reserve(hash.size());
|
|
||||||
|
|
||||||
for (auto it = hash.cbegin(); it != hash.cend(); ++it) {
|
|
||||||
parts << luaEscapeString(it.key()) + QLatin1String(" = ") + luaValue(it.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
return QLatin1String("{ ") + parts.join(QLatin1String(", ")) + QLatin1String(" }");
|
|
||||||
}
|
|
||||||
|
|
||||||
static QString luaMap(const QVariantMap& map) {
|
|
||||||
QStringList parts;
|
|
||||||
parts.reserve(map.size());
|
|
||||||
|
|
||||||
for (auto it = map.cbegin(); it != map.cend(); ++it) {
|
|
||||||
parts << luaEscapeString(it.key()) + QLatin1String(" = ") + luaValue(it.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
return QLatin1String("{ ") + parts.join(QLatin1String(", ")) + QLatin1String(" }");
|
|
||||||
}
|
|
||||||
|
|
||||||
static QString luaValue(const QVariant& v) {
|
|
||||||
if (!v.isValid() || v.isNull()) {
|
|
||||||
return QLatin1String("nil");
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (v.metaType().id()) {
|
|
||||||
case QMetaType::Bool:
|
|
||||||
return v.toBool() ? QLatin1String("true") : QLatin1String("false");
|
|
||||||
|
|
||||||
case QMetaType::Int:
|
|
||||||
case QMetaType::UInt:
|
|
||||||
case QMetaType::LongLong:
|
|
||||||
case QMetaType::ULongLong:
|
|
||||||
case QMetaType::Double:
|
|
||||||
return v.toString();
|
|
||||||
|
|
||||||
case QMetaType::QString:
|
|
||||||
return luaEscapeString(v.toString());
|
|
||||||
|
|
||||||
case QMetaType::QStringList:
|
|
||||||
return luaArray(v.toStringList());
|
|
||||||
|
|
||||||
case QMetaType::QVariantList:
|
|
||||||
return luaArray(v.toList());
|
|
||||||
|
|
||||||
case QMetaType::QVariantMap:
|
|
||||||
return luaMap(v.toMap());
|
|
||||||
|
|
||||||
case QMetaType::QVariantHash:
|
|
||||||
return luaMapFromHash(v.toHash());
|
|
||||||
|
|
||||||
default:
|
|
||||||
return luaEscapeString(v.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static QString normalizeOptionPath(QString key) {
|
|
||||||
key = key.trimmed();
|
|
||||||
key.replace(QLatin1Char(':'), QLatin1Char('.'));
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
static QString buildHlConfigCall(const QString& key, const QVariant& value) {
|
|
||||||
const auto parts = normalizeOptionPath(key).split(QLatin1Char('.'), Qt::SkipEmptyParts);
|
|
||||||
if (parts.isEmpty()) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
QString out;
|
|
||||||
out.reserve(32 + key.size() + value.toString().size());
|
|
||||||
out += QLatin1String("hl.config({ ");
|
|
||||||
|
|
||||||
for (int i = 0; i < parts.size(); ++i) {
|
|
||||||
out += parts.at(i);
|
|
||||||
out += QLatin1String(" = ");
|
|
||||||
if (i + 1 < parts.size()) {
|
|
||||||
out += QLatin1String("{ ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out += luaValue(value);
|
|
||||||
|
|
||||||
for (int i = 0; i + 1 < parts.size(); ++i) {
|
|
||||||
out += QLatin1String(" }");
|
|
||||||
}
|
|
||||||
|
|
||||||
out += QLatin1String(" })");
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
HyprExtras::HyprExtras(QObject* parent)
|
HyprExtras::HyprExtras(QObject* parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
, m_requestSocket("")
|
, m_requestSocket("")
|
||||||
, m_eventSocket("")
|
, m_eventSocket("")
|
||||||
, m_socket(nullptr)
|
, m_socket(nullptr)
|
||||||
, m_socketValid(false)
|
, m_socketValid(false)
|
||||||
, m_devices(new HyprDevices(this)) {
|
, m_devices(new HyprDevices(this)) {
|
||||||
const auto his = qEnvironmentVariable("HYPRLAND_INSTANCE_SIGNATURE");
|
const auto his = qEnvironmentVariable("HYPRLAND_INSTANCE_SIGNATURE");
|
||||||
if (his.isEmpty()) {
|
if (his.isEmpty()) {
|
||||||
qCWarning(lcHypr) << "$HYPRLAND_INSTANCE_SIGNATURE is unset. Unable to connect to Hyprland socket.";
|
qWarning()
|
||||||
return;
|
<< "HyprExtras::HyprExtras: $HYPRLAND_INSTANCE_SIGNATURE is unset. Unable to connect to Hyprland socket.";
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto hyprDir = QString("%1/hypr/%2").arg(qEnvironmentVariable("XDG_RUNTIME_DIR"), his);
|
auto hyprDir = QString("%1/hypr/%2").arg(qEnvironmentVariable("XDG_RUNTIME_DIR"), his);
|
||||||
if (!QDir(hyprDir).exists()) {
|
if (!QDir(hyprDir).exists()) {
|
||||||
hyprDir = QStringLiteral("/tmp/hypr/") + his;
|
hyprDir = "/tmp/hypr/" + his;
|
||||||
|
|
||||||
if (!QDir(hyprDir).exists()) {
|
if (!QDir(hyprDir).exists()) {
|
||||||
qCWarning(lcHypr) << "Hyprland socket directory does not exist. Unable to connect to Hyprland socket.";
|
qWarning() << "HyprExtras::HyprExtras: Hyprland socket directory does not exist. Unable to connect to "
|
||||||
return;
|
"Hyprland socket.";
|
||||||
}
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_requestSocket = hyprDir + QStringLiteral("/.socket.sock");
|
m_requestSocket = hyprDir + "/.socket.sock";
|
||||||
m_eventSocket = hyprDir + QStringLiteral("/.socket2.sock");
|
m_eventSocket = hyprDir + "/.socket2.sock";
|
||||||
|
|
||||||
refreshOptions();
|
refreshOptions();
|
||||||
refreshDevices();
|
refreshDevices();
|
||||||
|
|
||||||
m_socket = new QLocalSocket(this);
|
m_socket = new QLocalSocket(this);
|
||||||
|
|
||||||
QObject::connect(m_socket, &QLocalSocket::errorOccurred, this, &HyprExtras::socketError);
|
QObject::connect(m_socket, &QLocalSocket::errorOccurred, this, &HyprExtras::socketError);
|
||||||
QObject::connect(m_socket, &QLocalSocket::stateChanged, this, &HyprExtras::socketStateChanged);
|
QObject::connect(m_socket, &QLocalSocket::stateChanged, this, &HyprExtras::socketStateChanged);
|
||||||
QObject::connect(m_socket, &QLocalSocket::readyRead, this, &HyprExtras::readEvent);
|
QObject::connect(m_socket, &QLocalSocket::readyRead, this, &HyprExtras::readEvent);
|
||||||
|
|
||||||
m_socket->connectToServer(m_eventSocket, QLocalSocket::ReadOnly);
|
m_socket->connectToServer(m_eventSocket, QLocalSocket::ReadOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariantHash HyprExtras::options() const {
|
QVariantHash HyprExtras::options() const {
|
||||||
return m_options;
|
return m_options;
|
||||||
}
|
}
|
||||||
|
|
||||||
HyprDevices* HyprExtras::devices() const {
|
HyprDevices* HyprExtras::devices() const {
|
||||||
return m_devices;
|
return m_devices;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HyprExtras::message(const QString& message) {
|
void HyprExtras::message(const QString& message) {
|
||||||
if (message.isEmpty()) {
|
if (message.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
makeRequest(message, [](bool success, const QByteArray& res) {
|
makeRequest(message, [](bool success, const QByteArray& res) {
|
||||||
if (!success) {
|
if (!success) {
|
||||||
qCWarning(lcHypr) << "message: request error:" << QString::fromUtf8(res);
|
qWarning() << "HyprExtras::message: request error:" << QString::fromUtf8(res);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void HyprExtras::batchMessage(const QStringList& messages) {
|
void HyprExtras::batchMessage(const QStringList& messages) {
|
||||||
if (messages.isEmpty()) {
|
if (messages.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
makeRequest(QStringLiteral("[[BATCH]]") + messages.join(QLatin1Char(';')),
|
makeRequest("[[BATCH]]" + messages.join(";"), [](bool success, const QByteArray& res) {
|
||||||
[](bool success, const QByteArray& res) {
|
if (!success) {
|
||||||
if (!success) {
|
qWarning() << "HyprExtras::batchMessage: request error:" << QString::fromUtf8(res);
|
||||||
qCWarning(lcHypr) << "batchMessage: request error:" << QString::fromUtf8(res);
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HyprExtras::applyOptions(const QVariantHash& options) {
|
void HyprExtras::applyOptions(const QVariantHash& options) {
|
||||||
if (options.isEmpty()) {
|
if (options.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList calls;
|
QString request = "[[BATCH]]";
|
||||||
calls.reserve(options.size());
|
for (auto it = options.constBegin(); it != options.constEnd(); ++it) {
|
||||||
|
request += QString("keyword %1 %2;").arg(it.key(), it.value().toString());
|
||||||
|
}
|
||||||
|
|
||||||
for (auto it = options.constBegin(); it != options.constEnd(); ++it) {
|
makeRequest(request, [this](bool success, const QByteArray& res) {
|
||||||
const auto call = buildHlConfigCall(it.key(), it.value());
|
if (success) {
|
||||||
if (!call.isEmpty()) {
|
refreshOptions();
|
||||||
calls << call;
|
} else {
|
||||||
}
|
qWarning() << "HyprExtras::applyOptions: request error" << QString::fromUtf8(res);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
if (calls.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
makeRequest(QStringLiteral("eval ") + calls.join(QLatin1String("; ")), [this](bool success, const QByteArray& res) {
|
|
||||||
if (success) {
|
|
||||||
refreshOptions();
|
|
||||||
} else {
|
|
||||||
qCWarning(lcHypr) << "applyOptions: request error" << QString::fromUtf8(res);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HyprExtras::refreshOptions() {
|
void HyprExtras::refreshOptions() {
|
||||||
if (!m_optionsRefresh.isNull()) {
|
if (!m_optionsRefresh.isNull()) {
|
||||||
m_optionsRefresh->close();
|
m_optionsRefresh->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_optionsRefresh = makeRequestJson(QStringLiteral("descriptions"), [this](bool success, const QJsonDocument& response) {
|
m_optionsRefresh = makeRequestJson("descriptions", [this](bool success, const QJsonDocument& response) {
|
||||||
m_optionsRefresh.reset();
|
m_optionsRefresh.reset();
|
||||||
if (!success) {
|
if (!success) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto options = response.array();
|
const auto options = response.array();
|
||||||
bool dirty = false;
|
bool dirty = false;
|
||||||
|
|
||||||
for (const auto& o : std::as_const(options)) {
|
for (const auto& o : std::as_const(options)) {
|
||||||
const auto obj = o.toObject();
|
const auto obj = o.toObject();
|
||||||
const auto key = obj.value(QStringLiteral("value")).toString();
|
const auto key = obj.value("value").toString();
|
||||||
const auto value = obj.value(QStringLiteral("data")).toObject().value(QStringLiteral("current")).toVariant();
|
const auto value = obj.value("data").toObject().value("current").toVariant();
|
||||||
|
if (m_options.value(key) != value) {
|
||||||
|
dirty = true;
|
||||||
|
m_options.insert(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (m_options.value(key) != value) {
|
if (dirty) {
|
||||||
dirty = true;
|
emit optionsChanged();
|
||||||
m_options.insert(key, value);
|
}
|
||||||
}
|
});
|
||||||
}
|
|
||||||
|
|
||||||
if (dirty) {
|
|
||||||
emit optionsChanged();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HyprExtras::refreshDevices() {
|
void HyprExtras::refreshDevices() {
|
||||||
if (!m_devicesRefresh.isNull()) {
|
if (!m_devicesRefresh.isNull()) {
|
||||||
m_devicesRefresh->close();
|
m_devicesRefresh->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_devicesRefresh = makeRequestJson(QStringLiteral("devices"), [this](bool success, const QJsonDocument& response) {
|
m_devicesRefresh = makeRequestJson("devices", [this](bool success, const QJsonDocument& response) {
|
||||||
m_devicesRefresh.reset();
|
m_devicesRefresh.reset();
|
||||||
if (success) {
|
if (success) {
|
||||||
m_devices->updateLastIpcObject(response.object());
|
m_devices->updateLastIpcObject(response.object());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void HyprExtras::socketError(QLocalSocket::LocalSocketError error) const {
|
void HyprExtras::socketError(QLocalSocket::LocalSocketError error) const {
|
||||||
if (!m_socketValid) {
|
if (!m_socketValid) {
|
||||||
qCWarning(lcHypr) << "socketError: unable to connect to Hyprland event socket:" << error;
|
qWarning() << "HyprExtras::socketError: unable to connect to Hyprland event socket:" << error;
|
||||||
} else {
|
} else {
|
||||||
qCWarning(lcHypr) << "socketError: Hyprland event socket error:" << error;
|
qWarning() << "HyprExtras::socketError: Hyprland event socket error:" << error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HyprExtras::socketStateChanged(QLocalSocket::LocalSocketState state) {
|
void HyprExtras::socketStateChanged(QLocalSocket::LocalSocketState state) {
|
||||||
if (state == QLocalSocket::UnconnectedState && m_socketValid) {
|
if (state == QLocalSocket::UnconnectedState && m_socketValid) {
|
||||||
qCWarning(lcHypr) << "socketStateChanged: Hyprland event socket disconnected.";
|
qWarning() << "HyprExtras::socketStateChanged: Hyprland event socket disconnected.";
|
||||||
}
|
}
|
||||||
|
|
||||||
m_socketValid = state == QLocalSocket::ConnectedState;
|
m_socketValid = state == QLocalSocket::ConnectedState;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HyprExtras::readEvent() {
|
void HyprExtras::readEvent() {
|
||||||
while (true) {
|
while (true) {
|
||||||
auto rawEvent = m_socket->readLine();
|
auto rawEvent = m_socket->readLine();
|
||||||
if (rawEvent.isEmpty()) {
|
if (rawEvent.isEmpty()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
rawEvent.truncate(rawEvent.length() - 1);
|
rawEvent.truncate(rawEvent.length() - 1); // Remove trailing \n
|
||||||
const auto event = QByteArrayView(rawEvent.data(), rawEvent.indexOf(">>"));
|
const auto event = QByteArrayView(rawEvent.data(), rawEvent.indexOf(">>"));
|
||||||
handleEvent(QString::fromUtf8(event));
|
handleEvent(QString::fromUtf8(event));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HyprExtras::handleEvent(const QString& event) {
|
void HyprExtras::handleEvent(const QString& event) {
|
||||||
if (event == QStringLiteral("configreloaded")) {
|
if (event == "configreloaded") {
|
||||||
refreshOptions();
|
refreshOptions();
|
||||||
} else if (event == QStringLiteral("activelayout")) {
|
} else if (event == "activelayout") {
|
||||||
refreshDevices();
|
refreshDevices();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HyprExtras::SocketPtr HyprExtras::makeRequestJson(
|
HyprExtras::SocketPtr HyprExtras::makeRequestJson(
|
||||||
const QString& request, const std::function<void(bool, QJsonDocument)>& callback) {
|
const QString& request, const std::function<void(bool, QJsonDocument)>& callback) {
|
||||||
return makeRequest(QStringLiteral("j/") + request, [callback](bool success, const QByteArray& response) {
|
return makeRequest("j/" + request, [callback](bool success, const QByteArray& response) {
|
||||||
callback(success, QJsonDocument::fromJson(response));
|
callback(success, QJsonDocument::fromJson(response));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
HyprExtras::SocketPtr HyprExtras::makeRequest(
|
HyprExtras::SocketPtr HyprExtras::makeRequest(
|
||||||
const QString& request, const std::function<void(bool, QByteArray)>& callback) {
|
const QString& request, const std::function<void(bool, QByteArray)>& callback) {
|
||||||
if (m_requestSocket.isEmpty()) {
|
if (m_requestSocket.isEmpty()) {
|
||||||
return SocketPtr();
|
return SocketPtr();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto socket = SocketPtr::create(this);
|
auto socket = SocketPtr::create(this);
|
||||||
|
|
||||||
QObject::connect(socket.data(), &QLocalSocket::connected, this, [=, this]() {
|
QObject::connect(socket.data(), &QLocalSocket::connected, this, [=, this]() {
|
||||||
QObject::connect(socket.data(), &QLocalSocket::readyRead, this, [socket, callback]() {
|
QObject::connect(socket.data(), &QLocalSocket::readyRead, this, [socket, callback]() {
|
||||||
const auto response = socket->readAll();
|
const auto response = socket->readAll();
|
||||||
callback(true, std::move(response));
|
callback(true, std::move(response));
|
||||||
socket->close();
|
socket->close();
|
||||||
});
|
});
|
||||||
|
|
||||||
socket->write(request.toUtf8());
|
socket->write(request.toUtf8());
|
||||||
socket->flush();
|
socket->flush();
|
||||||
});
|
});
|
||||||
|
|
||||||
QObject::connect(socket.data(), &QLocalSocket::errorOccurred, this, [=](QLocalSocket::LocalSocketError err) {
|
QObject::connect(socket.data(), &QLocalSocket::errorOccurred, this, [=](QLocalSocket::LocalSocketError err) {
|
||||||
qCWarning(lcHypr) << "makeRequest: error making request:" << err << "| request:" << request;
|
qWarning() << "HyprExtras::makeRequest: error making request:" << err << "| request:" << request;
|
||||||
callback(false, {});
|
callback(false, {});
|
||||||
socket->close();
|
socket->close();
|
||||||
});
|
});
|
||||||
|
|
||||||
socket->connectToServer(m_requestSocket);
|
socket->connectToServer(m_requestSocket);
|
||||||
|
|
||||||
return socket;
|
return socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ZShell::internal::hypr
|
} // namespace ZShell::internal::hypr
|
||||||
|
|||||||
@@ -1,60 +1,56 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "hyprdevices.hpp"
|
||||||
#include <qlocalsocket.h>
|
#include <qlocalsocket.h>
|
||||||
#include <qobject.h>
|
#include <qobject.h>
|
||||||
#include <qqmlintegration.h>
|
#include <qqmlintegration.h>
|
||||||
#include <qsharedpointer.h>
|
|
||||||
#include <qvariant.h>
|
|
||||||
|
|
||||||
namespace ZShell::internal::hypr {
|
namespace ZShell::internal::hypr {
|
||||||
|
|
||||||
class HyprDevices;
|
|
||||||
|
|
||||||
class HyprExtras : public QObject {
|
class HyprExtras : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
QML_ELEMENT
|
QML_ELEMENT
|
||||||
Q_MOC_INCLUDE("hyprdevices.hpp")
|
|
||||||
|
|
||||||
Q_PROPERTY(QVariantHash options READ options NOTIFY optionsChanged)
|
Q_PROPERTY(QVariantHash options READ options NOTIFY optionsChanged)
|
||||||
Q_PROPERTY(ZShell::internal::hypr::HyprDevices* devices READ devices CONSTANT)
|
Q_PROPERTY(ZShell::internal::hypr::HyprDevices* devices READ devices CONSTANT)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit HyprExtras(QObject* parent = nullptr);
|
explicit HyprExtras(QObject* parent = nullptr);
|
||||||
|
|
||||||
[[nodiscard]] QVariantHash options() const;
|
[[nodiscard]] QVariantHash options() const;
|
||||||
[[nodiscard]] HyprDevices* devices() const;
|
[[nodiscard]] HyprDevices* devices() const;
|
||||||
|
|
||||||
Q_INVOKABLE void message(const QString& message);
|
Q_INVOKABLE void message(const QString& message);
|
||||||
Q_INVOKABLE void batchMessage(const QStringList& messages);
|
Q_INVOKABLE void batchMessage(const QStringList& messages);
|
||||||
Q_INVOKABLE void applyOptions(const QVariantHash& options);
|
Q_INVOKABLE void applyOptions(const QVariantHash& options);
|
||||||
|
|
||||||
Q_INVOKABLE void refreshOptions();
|
Q_INVOKABLE void refreshOptions();
|
||||||
Q_INVOKABLE void refreshDevices();
|
Q_INVOKABLE void refreshDevices();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void optionsChanged();
|
void optionsChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using SocketPtr = QSharedPointer<QLocalSocket>;
|
using SocketPtr = QSharedPointer<QLocalSocket>;
|
||||||
|
|
||||||
QString m_requestSocket;
|
QString m_requestSocket;
|
||||||
QString m_eventSocket;
|
QString m_eventSocket;
|
||||||
QLocalSocket* m_socket;
|
QLocalSocket* m_socket;
|
||||||
bool m_socketValid;
|
bool m_socketValid;
|
||||||
|
|
||||||
QVariantHash m_options;
|
QVariantHash m_options;
|
||||||
HyprDevices* const m_devices;
|
HyprDevices* const m_devices;
|
||||||
|
|
||||||
SocketPtr m_optionsRefresh;
|
SocketPtr m_optionsRefresh;
|
||||||
SocketPtr m_devicesRefresh;
|
SocketPtr m_devicesRefresh;
|
||||||
|
|
||||||
void socketError(QLocalSocket::LocalSocketError error) const;
|
void socketError(QLocalSocket::LocalSocketError error) const;
|
||||||
void socketStateChanged(QLocalSocket::LocalSocketState state);
|
void socketStateChanged(QLocalSocket::LocalSocketState state);
|
||||||
void readEvent();
|
void readEvent();
|
||||||
void handleEvent(const QString& event);
|
void handleEvent(const QString& event);
|
||||||
|
|
||||||
SocketPtr makeRequestJson(const QString& request, const std::function<void(bool, QJsonDocument)>& callback);
|
SocketPtr makeRequestJson(const QString& request, const std::function<void(bool, QJsonDocument)>& callback);
|
||||||
SocketPtr makeRequest(const QString& request, const std::function<void(bool, QByteArray)>& callback);
|
SocketPtr makeRequest(const QString& request, const std::function<void(bool, QByteArray)>& callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ZShell::internal::hypr
|
} // namespace ZShell::internal::hypr
|
||||||
|
|||||||
@@ -74,8 +74,6 @@ Defaults from `CMakeLists.txt`:
|
|||||||
|
|
||||||
### Nix Flake
|
### Nix Flake
|
||||||
|
|
||||||
_Note that Nix is not actively developed at this point. Things may be broken. Feel free to suggest fixes in a PR_
|
|
||||||
|
|
||||||
The flake exposes:
|
The flake exposes:
|
||||||
|
|
||||||
- `packages.<system>.zshell`
|
- `packages.<system>.zshell`
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"typer",
|
"typer",
|
||||||
"pillow",
|
"pillow",
|
||||||
|
"jinja2",
|
||||||
"materialyoucolor"
|
"materialyoucolor"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
import typer
|
import typer
|
||||||
from zshell.subcommands import shell, scheme, screenshot, wallpaper
|
from zshell.subcommands import shell, scheme, screenshot, wallpaper, preset
|
||||||
|
|
||||||
app = typer.Typer()
|
app = typer.Typer()
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ app.add_typer(shell.app, name="shell")
|
|||||||
app.add_typer(scheme.app, name="scheme")
|
app.add_typer(scheme.app, name="scheme")
|
||||||
app.add_typer(screenshot.app, name="screenshot")
|
app.add_typer(screenshot.app, name="screenshot")
|
||||||
app.add_typer(wallpaper.app, name="wallpaper")
|
app.add_typer(wallpaper.app, name="wallpaper")
|
||||||
# app.add_typer(preset.app, name="preset")
|
app.add_typer(preset.app, name="preset")
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,544 @@
|
|||||||
|
{
|
||||||
|
"id": "catppuccin",
|
||||||
|
"name": "Catppuccin",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"author": "Catppuccin Org",
|
||||||
|
"description": "Soothing pastel theme for the high-spirited!",
|
||||||
|
"dark": {},
|
||||||
|
"light": {},
|
||||||
|
"variants": {
|
||||||
|
"type": "multi",
|
||||||
|
"defaults": {
|
||||||
|
"dark": { "flavor": "mocha", "accent": "mauve" },
|
||||||
|
"light": { "flavor": "latte", "accent": "mauve" }
|
||||||
|
},
|
||||||
|
"flavors": [
|
||||||
|
{
|
||||||
|
"id": "latte",
|
||||||
|
"name": "Latte",
|
||||||
|
"light": {
|
||||||
|
"surface": "#ccd0da",
|
||||||
|
"surfaceText": "#4c4f69",
|
||||||
|
"surfaceVariant": "#eff1f5",
|
||||||
|
"surfaceVariantText": "#6c6f85",
|
||||||
|
"background": "#eff1f5",
|
||||||
|
"backgroundText": "#4c4f69",
|
||||||
|
"outline": "#9ca0b0",
|
||||||
|
"surfaceContainer": "#eff1f5",
|
||||||
|
"surfaceContainerHigh": "#e6e9ef",
|
||||||
|
"surfaceContainerHighest": "#dce0e8",
|
||||||
|
"error": "#d20f39",
|
||||||
|
"warning": "#fe640b",
|
||||||
|
"info": "#1e66f5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "frappe",
|
||||||
|
"name": "Frappé",
|
||||||
|
"dark": {
|
||||||
|
"surface": "#414559",
|
||||||
|
"surfaceText": "#c6d0f5",
|
||||||
|
"surfaceVariant": "#303446",
|
||||||
|
"surfaceVariantText": "#a5adce",
|
||||||
|
"background": "#303446",
|
||||||
|
"backgroundText": "#c6d0f5",
|
||||||
|
"outline": "#737994",
|
||||||
|
"surfaceContainer": "#303446",
|
||||||
|
"surfaceContainerHigh": "#292c3c",
|
||||||
|
"surfaceContainerHighest": "#232634",
|
||||||
|
"error": "#e78284",
|
||||||
|
"warning": "#ef9f76",
|
||||||
|
"info": "#8caaee"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "macchiato",
|
||||||
|
"name": "Macchiato",
|
||||||
|
"dark": {
|
||||||
|
"surface": "#363a4f",
|
||||||
|
"surfaceText": "#cad3f5",
|
||||||
|
"surfaceVariant": "#24273a",
|
||||||
|
"surfaceVariantText": "#a5adcb",
|
||||||
|
"background": "#24273a",
|
||||||
|
"backgroundText": "#cad3f5",
|
||||||
|
"outline": "#6e738d",
|
||||||
|
"surfaceContainer": "#24273a",
|
||||||
|
"surfaceContainerHigh": "#1e2030",
|
||||||
|
"surfaceContainerHighest": "#181926",
|
||||||
|
"error": "#ed8796",
|
||||||
|
"warning": "#f5a97f",
|
||||||
|
"info": "#8aadf4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "mocha",
|
||||||
|
"name": "Mocha",
|
||||||
|
"dark": {
|
||||||
|
"surface": "#313244",
|
||||||
|
"surfaceText": "#cdd6f4",
|
||||||
|
"surfaceVariant": "#1e1e2e",
|
||||||
|
"surfaceVariantText": "#a6adc8",
|
||||||
|
"background": "#1e1e2e",
|
||||||
|
"backgroundText": "#cdd6f4",
|
||||||
|
"outline": "#6c7086",
|
||||||
|
"surfaceContainer": "#1e1e2e",
|
||||||
|
"surfaceContainerHigh": "#181825",
|
||||||
|
"surfaceContainerHighest": "#11111b",
|
||||||
|
"error": "#f38ba8",
|
||||||
|
"warning": "#fab387",
|
||||||
|
"info": "#89b4fa"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"accents": [
|
||||||
|
{
|
||||||
|
"id": "rosewater",
|
||||||
|
"name": "Rosewater",
|
||||||
|
"latte": {
|
||||||
|
"primary": "#dc8a78",
|
||||||
|
"primaryText": "#eff1f5",
|
||||||
|
"primaryContainer": "#e1a99d",
|
||||||
|
"secondary": "#d8c7c4",
|
||||||
|
"surfaceTint": "#e1a99d"
|
||||||
|
},
|
||||||
|
"frappe": {
|
||||||
|
"primary": "#f2d5cf",
|
||||||
|
"primaryText": "#303446",
|
||||||
|
"primaryContainer": "#b8a5a6",
|
||||||
|
"secondary": "#a2748b",
|
||||||
|
"surfaceTint": "#b8a5a6"
|
||||||
|
},
|
||||||
|
"macchiato": {
|
||||||
|
"primary": "#f4dbd6",
|
||||||
|
"primaryText": "#24273a",
|
||||||
|
"primaryContainer": "#b6a6a7",
|
||||||
|
"secondary": "#9f6f8d",
|
||||||
|
"surfaceTint": "#b6a6a7"
|
||||||
|
},
|
||||||
|
"mocha": {
|
||||||
|
"primary": "#f5e0dc",
|
||||||
|
"primaryText": "#1e1e2e",
|
||||||
|
"primaryContainer": "#b5a6a8",
|
||||||
|
"secondary": "#9d6d87",
|
||||||
|
"surfaceTint": "#b5a6a8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flamingo",
|
||||||
|
"name": "Flamingo",
|
||||||
|
"latte": {
|
||||||
|
"primary": "#dd7878",
|
||||||
|
"primaryText": "#eff1f5",
|
||||||
|
"primaryContainer": "#e29c9d",
|
||||||
|
"secondary": "#d7c3c4",
|
||||||
|
"surfaceTint": "#e29c9d"
|
||||||
|
},
|
||||||
|
"frappe": {
|
||||||
|
"primary": "#eebebe",
|
||||||
|
"primaryText": "#303446",
|
||||||
|
"primaryContainer": "#b5949a",
|
||||||
|
"secondary": "#9d6b80",
|
||||||
|
"surfaceTint": "#b5949a"
|
||||||
|
},
|
||||||
|
"macchiato": {
|
||||||
|
"primary": "#f0c6c6",
|
||||||
|
"primaryText": "#24273a",
|
||||||
|
"primaryContainer": "#b3979c",
|
||||||
|
"secondary": "#996780",
|
||||||
|
"surfaceTint": "#b3979c"
|
||||||
|
},
|
||||||
|
"mocha": {
|
||||||
|
"primary": "#f2cdcd",
|
||||||
|
"primaryText": "#1e1e2e",
|
||||||
|
"primaryContainer": "#b3999e",
|
||||||
|
"secondary": "#98667c",
|
||||||
|
"surfaceTint": "#b3999e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "pink",
|
||||||
|
"name": "Pink",
|
||||||
|
"latte": {
|
||||||
|
"primary": "#ea76cb",
|
||||||
|
"primaryText": "#eff1f5",
|
||||||
|
"primaryContainer": "#eb9bd7",
|
||||||
|
"secondary": "#d9c7d5",
|
||||||
|
"surfaceTint": "#eb9bd7"
|
||||||
|
},
|
||||||
|
"frappe": {
|
||||||
|
"primary": "#f4b8e4",
|
||||||
|
"primaryText": "#303446",
|
||||||
|
"primaryContainer": "#b990b5",
|
||||||
|
"secondary": "#996e9e",
|
||||||
|
"surfaceTint": "#b990b5"
|
||||||
|
},
|
||||||
|
"macchiato": {
|
||||||
|
"primary": "#f5bde6",
|
||||||
|
"primaryText": "#24273a",
|
||||||
|
"primaryContainer": "#b791b2",
|
||||||
|
"secondary": "#95689a",
|
||||||
|
"surfaceTint": "#b791b2"
|
||||||
|
},
|
||||||
|
"mocha": {
|
||||||
|
"primary": "#f5c2e7",
|
||||||
|
"primaryText": "#1e1e2e",
|
||||||
|
"primaryContainer": "#b591b0",
|
||||||
|
"secondary": "#966597",
|
||||||
|
"surfaceTint": "#b591b0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "mauve",
|
||||||
|
"name": "Mauve",
|
||||||
|
"latte": {
|
||||||
|
"primary": "#8839ef",
|
||||||
|
"primaryText": "#eff1f5",
|
||||||
|
"primaryContainer": "#a670f1",
|
||||||
|
"secondary": "#c2b8d0",
|
||||||
|
"surfaceTint": "#a670f1"
|
||||||
|
},
|
||||||
|
"frappe": {
|
||||||
|
"primary": "#ca9ee6",
|
||||||
|
"primaryText": "#303446",
|
||||||
|
"primaryContainer": "#9c7eb6",
|
||||||
|
"secondary": "#7d6799",
|
||||||
|
"surfaceTint": "#9c7eb6"
|
||||||
|
},
|
||||||
|
"macchiato": {
|
||||||
|
"primary": "#c6a0f6",
|
||||||
|
"primaryText": "#24273a",
|
||||||
|
"primaryContainer": "#967cbe",
|
||||||
|
"secondary": "#766597",
|
||||||
|
"surfaceTint": "#967cbe"
|
||||||
|
},
|
||||||
|
"mocha": {
|
||||||
|
"primary": "#cba6f7",
|
||||||
|
"primaryText": "#1e1e2e",
|
||||||
|
"primaryContainer": "#977ebb",
|
||||||
|
"secondary": "#756294",
|
||||||
|
"surfaceTint": "#977ebb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "red",
|
||||||
|
"name": "Red",
|
||||||
|
"latte": {
|
||||||
|
"primary": "#d20f39",
|
||||||
|
"primaryText": "#eff1f5",
|
||||||
|
"primaryContainer": "#da5371",
|
||||||
|
"secondary": "#c0a0a8",
|
||||||
|
"surfaceTint": "#da5371"
|
||||||
|
},
|
||||||
|
"frappe": {
|
||||||
|
"primary": "#e78284",
|
||||||
|
"primaryText": "#303446",
|
||||||
|
"primaryContainer": "#b06a72",
|
||||||
|
"secondary": "#8b5d66",
|
||||||
|
"surfaceTint": "#b06a72"
|
||||||
|
},
|
||||||
|
"macchiato": {
|
||||||
|
"primary": "#ed8796",
|
||||||
|
"primaryText": "#24273a",
|
||||||
|
"primaryContainer": "#b16b7a",
|
||||||
|
"secondary": "#865a69",
|
||||||
|
"surfaceTint": "#b16b7a"
|
||||||
|
},
|
||||||
|
"mocha": {
|
||||||
|
"primary": "#f38ba8",
|
||||||
|
"primaryText": "#1e1e2e",
|
||||||
|
"primaryContainer": "#b46b84",
|
||||||
|
"secondary": "#85596b",
|
||||||
|
"surfaceTint": "#b46b84"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "maroon",
|
||||||
|
"name": "Maroon",
|
||||||
|
"latte": {
|
||||||
|
"primary": "#e64553",
|
||||||
|
"primaryText": "#eff1f5",
|
||||||
|
"primaryContainer": "#e87883",
|
||||||
|
"secondary": "#cfb7ba",
|
||||||
|
"surfaceTint": "#e87883"
|
||||||
|
},
|
||||||
|
"frappe": {
|
||||||
|
"primary": "#ea999c",
|
||||||
|
"primaryText": "#303446",
|
||||||
|
"primaryContainer": "#b27a83",
|
||||||
|
"secondary": "#92626f",
|
||||||
|
"surfaceTint": "#b27a83"
|
||||||
|
},
|
||||||
|
"macchiato": {
|
||||||
|
"primary": "#ee99a0",
|
||||||
|
"primaryText": "#24273a",
|
||||||
|
"primaryContainer": "#b27781",
|
||||||
|
"secondary": "#8c5e6c",
|
||||||
|
"surfaceTint": "#b27781"
|
||||||
|
},
|
||||||
|
"mocha": {
|
||||||
|
"primary": "#eba0ac",
|
||||||
|
"primaryText": "#1e1e2e",
|
||||||
|
"primaryContainer": "#ae7987",
|
||||||
|
"secondary": "#895b6c",
|
||||||
|
"surfaceTint": "#ae7987"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "peach",
|
||||||
|
"name": "Peach",
|
||||||
|
"latte": {
|
||||||
|
"primary": "#fe640b",
|
||||||
|
"primaryText": "#eff1f5",
|
||||||
|
"primaryContainer": "#f98e51",
|
||||||
|
"secondary": "#c9b7ad",
|
||||||
|
"surfaceTint": "#f98e51"
|
||||||
|
},
|
||||||
|
"frappe": {
|
||||||
|
"primary": "#ef9f76",
|
||||||
|
"primaryText": "#303446",
|
||||||
|
"primaryContainer": "#b67f68",
|
||||||
|
"secondary": "#8f6a5f",
|
||||||
|
"surfaceTint": "#b67f68"
|
||||||
|
},
|
||||||
|
"macchiato": {
|
||||||
|
"primary": "#f5a97f",
|
||||||
|
"primaryText": "#24273a",
|
||||||
|
"primaryContainer": "#b7836a",
|
||||||
|
"secondary": "#8c695e",
|
||||||
|
"surfaceTint": "#b7836a"
|
||||||
|
},
|
||||||
|
"mocha": {
|
||||||
|
"primary": "#fab387",
|
||||||
|
"primaryText": "#1e1e2e",
|
||||||
|
"primaryContainer": "#b8876d",
|
||||||
|
"secondary": "#8b6a5d",
|
||||||
|
"surfaceTint": "#b8876d"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "yellow",
|
||||||
|
"name": "Yellow",
|
||||||
|
"latte": {
|
||||||
|
"primary": "#df8e1d",
|
||||||
|
"primaryText": "#eff1f5",
|
||||||
|
"primaryContainer": "#e4ac5d",
|
||||||
|
"secondary": "#c6baaa",
|
||||||
|
"surfaceTint": "#e4ac5d"
|
||||||
|
},
|
||||||
|
"frappe": {
|
||||||
|
"primary": "#e5c890",
|
||||||
|
"primaryText": "#303446",
|
||||||
|
"primaryContainer": "#af9b7a",
|
||||||
|
"secondary": "#948062",
|
||||||
|
"surfaceTint": "#af9b7a"
|
||||||
|
},
|
||||||
|
"macchiato": {
|
||||||
|
"primary": "#eed49f",
|
||||||
|
"primaryText": "#24273a",
|
||||||
|
"primaryContainer": "#b2a181",
|
||||||
|
"secondary": "#947e62",
|
||||||
|
"surfaceTint": "#b2a181"
|
||||||
|
},
|
||||||
|
"mocha": {
|
||||||
|
"primary": "#f9e2af",
|
||||||
|
"primaryText": "#1e1e2e",
|
||||||
|
"primaryContainer": "#b8a889",
|
||||||
|
"secondary": "#978265",
|
||||||
|
"surfaceTint": "#b8a889"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "green",
|
||||||
|
"name": "Green",
|
||||||
|
"latte": {
|
||||||
|
"primary": "#40a02b",
|
||||||
|
"primaryText": "#eff1f5",
|
||||||
|
"primaryContainer": "#74b867",
|
||||||
|
"secondary": "#9fbd9b",
|
||||||
|
"surfaceTint": "#74b867"
|
||||||
|
},
|
||||||
|
"frappe": {
|
||||||
|
"primary": "#a6d189",
|
||||||
|
"primaryText": "#303446",
|
||||||
|
"primaryContainer": "#83a275",
|
||||||
|
"secondary": "#648e5e",
|
||||||
|
"surfaceTint": "#83a275"
|
||||||
|
},
|
||||||
|
"macchiato": {
|
||||||
|
"primary": "#a6da95",
|
||||||
|
"primaryText": "#24273a",
|
||||||
|
"primaryContainer": "#80a57a",
|
||||||
|
"secondary": "#5c8a61",
|
||||||
|
"surfaceTint": "#80a57a"
|
||||||
|
},
|
||||||
|
"mocha": {
|
||||||
|
"primary": "#a6e3a1",
|
||||||
|
"primaryText": "#1e1e2e",
|
||||||
|
"primaryContainer": "#7ea87f",
|
||||||
|
"secondary": "#5b8964",
|
||||||
|
"surfaceTint": "#7ea87f"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "teal",
|
||||||
|
"name": "Teal",
|
||||||
|
"latte": {
|
||||||
|
"primary": "#179299",
|
||||||
|
"primaryText": "#eff1f5",
|
||||||
|
"primaryContainer": "#57aeb4",
|
||||||
|
"secondary": "#93b4b7",
|
||||||
|
"surfaceTint": "#57aeb4"
|
||||||
|
},
|
||||||
|
"frappe": {
|
||||||
|
"primary": "#81c8be",
|
||||||
|
"primaryText": "#303446",
|
||||||
|
"primaryContainer": "#699b9a",
|
||||||
|
"secondary": "#588084",
|
||||||
|
"surfaceTint": "#699b9a"
|
||||||
|
},
|
||||||
|
"macchiato": {
|
||||||
|
"primary": "#8bd5ca",
|
||||||
|
"primaryText": "#24273a",
|
||||||
|
"primaryContainer": "#6da29f",
|
||||||
|
"secondary": "#577e83",
|
||||||
|
"surfaceTint": "#6da29f"
|
||||||
|
},
|
||||||
|
"mocha": {
|
||||||
|
"primary": "#94e2d5",
|
||||||
|
"primaryText": "#1e1e2e",
|
||||||
|
"primaryContainer": "#71a8a4",
|
||||||
|
"secondary": "#588284",
|
||||||
|
"surfaceTint": "#71a8a4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "sky",
|
||||||
|
"name": "Sky",
|
||||||
|
"latte": {
|
||||||
|
"primary": "#04a5e5",
|
||||||
|
"primaryText": "#eff1f5",
|
||||||
|
"primaryContainer": "#4abcea",
|
||||||
|
"secondary": "#a4b9c2",
|
||||||
|
"surfaceTint": "#4abcea"
|
||||||
|
},
|
||||||
|
"frappe": {
|
||||||
|
"primary": "#99d1db",
|
||||||
|
"primaryText": "#303446",
|
||||||
|
"primaryContainer": "#79a2af",
|
||||||
|
"secondary": "#628494",
|
||||||
|
"surfaceTint": "#79a2af"
|
||||||
|
},
|
||||||
|
"macchiato": {
|
||||||
|
"primary": "#91d7e3",
|
||||||
|
"primaryText": "#24273a",
|
||||||
|
"primaryContainer": "#71a3b0",
|
||||||
|
"secondary": "#5e7e8c",
|
||||||
|
"surfaceTint": "#71a3b0"
|
||||||
|
},
|
||||||
|
"mocha": {
|
||||||
|
"primary": "#89dceb",
|
||||||
|
"primaryText": "#1e1e2e",
|
||||||
|
"primaryContainer": "#69a3b3",
|
||||||
|
"secondary": "#5a7b88",
|
||||||
|
"surfaceTint": "#69a3b3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "sapphire",
|
||||||
|
"name": "Sapphire",
|
||||||
|
"latte": {
|
||||||
|
"primary": "#209fb5",
|
||||||
|
"primaryText": "#eff1f5",
|
||||||
|
"primaryContainer": "#5db8c8",
|
||||||
|
"secondary": "#9eb9be",
|
||||||
|
"surfaceTint": "#5db8c8"
|
||||||
|
},
|
||||||
|
"frappe": {
|
||||||
|
"primary": "#85c1dc",
|
||||||
|
"primaryText": "#303446",
|
||||||
|
"primaryContainer": "#6b96af",
|
||||||
|
"secondary": "#5e7b8e",
|
||||||
|
"surfaceTint": "#6b96af"
|
||||||
|
},
|
||||||
|
"macchiato": {
|
||||||
|
"primary": "#7dc4e4",
|
||||||
|
"primaryText": "#24273a",
|
||||||
|
"primaryContainer": "#6396b1",
|
||||||
|
"secondary": "#5a7486",
|
||||||
|
"surfaceTint": "#6396b1"
|
||||||
|
},
|
||||||
|
"mocha": {
|
||||||
|
"primary": "#74c7ec",
|
||||||
|
"primaryText": "#1e1e2e",
|
||||||
|
"primaryContainer": "#5a95b4",
|
||||||
|
"secondary": "#567080",
|
||||||
|
"surfaceTint": "#5a95b4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "blue",
|
||||||
|
"name": "Blue",
|
||||||
|
"latte": {
|
||||||
|
"primary": "#1e66f5",
|
||||||
|
"primaryText": "#eff1f5",
|
||||||
|
"primaryContainer": "#5c90f5",
|
||||||
|
"secondary": "#b1bacb",
|
||||||
|
"surfaceTint": "#5c90f5"
|
||||||
|
},
|
||||||
|
"frappe": {
|
||||||
|
"primary": "#8caaee",
|
||||||
|
"primaryText": "#303446",
|
||||||
|
"primaryContainer": "#7086bc",
|
||||||
|
"secondary": "#637195",
|
||||||
|
"surfaceTint": "#7086bc"
|
||||||
|
},
|
||||||
|
"macchiato": {
|
||||||
|
"primary": "#8aadf4",
|
||||||
|
"primaryText": "#24273a",
|
||||||
|
"primaryContainer": "#6c85bc",
|
||||||
|
"secondary": "#5f6d8f",
|
||||||
|
"surfaceTint": "#6c85bc"
|
||||||
|
},
|
||||||
|
"mocha": {
|
||||||
|
"primary": "#89b4fa",
|
||||||
|
"primaryText": "#1e1e2e",
|
||||||
|
"primaryContainer": "#6987bd",
|
||||||
|
"secondary": "#5d6c8b",
|
||||||
|
"surfaceTint": "#6987bd"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "lavender",
|
||||||
|
"name": "Lavender",
|
||||||
|
"latte": {
|
||||||
|
"primary": "#7287fd",
|
||||||
|
"primaryText": "#eff1f5",
|
||||||
|
"primaryContainer": "#97a7fb",
|
||||||
|
"secondary": "#cdcfdd",
|
||||||
|
"surfaceTint": "#97a7fb"
|
||||||
|
},
|
||||||
|
"frappe": {
|
||||||
|
"primary": "#babbf1",
|
||||||
|
"primaryText": "#303446",
|
||||||
|
"primaryContainer": "#9192be",
|
||||||
|
"secondary": "#7175a1",
|
||||||
|
"surfaceTint": "#9192be"
|
||||||
|
},
|
||||||
|
"macchiato": {
|
||||||
|
"primary": "#b7bdf8",
|
||||||
|
"primaryText": "#24273a",
|
||||||
|
"primaryContainer": "#8b91bf",
|
||||||
|
"secondary": "#6b709d",
|
||||||
|
"surfaceTint": "#8b91bf"
|
||||||
|
},
|
||||||
|
"mocha": {
|
||||||
|
"primary": "#b4befe",
|
||||||
|
"primaryText": "#1e1e2e",
|
||||||
|
"primaryContainer": "#878ec0",
|
||||||
|
"secondary": "#676d99",
|
||||||
|
"surfaceTint": "#878ec0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,544 +0,0 @@
|
|||||||
_data = {
|
|
||||||
"id": "catppuccin",
|
|
||||||
"name": "Catppuccin",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"author": "Catppuccin Org",
|
|
||||||
"description": "Soothing pastel theme for the high-spirited!",
|
|
||||||
"dark": {},
|
|
||||||
"light": {},
|
|
||||||
"variants": {
|
|
||||||
"type": "multi",
|
|
||||||
"defaults": {
|
|
||||||
"dark": {"m3flavor": "mocha", "m3accent": "mauve"},
|
|
||||||
"light": {"m3flavor": "latte", "m3accent": "mauve"},
|
|
||||||
},
|
|
||||||
"flavors": [
|
|
||||||
{
|
|
||||||
"id": "latte",
|
|
||||||
"name": "Latte",
|
|
||||||
"light": {
|
|
||||||
"m3surface": "#ccd0da",
|
|
||||||
"m3surfaceText": "#4c4f69",
|
|
||||||
"m3surfaceVariant": "#eff1f5",
|
|
||||||
"m3surfaceVariantText": "#6c6f85",
|
|
||||||
"m3background": "#eff1f5",
|
|
||||||
"m3backgroundText": "#4c4f69",
|
|
||||||
"m3outline": "#9ca0b0",
|
|
||||||
"m3surfaceContainer": "#eff1f5",
|
|
||||||
"m3surfaceContainerHigh": "#e6e9ef",
|
|
||||||
"m3surfaceContainerHighest": "#dce0e8",
|
|
||||||
"m3error": "#d20f39",
|
|
||||||
"m3warning": "#fe640b",
|
|
||||||
"m3info": "#1e66f5",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "frappe",
|
|
||||||
"name": "Frappé",
|
|
||||||
"dark": {
|
|
||||||
"m3surface": "#414559",
|
|
||||||
"m3surfaceText": "#c6d0f5",
|
|
||||||
"m3surfaceVariant": "#303446",
|
|
||||||
"m3surfaceVariantText": "#a5adce",
|
|
||||||
"m3background": "#303446",
|
|
||||||
"m3backgroundText": "#c6d0f5",
|
|
||||||
"m3outline": "#737994",
|
|
||||||
"m3surfaceContainer": "#303446",
|
|
||||||
"m3surfaceContainerHigh": "#292c3c",
|
|
||||||
"m3surfaceContainerHighest": "#232634",
|
|
||||||
"m3error": "#e78284",
|
|
||||||
"m3warning": "#ef9f76",
|
|
||||||
"m3info": "#8caaee",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "macchiato",
|
|
||||||
"name": "Macchiato",
|
|
||||||
"dark": {
|
|
||||||
"m3surface": "#363a4f",
|
|
||||||
"m3surfaceText": "#cad3f5",
|
|
||||||
"m3surfaceVariant": "#24273a",
|
|
||||||
"m3surfaceVariantText": "#a5adcb",
|
|
||||||
"m3background": "#24273a",
|
|
||||||
"m3backgroundText": "#cad3f5",
|
|
||||||
"m3outline": "#6e738d",
|
|
||||||
"m3surfaceContainer": "#24273a",
|
|
||||||
"m3surfaceContainerHigh": "#1e2030",
|
|
||||||
"m3surfaceContainerHighest": "#181926",
|
|
||||||
"m3error": "#ed8796",
|
|
||||||
"m3warning": "#f5a97f",
|
|
||||||
"m3info": "#8aadf4",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "mocha",
|
|
||||||
"name": "Mocha",
|
|
||||||
"dark": {
|
|
||||||
"m3surface": "#313244",
|
|
||||||
"m3surfaceText": "#cdd6f4",
|
|
||||||
"m3surfaceVariant": "#1e1e2e",
|
|
||||||
"m3surfaceVariantText": "#a6adc8",
|
|
||||||
"m3background": "#1e1e2e",
|
|
||||||
"m3backgroundText": "#cdd6f4",
|
|
||||||
"m3outline": "#6c7086",
|
|
||||||
"m3surfaceContainer": "#1e1e2e",
|
|
||||||
"m3surfaceContainerHigh": "#181825",
|
|
||||||
"m3surfaceContainerHighest": "#11111b",
|
|
||||||
"m3error": "#f38ba8",
|
|
||||||
"m3warning": "#fab387",
|
|
||||||
"m3info": "#89b4fa",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"accents": [
|
|
||||||
{
|
|
||||||
"id": "rosewater",
|
|
||||||
"name": "Rosewater",
|
|
||||||
"latte": {
|
|
||||||
"m3primary": "#dc8a78",
|
|
||||||
"m3primaryText": "#eff1f5",
|
|
||||||
"m3primaryContainer": "#e1a99d",
|
|
||||||
"m3secondary": "#d8c7c4",
|
|
||||||
"m3surfaceTint": "#e1a99d",
|
|
||||||
},
|
|
||||||
"frappe": {
|
|
||||||
"m3primary": "#f2d5cf",
|
|
||||||
"m3primaryText": "#303446",
|
|
||||||
"m3primaryContainer": "#b8a5a6",
|
|
||||||
"m3secondary": "#a2748b",
|
|
||||||
"m3surfaceTint": "#b8a5a6",
|
|
||||||
},
|
|
||||||
"macchiato": {
|
|
||||||
"m3primary": "#f4dbd6",
|
|
||||||
"m3primaryText": "#24273a",
|
|
||||||
"m3primaryContainer": "#b6a6a7",
|
|
||||||
"m3secondary": "#9f6f8d",
|
|
||||||
"m3surfaceTint": "#b6a6a7",
|
|
||||||
},
|
|
||||||
"mocha": {
|
|
||||||
"m3primary": "#f5e0dc",
|
|
||||||
"m3primaryText": "#1e1e2e",
|
|
||||||
"m3primaryContainer": "#b5a6a8",
|
|
||||||
"m3secondary": "#9d6d87",
|
|
||||||
"m3surfaceTint": "#b5a6a8",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "flamingo",
|
|
||||||
"name": "Flamingo",
|
|
||||||
"latte": {
|
|
||||||
"m3primary": "#dd7878",
|
|
||||||
"m3primaryText": "#eff1f5",
|
|
||||||
"m3primaryContainer": "#e29c9d",
|
|
||||||
"m3secondary": "#d7c3c4",
|
|
||||||
"m3surfaceTint": "#e29c9d",
|
|
||||||
},
|
|
||||||
"frappe": {
|
|
||||||
"m3primary": "#eebebe",
|
|
||||||
"m3primaryText": "#303446",
|
|
||||||
"m3primaryContainer": "#b5949a",
|
|
||||||
"m3secondary": "#9d6b80",
|
|
||||||
"m3surfaceTint": "#b5949a",
|
|
||||||
},
|
|
||||||
"macchiato": {
|
|
||||||
"m3primary": "#f0c6c6",
|
|
||||||
"m3primaryText": "#24273a",
|
|
||||||
"m3primaryContainer": "#b3979c",
|
|
||||||
"m3secondary": "#996780",
|
|
||||||
"m3surfaceTint": "#b3979c",
|
|
||||||
},
|
|
||||||
"mocha": {
|
|
||||||
"m3primary": "#f2cdcd",
|
|
||||||
"m3primaryText": "#1e1e2e",
|
|
||||||
"m3primaryContainer": "#b3999e",
|
|
||||||
"m3secondary": "#98667c",
|
|
||||||
"m3surfaceTint": "#b3999e",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "pink",
|
|
||||||
"name": "Pink",
|
|
||||||
"latte": {
|
|
||||||
"m3primary": "#ea76cb",
|
|
||||||
"m3primaryText": "#eff1f5",
|
|
||||||
"m3primaryContainer": "#eb9bd7",
|
|
||||||
"m3secondary": "#d9c7d5",
|
|
||||||
"m3surfaceTint": "#eb9bd7",
|
|
||||||
},
|
|
||||||
"frappe": {
|
|
||||||
"m3primary": "#f4b8e4",
|
|
||||||
"m3primaryText": "#303446",
|
|
||||||
"m3primaryContainer": "#b990b5",
|
|
||||||
"m3secondary": "#996e9e",
|
|
||||||
"m3surfaceTint": "#b990b5",
|
|
||||||
},
|
|
||||||
"macchiato": {
|
|
||||||
"m3primary": "#f5bde6",
|
|
||||||
"m3primaryText": "#24273a",
|
|
||||||
"m3primaryContainer": "#b791b2",
|
|
||||||
"m3secondary": "#95689a",
|
|
||||||
"m3surfaceTint": "#b791b2",
|
|
||||||
},
|
|
||||||
"mocha": {
|
|
||||||
"m3primary": "#f5c2e7",
|
|
||||||
"m3primaryText": "#1e1e2e",
|
|
||||||
"m3primaryContainer": "#b591b0",
|
|
||||||
"m3secondary": "#966597",
|
|
||||||
"m3surfaceTint": "#b591b0",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "mauve",
|
|
||||||
"name": "Mauve",
|
|
||||||
"latte": {
|
|
||||||
"m3primary": "#8839ef",
|
|
||||||
"m3primaryText": "#eff1f5",
|
|
||||||
"m3primaryContainer": "#a670f1",
|
|
||||||
"m3secondary": "#c2b8d0",
|
|
||||||
"m3surfaceTint": "#a670f1",
|
|
||||||
},
|
|
||||||
"frappe": {
|
|
||||||
"m3primary": "#ca9ee6",
|
|
||||||
"m3primaryText": "#303446",
|
|
||||||
"m3primaryContainer": "#9c7eb6",
|
|
||||||
"m3secondary": "#7d6799",
|
|
||||||
"m3surfaceTint": "#9c7eb6",
|
|
||||||
},
|
|
||||||
"macchiato": {
|
|
||||||
"m3primary": "#c6a0f6",
|
|
||||||
"m3primaryText": "#24273a",
|
|
||||||
"m3primaryContainer": "#967cbe",
|
|
||||||
"m3secondary": "#766597",
|
|
||||||
"m3surfaceTint": "#967cbe",
|
|
||||||
},
|
|
||||||
"mocha": {
|
|
||||||
"m3primary": "#cba6f7",
|
|
||||||
"m3primaryText": "#1e1e2e",
|
|
||||||
"m3primaryContainer": "#977ebb",
|
|
||||||
"m3secondary": "#756294",
|
|
||||||
"m3surfaceTint": "#977ebb",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "red",
|
|
||||||
"name": "Red",
|
|
||||||
"latte": {
|
|
||||||
"m3primary": "#d20f39",
|
|
||||||
"m3primaryText": "#eff1f5",
|
|
||||||
"m3primaryContainer": "#da5371",
|
|
||||||
"m3secondary": "#c0a0a8",
|
|
||||||
"m3surfaceTint": "#da5371",
|
|
||||||
},
|
|
||||||
"frappe": {
|
|
||||||
"m3primary": "#e78284",
|
|
||||||
"m3primaryText": "#303446",
|
|
||||||
"m3primaryContainer": "#b06a72",
|
|
||||||
"m3secondary": "#8b5d66",
|
|
||||||
"m3surfaceTint": "#b06a72",
|
|
||||||
},
|
|
||||||
"macchiato": {
|
|
||||||
"m3primary": "#ed8796",
|
|
||||||
"m3primaryText": "#24273a",
|
|
||||||
"m3primaryContainer": "#b16b7a",
|
|
||||||
"m3secondary": "#865a69",
|
|
||||||
"m3surfaceTint": "#b16b7a",
|
|
||||||
},
|
|
||||||
"mocha": {
|
|
||||||
"m3primary": "#f38ba8",
|
|
||||||
"m3primaryText": "#1e1e2e",
|
|
||||||
"m3primaryContainer": "#b46b84",
|
|
||||||
"m3secondary": "#85596b",
|
|
||||||
"m3surfaceTint": "#b46b84",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "maroon",
|
|
||||||
"name": "Maroon",
|
|
||||||
"latte": {
|
|
||||||
"m3primary": "#e64553",
|
|
||||||
"m3primaryText": "#eff1f5",
|
|
||||||
"m3primaryContainer": "#e87883",
|
|
||||||
"m3secondary": "#cfb7ba",
|
|
||||||
"m3surfaceTint": "#e87883",
|
|
||||||
},
|
|
||||||
"frappe": {
|
|
||||||
"m3primary": "#ea999c",
|
|
||||||
"m3primaryText": "#303446",
|
|
||||||
"m3primaryContainer": "#b27a83",
|
|
||||||
"m3secondary": "#92626f",
|
|
||||||
"m3surfaceTint": "#b27a83",
|
|
||||||
},
|
|
||||||
"macchiato": {
|
|
||||||
"m3primary": "#ee99a0",
|
|
||||||
"m3primaryText": "#24273a",
|
|
||||||
"m3primaryContainer": "#b27781",
|
|
||||||
"m3secondary": "#8c5e6c",
|
|
||||||
"m3surfaceTint": "#b27781",
|
|
||||||
},
|
|
||||||
"mocha": {
|
|
||||||
"m3primary": "#eba0ac",
|
|
||||||
"m3primaryText": "#1e1e2e",
|
|
||||||
"m3primaryContainer": "#ae7987",
|
|
||||||
"m3secondary": "#895b6c",
|
|
||||||
"m3surfaceTint": "#ae7987",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "peach",
|
|
||||||
"name": "Peach",
|
|
||||||
"latte": {
|
|
||||||
"m3primary": "#fe640b",
|
|
||||||
"m3primaryText": "#eff1f5",
|
|
||||||
"m3primaryContainer": "#f98e51",
|
|
||||||
"m3secondary": "#c9b7ad",
|
|
||||||
"m3surfaceTint": "#f98e51",
|
|
||||||
},
|
|
||||||
"frappe": {
|
|
||||||
"m3primary": "#ef9f76",
|
|
||||||
"m3primaryText": "#303446",
|
|
||||||
"m3primaryContainer": "#b67f68",
|
|
||||||
"m3secondary": "#8f6a5f",
|
|
||||||
"m3surfaceTint": "#b67f68",
|
|
||||||
},
|
|
||||||
"macchiato": {
|
|
||||||
"m3primary": "#f5a97f",
|
|
||||||
"m3primaryText": "#24273a",
|
|
||||||
"m3primaryContainer": "#b7836a",
|
|
||||||
"m3secondary": "#8c695e",
|
|
||||||
"m3surfaceTint": "#b7836a",
|
|
||||||
},
|
|
||||||
"mocha": {
|
|
||||||
"m3primary": "#fab387",
|
|
||||||
"m3primaryText": "#1e1e2e",
|
|
||||||
"m3primaryContainer": "#b8876d",
|
|
||||||
"m3secondary": "#8b6a5d",
|
|
||||||
"m3surfaceTint": "#b8876d",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "yellow",
|
|
||||||
"name": "Yellow",
|
|
||||||
"latte": {
|
|
||||||
"m3primary": "#df8e1d",
|
|
||||||
"m3primaryText": "#eff1f5",
|
|
||||||
"m3primaryContainer": "#e4ac5d",
|
|
||||||
"m3secondary": "#c6baaa",
|
|
||||||
"m3surfaceTint": "#e4ac5d",
|
|
||||||
},
|
|
||||||
"frappe": {
|
|
||||||
"m3primary": "#e5c890",
|
|
||||||
"m3primaryText": "#303446",
|
|
||||||
"m3primaryContainer": "#af9b7a",
|
|
||||||
"m3secondary": "#948062",
|
|
||||||
"m3surfaceTint": "#af9b7a",
|
|
||||||
},
|
|
||||||
"macchiato": {
|
|
||||||
"m3primary": "#eed49f",
|
|
||||||
"m3primaryText": "#24273a",
|
|
||||||
"m3primaryContainer": "#b2a181",
|
|
||||||
"m3secondary": "#947e62",
|
|
||||||
"m3surfaceTint": "#b2a181",
|
|
||||||
},
|
|
||||||
"mocha": {
|
|
||||||
"m3primary": "#f9e2af",
|
|
||||||
"m3primaryText": "#1e1e2e",
|
|
||||||
"m3primaryContainer": "#b8a889",
|
|
||||||
"m3secondary": "#978265",
|
|
||||||
"m3surfaceTint": "#b8a889",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "green",
|
|
||||||
"name": "Green",
|
|
||||||
"latte": {
|
|
||||||
"m3primary": "#40a02b",
|
|
||||||
"m3primaryText": "#eff1f5",
|
|
||||||
"m3primaryContainer": "#74b867",
|
|
||||||
"m3secondary": "#9fbd9b",
|
|
||||||
"m3surfaceTint": "#74b867",
|
|
||||||
},
|
|
||||||
"frappe": {
|
|
||||||
"m3primary": "#a6d189",
|
|
||||||
"m3primaryText": "#303446",
|
|
||||||
"m3primaryContainer": "#83a275",
|
|
||||||
"m3secondary": "#648e5e",
|
|
||||||
"m3surfaceTint": "#83a275",
|
|
||||||
},
|
|
||||||
"macchiato": {
|
|
||||||
"m3primary": "#a6da95",
|
|
||||||
"m3primaryText": "#24273a",
|
|
||||||
"m3primaryContainer": "#80a57a",
|
|
||||||
"m3secondary": "#5c8a61",
|
|
||||||
"m3surfaceTint": "#80a57a",
|
|
||||||
},
|
|
||||||
"mocha": {
|
|
||||||
"m3primary": "#a6e3a1",
|
|
||||||
"m3primaryText": "#1e1e2e",
|
|
||||||
"m3primaryContainer": "#7ea87f",
|
|
||||||
"m3secondary": "#5b8964",
|
|
||||||
"m3surfaceTint": "#7ea87f",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "teal",
|
|
||||||
"name": "Teal",
|
|
||||||
"latte": {
|
|
||||||
"m3primary": "#179299",
|
|
||||||
"m3primaryText": "#eff1f5",
|
|
||||||
"m3primaryContainer": "#57aeb4",
|
|
||||||
"m3secondary": "#93b4b7",
|
|
||||||
"m3surfaceTint": "#57aeb4",
|
|
||||||
},
|
|
||||||
"frappe": {
|
|
||||||
"m3primary": "#81c8be",
|
|
||||||
"m3primaryText": "#303446",
|
|
||||||
"m3primaryContainer": "#699b9a",
|
|
||||||
"m3secondary": "#588084",
|
|
||||||
"m3surfaceTint": "#699b9a",
|
|
||||||
},
|
|
||||||
"macchiato": {
|
|
||||||
"m3primary": "#8bd5ca",
|
|
||||||
"m3primaryText": "#24273a",
|
|
||||||
"m3primaryContainer": "#6da29f",
|
|
||||||
"m3secondary": "#577e83",
|
|
||||||
"m3surfaceTint": "#6da29f",
|
|
||||||
},
|
|
||||||
"mocha": {
|
|
||||||
"m3primary": "#94e2d5",
|
|
||||||
"m3primaryText": "#1e1e2e",
|
|
||||||
"m3primaryContainer": "#71a8a4",
|
|
||||||
"m3secondary": "#588284",
|
|
||||||
"m3surfaceTint": "#71a8a4",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "sky",
|
|
||||||
"name": "Sky",
|
|
||||||
"latte": {
|
|
||||||
"m3primary": "#04a5e5",
|
|
||||||
"m3primaryText": "#eff1f5",
|
|
||||||
"m3primaryContainer": "#4abcea",
|
|
||||||
"m3secondary": "#a4b9c2",
|
|
||||||
"m3surfaceTint": "#4abcea",
|
|
||||||
},
|
|
||||||
"frappe": {
|
|
||||||
"m3primary": "#99d1db",
|
|
||||||
"m3primaryText": "#303446",
|
|
||||||
"m3primaryContainer": "#79a2af",
|
|
||||||
"m3secondary": "#628494",
|
|
||||||
"m3surfaceTint": "#79a2af",
|
|
||||||
},
|
|
||||||
"macchiato": {
|
|
||||||
"m3primary": "#91d7e3",
|
|
||||||
"m3primaryText": "#24273a",
|
|
||||||
"m3primaryContainer": "#71a3b0",
|
|
||||||
"m3secondary": "#5e7e8c",
|
|
||||||
"m3surfaceTint": "#71a3b0",
|
|
||||||
},
|
|
||||||
"mocha": {
|
|
||||||
"m3primary": "#89dceb",
|
|
||||||
"m3primaryText": "#1e1e2e",
|
|
||||||
"m3primaryContainer": "#69a3b3",
|
|
||||||
"m3secondary": "#5a7b88",
|
|
||||||
"m3surfaceTint": "#69a3b3",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "sapphire",
|
|
||||||
"name": "Sapphire",
|
|
||||||
"latte": {
|
|
||||||
"m3primary": "#209fb5",
|
|
||||||
"m3primaryText": "#eff1f5",
|
|
||||||
"m3primaryContainer": "#5db8c8",
|
|
||||||
"m3secondary": "#9eb9be",
|
|
||||||
"m3surfaceTint": "#5db8c8",
|
|
||||||
},
|
|
||||||
"frappe": {
|
|
||||||
"m3primary": "#85c1dc",
|
|
||||||
"m3primaryText": "#303446",
|
|
||||||
"m3primaryContainer": "#6b96af",
|
|
||||||
"m3secondary": "#5e7b8e",
|
|
||||||
"m3surfaceTint": "#6b96af",
|
|
||||||
},
|
|
||||||
"macchiato": {
|
|
||||||
"m3primary": "#7dc4e4",
|
|
||||||
"m3primaryText": "#24273a",
|
|
||||||
"m3primaryContainer": "#6396b1",
|
|
||||||
"m3secondary": "#5a7486",
|
|
||||||
"m3surfaceTint": "#6396b1",
|
|
||||||
},
|
|
||||||
"mocha": {
|
|
||||||
"m3primary": "#74c7ec",
|
|
||||||
"m3primaryText": "#1e1e2e",
|
|
||||||
"m3primaryContainer": "#5a95b4",
|
|
||||||
"m3secondary": "#567080",
|
|
||||||
"m3surfaceTint": "#5a95b4",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "blue",
|
|
||||||
"name": "Blue",
|
|
||||||
"latte": {
|
|
||||||
"m3primary": "#1e66f5",
|
|
||||||
"m3primaryText": "#eff1f5",
|
|
||||||
"m3primaryContainer": "#5c90f5",
|
|
||||||
"m3secondary": "#b1bacb",
|
|
||||||
"m3surfaceTint": "#5c90f5",
|
|
||||||
},
|
|
||||||
"frappe": {
|
|
||||||
"m3primary": "#8caaee",
|
|
||||||
"m3primaryText": "#303446",
|
|
||||||
"m3primaryContainer": "#7086bc",
|
|
||||||
"m3secondary": "#637195",
|
|
||||||
"m3surfaceTint": "#7086bc",
|
|
||||||
},
|
|
||||||
"macchiato": {
|
|
||||||
"m3primary": "#8aadf4",
|
|
||||||
"m3primaryText": "#24273a",
|
|
||||||
"m3primaryContainer": "#6c85bc",
|
|
||||||
"m3secondary": "#5f6d8f",
|
|
||||||
"m3surfaceTint": "#6c85bc",
|
|
||||||
},
|
|
||||||
"mocha": {
|
|
||||||
"m3primary": "#89b4fa",
|
|
||||||
"m3primaryText": "#1e1e2e",
|
|
||||||
"m3primaryContainer": "#6987bd",
|
|
||||||
"m3secondary": "#5d6c8b",
|
|
||||||
"m3surfaceTint": "#6987bd",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "lavender",
|
|
||||||
"name": "Lavender",
|
|
||||||
"latte": {
|
|
||||||
"m3primary": "#7287fd",
|
|
||||||
"m3primaryText": "#eff1f5",
|
|
||||||
"m3primaryContainer": "#97a7fb",
|
|
||||||
"m3secondary": "#cdcfdd",
|
|
||||||
"m3surfaceTint": "#97a7fb",
|
|
||||||
},
|
|
||||||
"frappe": {
|
|
||||||
"m3primary": "#babbf1",
|
|
||||||
"m3primaryText": "#303446",
|
|
||||||
"m3primaryContainer": "#9192be",
|
|
||||||
"m3secondary": "#7175a1",
|
|
||||||
"m3surfaceTint": "#9192be",
|
|
||||||
},
|
|
||||||
"macchiato": {
|
|
||||||
"m3primary": "#b7bdf8",
|
|
||||||
"m3primaryText": "#24273a",
|
|
||||||
"m3primaryContainer": "#8b91bf",
|
|
||||||
"m3secondary": "#6b709d",
|
|
||||||
"m3surfaceTint": "#8b91bf",
|
|
||||||
},
|
|
||||||
"mocha": {
|
|
||||||
"m3primary": "#b4befe",
|
|
||||||
"m3primaryText": "#1e1e2e",
|
|
||||||
"m3primaryContainer": "#878ec0",
|
|
||||||
"m3secondary": "#676d99",
|
|
||||||
"m3surfaceTint": "#878ec0",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,13 +1,62 @@
|
|||||||
# import json
|
from __future__ import annotations
|
||||||
# import typer
|
|
||||||
# from zshell.assets.schemes.catppuccin import catppuccin
|
|
||||||
#
|
|
||||||
# app = typer.Typer()
|
|
||||||
#
|
|
||||||
# SCHEMES = catppuccin.variants.flavors
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# @app.command()
|
|
||||||
# def set():
|
|
||||||
|
|
||||||
# TODO: Currently unsused
|
import json
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import typer
|
||||||
|
|
||||||
|
from zshell.utils.presets import build_palette, list_presets, load_preset_file
|
||||||
|
|
||||||
|
app = typer.Typer()
|
||||||
|
OUTPUT = Path(os.getenv("HOME", "")) / ".local/state/zshell/scheme.json"
|
||||||
|
|
||||||
|
|
||||||
|
def _split_preset(value: str) -> tuple[str, str | None, str | None]:
|
||||||
|
parts = value.split(":")
|
||||||
|
if len(parts) == 1:
|
||||||
|
return parts[0], None, None
|
||||||
|
if len(parts) == 3:
|
||||||
|
return parts[0], parts[1], parts[2]
|
||||||
|
raise typer.BadParameter("Preset must be <name> or <name>:<flavor>:<accent>")
|
||||||
|
|
||||||
|
|
||||||
|
@app.command()
|
||||||
|
def list():
|
||||||
|
for preset_name in list_presets():
|
||||||
|
data = load_preset_file(preset_name)
|
||||||
|
flavors = [item["id"] for item in data["variants"]["flavors"]]
|
||||||
|
accents = [item["id"] for item in data["variants"]["accents"]]
|
||||||
|
for flavor in flavors:
|
||||||
|
for accent in accents:
|
||||||
|
typer.echo(f"{preset_name}:{flavor}:{accent}")
|
||||||
|
|
||||||
|
|
||||||
|
@app.command()
|
||||||
|
def set(
|
||||||
|
preset: str = typer.Argument(
|
||||||
|
..., help="Preset in form <name> or <name>:<flavor>:<accent>"
|
||||||
|
),
|
||||||
|
mode: str = typer.Option("dark", help="Mode for preset colors."),
|
||||||
|
):
|
||||||
|
name, flavor, accent = _split_preset(preset)
|
||||||
|
data = load_preset_file(name)
|
||||||
|
|
||||||
|
if flavor is None or accent is None:
|
||||||
|
defaults = data["variants"]["defaults"][mode]
|
||||||
|
flavor = defaults["flavor"]
|
||||||
|
accent = defaults["accent"]
|
||||||
|
|
||||||
|
palette = build_palette(data, flavor, accent, mode)
|
||||||
|
out = {
|
||||||
|
"name": palette.name,
|
||||||
|
"flavor": f"{palette.flavor}:{palette.accent}",
|
||||||
|
"mode": palette.mode,
|
||||||
|
"variant": name,
|
||||||
|
"colors": dict(palette.colors),
|
||||||
|
"seed": int(palette.colors["primary"].lstrip("#"), 16),
|
||||||
|
}
|
||||||
|
|
||||||
|
OUTPUT.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
OUTPUT.write_text(json.dumps(out, indent=4), encoding="utf-8")
|
||||||
|
typer.echo(f"applied: {name}:{flavor}:{accent}")
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user