Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 33746fca04 | |||
| 853b683962 | |||
| b1bfcb3ed0 | |||
| 68662120ba | |||
| b8af60008d | |||
| b8524ff621 | |||
| ffde4063a0 | |||
| 053efb4aaf | |||
| c88aef2164 | |||
| 01b54ec5e1 | |||
| 7276ee28dc | |||
| a14ebe2016 | |||
| d3f6765819 | |||
| a3d0ee18cb | |||
| c9d6b95ca5 | |||
| 794a26a3fe | |||
| ca3a288eab | |||
| 902863e5ba | |||
| dd49198cf7 |
@@ -1,26 +0,0 @@
|
|||||||
name: Format (JS/TS)
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
format:
|
|
||||||
runs-on: alpine
|
|
||||||
container: node:20-alpine
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install tools
|
|
||||||
run: |
|
|
||||||
apk add --no-cache \
|
|
||||||
git
|
|
||||||
|
|
||||||
- name: Prettier
|
|
||||||
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 .gitignore
|
|
||||||
else
|
|
||||||
echo "No JS/TS files found"
|
|
||||||
fi
|
|
||||||
@@ -1,33 +1,42 @@
|
|||||||
name: Lint (JS/TS)
|
name: Lint & Format (JS/TS)
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint:
|
lint-format:
|
||||||
runs-on: alpine
|
runs-on: alpine
|
||||||
container: node:20-alpine
|
container: node:26-alpine
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install tools
|
- name: Install tools
|
||||||
run: |
|
run: |
|
||||||
apk add --no-cache \
|
apk add --no-cache \
|
||||||
git
|
git
|
||||||
|
|
||||||
- name: ESLint
|
- name: Prettier
|
||||||
run: |
|
continue-on-error: true
|
||||||
if [ -n "$(find . \( -iname "*.js" -o -iname "*.jsx" -o -iname "*.ts" -o -iname "*.tsx" -o -iname "*.mjs" -o -iname "*.cjs" \) -print -quit)" ]; then
|
run: |
|
||||||
if [ -f package.json ]; then
|
if [ -n "$(find . \( -iname "*.js" -o -iname "*.jsx" -o -iname "*.ts" -o -iname "*.tsx" -o -iname "*.mjs" -o -iname "*.cjs" \) -print -quit)" ]; then
|
||||||
npm install --no-audit --no-fund
|
npx --yes prettier --check "**/*.{js,jsx,ts,tsx,mjs,cjs}" --ignore-path .prettierignore
|
||||||
fi
|
else
|
||||||
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
|
echo "No JS/TS files found"
|
||||||
npx --yes eslint .
|
fi
|
||||||
else
|
|
||||||
echo "No eslint config found"
|
- name: ESLint
|
||||||
fi
|
run: |
|
||||||
else
|
if [ -n "$(find . \( -iname "*.js" -o -iname "*.jsx" -o -iname "*.ts" -o -iname "*.tsx" -o -iname "*.mjs" -o -iname "*.cjs" \) -print -quit)" ]; then
|
||||||
echo "No JS/TS files found"
|
if [ -f package.json ]; then
|
||||||
fi
|
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,27 +1,34 @@
|
|||||||
name: Lint (Python)
|
name: Lint & Format (Python)
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint:
|
lint-format:
|
||||||
runs-on: alpine
|
runs-on: alpine
|
||||||
container: node:20-alpine
|
container: node:26-alpine
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install tools
|
- name: Install tools
|
||||||
run: |
|
run: |
|
||||||
apk add --no-cache \
|
apk add --no-cache \
|
||||||
git \
|
git \
|
||||||
python3 \
|
python3 \
|
||||||
py3-pip
|
py3-pip
|
||||||
|
python3 -m venv .venv
|
||||||
|
. .venv/bin/activate
|
||||||
|
pip install --no-cache-dir ruff
|
||||||
|
|
||||||
- name: Ruff
|
- name: Format check
|
||||||
run: |
|
continue-on-error: true
|
||||||
python3 -m venv .venv
|
run: |
|
||||||
. .venv/bin/activate
|
. .venv/bin/activate
|
||||||
pip install --no-cache-dir ruff
|
ruff format --check .
|
||||||
ruff check .
|
|
||||||
|
- name: Lint
|
||||||
|
run: |
|
||||||
|
. .venv/bin/activate
|
||||||
|
ruff check .
|
||||||
|
|||||||
@@ -1,34 +1,72 @@
|
|||||||
name: Lint (Rust)
|
name: Lint & Format (Rust)
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint:
|
lint-format:
|
||||||
runs-on: alpine
|
runs-on: alpine
|
||||||
container: node:20-alpine
|
container: node:26-alpine
|
||||||
|
env:
|
||||||
|
CARGO_HOME: ${{ github.workspace }}/.cargo
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install tools
|
- name: Cache cargo packages
|
||||||
run: |
|
uses: actions/cache@v4
|
||||||
apk add --no-cache \
|
env:
|
||||||
git \
|
cache-name: cache-cargo-packages
|
||||||
cargo \
|
with:
|
||||||
rust \
|
path: |
|
||||||
rust-clippy
|
.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: Clippy
|
- name: Install tools
|
||||||
run: |
|
run: |
|
||||||
if [ -n "$(find . -name "Cargo.toml" -print -quit)" ]; then
|
apk add --no-cache \
|
||||||
find . -name "Cargo.toml" -print0 | while IFS= read -r -d '' manifest; do
|
git \
|
||||||
cargo clippy --manifest-path "$manifest" -- -D warnings
|
cargo \
|
||||||
done
|
rust \
|
||||||
elif [ -n "$(find . -name "*.rs" -print -quit)" ]; then
|
rustfmt \
|
||||||
echo "Rust files found but no Cargo.toml"
|
rust-clippy
|
||||||
exit 1
|
|
||||||
else
|
- name: Format check
|
||||||
echo "No Rust project found"
|
continue-on-error: true
|
||||||
fi
|
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
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
.venv/
|
||||||
|
scripts/fzf.js
|
||||||
|
scripts/fuzzysort.js
|
||||||
@@ -80,10 +80,32 @@ Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function reloadHyprRules(): void {
|
function reloadHyprRules(): void {
|
||||||
const barStr = Hyprland.usingLua ? `eval 'hl.layer_rule({ match = { namespace = "ZShell-Bar" }, %1 = true, %2 = true })'` : "keyword layerrule %1 %2, match:namespace ZShell-Bar";
|
const blur = transparency.enabled ? 1 : 0;
|
||||||
const authStr = Hyprland.usingLua ? `eval 'hl.layer_rule({ match = { namespace = "ZShell-Auth" }, %1 = true, %2 = true })'` : "keyword layerrule %1 %2, match:namespace ZShell-Auth";
|
const alpha = transparency.base - 0.03;
|
||||||
Hypr.extras.batchMessage([barStr.arg("blur").arg(transparency.enabled ? 1 : 0), barStr.arg("ignore_alpha").arg(transparency.base - 0.03)]);
|
|
||||||
Hypr.extras.batchMessage([authStr.arg("blur").arg(transparency.enabled ? 1 : 0), authStr.arg("ignore_alpha").arg(transparency.base - 0.03)]);
|
const rules = `
|
||||||
|
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 {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ 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 {
|
||||||
@@ -37,6 +38,7 @@ Item {
|
|||||||
readonly property alias settingsWrapper: settingsWrapper
|
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
|
||||||
|
|
||||||
@@ -93,6 +95,79 @@ 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
|
||||||
|
|
||||||
|
|||||||
+35
-7
@@ -64,7 +64,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
|
regions: [...popoutRegions.instances, ...subMenuRegions.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,6 +93,22 @@ 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
|
||||||
|
|
||||||
@@ -182,7 +198,7 @@ Variants {
|
|||||||
|
|
||||||
property real extraHeight: 0.2
|
property real extraHeight: 0.2
|
||||||
|
|
||||||
deformAmount: 0.08
|
deformAmount: 0.06
|
||||||
implicitHeight: panels.dashboard.height * (1 + extraHeight)
|
implicitHeight: panels.dashboard.height * (1 + extraHeight)
|
||||||
implicitWidth: panels.dashboard.width
|
implicitWidth: panels.dashboard.width
|
||||||
panel: panels.dashboardWrapper
|
panel: panels.dashboardWrapper
|
||||||
@@ -196,7 +212,7 @@ Variants {
|
|||||||
|
|
||||||
property real extraHeight: 0.2
|
property real extraHeight: 0.2
|
||||||
|
|
||||||
deformAmount: 0.08
|
deformAmount: 0.06
|
||||||
implicitHeight: panels.launcher.height * (1 + extraHeight)
|
implicitHeight: panels.launcher.height * (1 + extraHeight)
|
||||||
panel: panels.launcher
|
panel: panels.launcher
|
||||||
radius: Appearance.rounding.smallest + 5
|
radius: Appearance.rounding.smallest + 5
|
||||||
@@ -207,7 +223,7 @@ Variants {
|
|||||||
id: sidebarBg
|
id: sidebarBg
|
||||||
|
|
||||||
bottomLeftRadius: 0
|
bottomLeftRadius: 0
|
||||||
deformAmount: 0.08
|
deformAmount: 0.04
|
||||||
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
|
||||||
@@ -262,7 +278,7 @@ Variants {
|
|||||||
PanelBg {
|
PanelBg {
|
||||||
id: resourcesBg
|
id: resourcesBg
|
||||||
|
|
||||||
deformAmount: 0.08
|
deformAmount: 0.05
|
||||||
implicitHeight: panels.resources.height
|
implicitHeight: panels.resources.height
|
||||||
implicitWidth: panels.resources.width
|
implicitWidth: panels.resources.width
|
||||||
panel: panels.resourcesWrapper
|
panel: panels.resourcesWrapper
|
||||||
@@ -276,10 +292,10 @@ Variants {
|
|||||||
|
|
||||||
property real extraHeight: 0.2
|
property real extraHeight: 0.2
|
||||||
|
|
||||||
deformAmount: 0.08
|
deformAmount: 0.03
|
||||||
implicitHeight: panels.settings.height * (1 + extraHeight)
|
implicitHeight: panels.settings.height * (1 + extraHeight)
|
||||||
implicitWidth: panels.settings.width
|
implicitWidth: panels.settings.width
|
||||||
panel: panels.settingsWrapper
|
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
|
||||||
@@ -302,6 +318,18 @@ Variants {
|
|||||||
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 {
|
||||||
|
|||||||
@@ -13,11 +13,11 @@ Singleton {
|
|||||||
|
|
||||||
function setHyprConf(): void {
|
function setHyprConf(): void {
|
||||||
Hypr.extras.applyOptions({
|
Hypr.extras.applyOptions({
|
||||||
"animations:enabled": 0,
|
"animations.enabled": 0,
|
||||||
"decoration:shadow:enabled": 0,
|
"decoration.shadow.enabled": 0,
|
||||||
"decoration:blur:enabled": 0,
|
"decoration.blur.enabled": 0,
|
||||||
"general:border_size": 0,
|
"general.border_size": 0,
|
||||||
"decoration:rounding": 0
|
"decoration.rounding": 0
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ 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
|
||||||
@@ -63,6 +64,7 @@ Item {
|
|||||||
|
|
||||||
TrayMenuPopout {
|
TrayMenuPopout {
|
||||||
popouts: root.popouts
|
popouts: root.popouts
|
||||||
|
screen: root.screen
|
||||||
trayItem: trayMenu.modelData.menu
|
trayItem: trayMenu.modelData.menu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,36 @@
|
|||||||
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,158 @@
|
|||||||
|
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,251 +1,16 @@
|
|||||||
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
|
||||||
|
|
||||||
StackView {
|
SubMenu {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property int biggestWidth: 0
|
handle: trayItem
|
||||||
required property PopoutState popouts
|
level: 0
|
||||||
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 int index
|
|
||||||
required property QsMenuEntry modelData
|
|
||||||
|
|
||||||
color: modelData.isSeparator ? DynamicColors.palette.m3outlineVariant : "transparent"
|
|
||||||
implicitHeight: modelData.isSeparator ? 1 : children.implicitHeight
|
|
||||||
implicitWidth: root.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) {
|
|
||||||
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: 30
|
|
||||||
implicitWidth: back.implicitWidth
|
|
||||||
|
|
||||||
Item {
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
implicitHeight: 30
|
|
||||||
implicitWidth: root.biggestWidth
|
|
||||||
|
|
||||||
CustomRect {
|
|
||||||
anchors.fill: parent
|
|
||||||
color: DynamicColors.palette.m3secondaryContainer
|
|
||||||
radius: Appearance.rounding.full
|
|
||||||
|
|
||||||
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")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+3
-1
@@ -15,13 +15,14 @@ Item {
|
|||||||
property real currentCenter
|
property real currentCenter
|
||||||
property alias currentName: popoutState.currentName
|
property alias currentName: popoutState.currentName
|
||||||
property string detachedMode
|
property string detachedMode
|
||||||
readonly property bool isDetached: detachedMode.length > 0
|
|
||||||
property alias hasCurrent: popoutState.hasCurrent
|
property alias hasCurrent: popoutState.hasCurrent
|
||||||
|
readonly property bool isDetached: detachedMode.length > 0
|
||||||
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;
|
||||||
@@ -79,6 +80,7 @@ Item {
|
|||||||
|
|
||||||
sourceComponent: Content {
|
sourceComponent: Content {
|
||||||
popouts: popoutState
|
popouts: popoutState
|
||||||
|
screen: root.screen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,12 +5,166 @@
|
|||||||
#include <qjsonarray.h>
|
#include <qjsonarray.h>
|
||||||
#include <qlocalsocket.h>
|
#include <qlocalsocket.h>
|
||||||
#include <qloggingcategory.h>
|
#include <qloggingcategory.h>
|
||||||
|
#include <qmetatype.h>
|
||||||
|
#include <qregularexpression.h>
|
||||||
#include <qvariant.h>
|
#include <qvariant.h>
|
||||||
|
|
||||||
Q_LOGGING_CATEGORY(lcHypr, "ZShell.internal.hypr", QtInfoMsg)
|
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("")
|
||||||
@@ -26,7 +180,7 @@ HyprExtras::HyprExtras(QObject* parent)
|
|||||||
|
|
||||||
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 = "/tmp/hypr/" + his;
|
hyprDir = QStringLiteral("/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.";
|
qCWarning(lcHypr) << "Hyprland socket directory does not exist. Unable to connect to Hyprland socket.";
|
||||||
@@ -34,8 +188,8 @@ HyprExtras::HyprExtras(QObject* parent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_requestSocket = hyprDir + "/.socket.sock";
|
m_requestSocket = hyprDir + QStringLiteral("/.socket.sock");
|
||||||
m_eventSocket = hyprDir + "/.socket2.sock";
|
m_eventSocket = hyprDir + QStringLiteral("/.socket2.sock");
|
||||||
|
|
||||||
refreshOptions();
|
refreshOptions();
|
||||||
refreshDevices();
|
refreshDevices();
|
||||||
@@ -74,7 +228,8 @@ void HyprExtras::batchMessage(const QStringList& messages) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
makeRequest("[[BATCH]]" + messages.join(";"), [](bool success, const QByteArray& res) {
|
makeRequest(QStringLiteral("[[BATCH]]") + messages.join(QLatin1Char(';')),
|
||||||
|
[](bool success, const QByteArray& res) {
|
||||||
if (!success) {
|
if (!success) {
|
||||||
qCWarning(lcHypr) << "batchMessage: request error:" << QString::fromUtf8(res);
|
qCWarning(lcHypr) << "batchMessage: request error:" << QString::fromUtf8(res);
|
||||||
}
|
}
|
||||||
@@ -86,14 +241,21 @@ void HyprExtras::applyOptions(const QVariantHash& options) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString request;
|
QStringList calls;
|
||||||
request.reserve(12 + options.size() * 40);
|
calls.reserve(options.size());
|
||||||
request += QLatin1String("[[BATCH]]");
|
|
||||||
for (auto it = options.constBegin(); it != options.constEnd(); ++it) {
|
for (auto it = options.constBegin(); it != options.constEnd(); ++it) {
|
||||||
request += QLatin1String("keyword ") + it.key() + QLatin1Char(' ') + it.value().toString() + QLatin1Char(';');
|
const auto call = buildHlConfigCall(it.key(), it.value());
|
||||||
|
if (!call.isEmpty()) {
|
||||||
|
calls << call;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
makeRequest(request, [this](bool success, const QByteArray& res) {
|
if (calls.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
makeRequest(QStringLiteral("eval ") + calls.join(QLatin1String("; ")), [this](bool success, const QByteArray& res) {
|
||||||
if (success) {
|
if (success) {
|
||||||
refreshOptions();
|
refreshOptions();
|
||||||
} else {
|
} else {
|
||||||
@@ -107,7 +269,7 @@ void HyprExtras::refreshOptions() {
|
|||||||
m_optionsRefresh->close();
|
m_optionsRefresh->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_optionsRefresh = makeRequestJson("descriptions", [this](bool success, const QJsonDocument& response) {
|
m_optionsRefresh = makeRequestJson(QStringLiteral("descriptions"), [this](bool success, const QJsonDocument& response) {
|
||||||
m_optionsRefresh.reset();
|
m_optionsRefresh.reset();
|
||||||
if (!success) {
|
if (!success) {
|
||||||
return;
|
return;
|
||||||
@@ -118,8 +280,9 @@ void HyprExtras::refreshOptions() {
|
|||||||
|
|
||||||
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("value").toString();
|
const auto key = obj.value(QStringLiteral("value")).toString();
|
||||||
const auto value = obj.value("data").toObject().value("current").toVariant();
|
const auto value = obj.value(QStringLiteral("data")).toObject().value(QStringLiteral("current")).toVariant();
|
||||||
|
|
||||||
if (m_options.value(key) != value) {
|
if (m_options.value(key) != value) {
|
||||||
dirty = true;
|
dirty = true;
|
||||||
m_options.insert(key, value);
|
m_options.insert(key, value);
|
||||||
@@ -137,7 +300,7 @@ void HyprExtras::refreshDevices() {
|
|||||||
m_devicesRefresh->close();
|
m_devicesRefresh->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_devicesRefresh = makeRequestJson("devices", [this](bool success, const QJsonDocument& response) {
|
m_devicesRefresh = makeRequestJson(QStringLiteral("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());
|
||||||
@@ -167,23 +330,23 @@ void HyprExtras::readEvent() {
|
|||||||
if (rawEvent.isEmpty()) {
|
if (rawEvent.isEmpty()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
rawEvent.truncate(rawEvent.length() - 1); // Remove trailing \n
|
rawEvent.truncate(rawEvent.length() - 1);
|
||||||
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 == "configreloaded") {
|
if (event == QStringLiteral("configreloaded")) {
|
||||||
refreshOptions();
|
refreshOptions();
|
||||||
} else if (event == "activelayout") {
|
} else if (event == QStringLiteral("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("j/" + request, [callback](bool success, const QByteArray& response) {
|
return makeRequest(QStringLiteral("j/") + request, [callback](bool success, const QByteArray& response) {
|
||||||
callback(success, QJsonDocument::fromJson(response));
|
callback(success, QJsonDocument::fromJson(response));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,14 +9,8 @@ _data = {
|
|||||||
"variants": {
|
"variants": {
|
||||||
"type": "multi",
|
"type": "multi",
|
||||||
"defaults": {
|
"defaults": {
|
||||||
"dark": {
|
"dark": {"m3flavor": "mocha", "m3accent": "mauve"},
|
||||||
"m3flavor": "mocha",
|
"light": {"m3flavor": "latte", "m3accent": "mauve"},
|
||||||
"m3accent": "mauve"
|
|
||||||
},
|
|
||||||
"light": {
|
|
||||||
"m3flavor": "latte",
|
|
||||||
"m3accent": "mauve"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"flavors": [
|
"flavors": [
|
||||||
{
|
{
|
||||||
@@ -35,8 +29,8 @@ _data = {
|
|||||||
"m3surfaceContainerHighest": "#dce0e8",
|
"m3surfaceContainerHighest": "#dce0e8",
|
||||||
"m3error": "#d20f39",
|
"m3error": "#d20f39",
|
||||||
"m3warning": "#fe640b",
|
"m3warning": "#fe640b",
|
||||||
"m3info": "#1e66f5"
|
"m3info": "#1e66f5",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "frappe",
|
"id": "frappe",
|
||||||
@@ -54,8 +48,8 @@ _data = {
|
|||||||
"m3surfaceContainerHighest": "#232634",
|
"m3surfaceContainerHighest": "#232634",
|
||||||
"m3error": "#e78284",
|
"m3error": "#e78284",
|
||||||
"m3warning": "#ef9f76",
|
"m3warning": "#ef9f76",
|
||||||
"m3info": "#8caaee"
|
"m3info": "#8caaee",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "macchiato",
|
"id": "macchiato",
|
||||||
@@ -73,8 +67,8 @@ _data = {
|
|||||||
"m3surfaceContainerHighest": "#181926",
|
"m3surfaceContainerHighest": "#181926",
|
||||||
"m3error": "#ed8796",
|
"m3error": "#ed8796",
|
||||||
"m3warning": "#f5a97f",
|
"m3warning": "#f5a97f",
|
||||||
"m3info": "#8aadf4"
|
"m3info": "#8aadf4",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "mocha",
|
"id": "mocha",
|
||||||
@@ -92,9 +86,9 @@ _data = {
|
|||||||
"m3surfaceContainerHighest": "#11111b",
|
"m3surfaceContainerHighest": "#11111b",
|
||||||
"m3error": "#f38ba8",
|
"m3error": "#f38ba8",
|
||||||
"m3warning": "#fab387",
|
"m3warning": "#fab387",
|
||||||
"m3info": "#89b4fa"
|
"m3info": "#89b4fa",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
"accents": [
|
"accents": [
|
||||||
{
|
{
|
||||||
@@ -105,29 +99,29 @@ _data = {
|
|||||||
"m3primaryText": "#eff1f5",
|
"m3primaryText": "#eff1f5",
|
||||||
"m3primaryContainer": "#e1a99d",
|
"m3primaryContainer": "#e1a99d",
|
||||||
"m3secondary": "#d8c7c4",
|
"m3secondary": "#d8c7c4",
|
||||||
"m3surfaceTint": "#e1a99d"
|
"m3surfaceTint": "#e1a99d",
|
||||||
},
|
},
|
||||||
"frappe": {
|
"frappe": {
|
||||||
"m3primary": "#f2d5cf",
|
"m3primary": "#f2d5cf",
|
||||||
"m3primaryText": "#303446",
|
"m3primaryText": "#303446",
|
||||||
"m3primaryContainer": "#b8a5a6",
|
"m3primaryContainer": "#b8a5a6",
|
||||||
"m3secondary": "#a2748b",
|
"m3secondary": "#a2748b",
|
||||||
"m3surfaceTint": "#b8a5a6"
|
"m3surfaceTint": "#b8a5a6",
|
||||||
},
|
},
|
||||||
"macchiato": {
|
"macchiato": {
|
||||||
"m3primary": "#f4dbd6",
|
"m3primary": "#f4dbd6",
|
||||||
"m3primaryText": "#24273a",
|
"m3primaryText": "#24273a",
|
||||||
"m3primaryContainer": "#b6a6a7",
|
"m3primaryContainer": "#b6a6a7",
|
||||||
"m3secondary": "#9f6f8d",
|
"m3secondary": "#9f6f8d",
|
||||||
"m3surfaceTint": "#b6a6a7"
|
"m3surfaceTint": "#b6a6a7",
|
||||||
},
|
},
|
||||||
"mocha": {
|
"mocha": {
|
||||||
"m3primary": "#f5e0dc",
|
"m3primary": "#f5e0dc",
|
||||||
"m3primaryText": "#1e1e2e",
|
"m3primaryText": "#1e1e2e",
|
||||||
"m3primaryContainer": "#b5a6a8",
|
"m3primaryContainer": "#b5a6a8",
|
||||||
"m3secondary": "#9d6d87",
|
"m3secondary": "#9d6d87",
|
||||||
"m3surfaceTint": "#b5a6a8"
|
"m3surfaceTint": "#b5a6a8",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "flamingo",
|
"id": "flamingo",
|
||||||
@@ -137,29 +131,29 @@ _data = {
|
|||||||
"m3primaryText": "#eff1f5",
|
"m3primaryText": "#eff1f5",
|
||||||
"m3primaryContainer": "#e29c9d",
|
"m3primaryContainer": "#e29c9d",
|
||||||
"m3secondary": "#d7c3c4",
|
"m3secondary": "#d7c3c4",
|
||||||
"m3surfaceTint": "#e29c9d"
|
"m3surfaceTint": "#e29c9d",
|
||||||
},
|
},
|
||||||
"frappe": {
|
"frappe": {
|
||||||
"m3primary": "#eebebe",
|
"m3primary": "#eebebe",
|
||||||
"m3primaryText": "#303446",
|
"m3primaryText": "#303446",
|
||||||
"m3primaryContainer": "#b5949a",
|
"m3primaryContainer": "#b5949a",
|
||||||
"m3secondary": "#9d6b80",
|
"m3secondary": "#9d6b80",
|
||||||
"m3surfaceTint": "#b5949a"
|
"m3surfaceTint": "#b5949a",
|
||||||
},
|
},
|
||||||
"macchiato": {
|
"macchiato": {
|
||||||
"m3primary": "#f0c6c6",
|
"m3primary": "#f0c6c6",
|
||||||
"m3primaryText": "#24273a",
|
"m3primaryText": "#24273a",
|
||||||
"m3primaryContainer": "#b3979c",
|
"m3primaryContainer": "#b3979c",
|
||||||
"m3secondary": "#996780",
|
"m3secondary": "#996780",
|
||||||
"m3surfaceTint": "#b3979c"
|
"m3surfaceTint": "#b3979c",
|
||||||
},
|
},
|
||||||
"mocha": {
|
"mocha": {
|
||||||
"m3primary": "#f2cdcd",
|
"m3primary": "#f2cdcd",
|
||||||
"m3primaryText": "#1e1e2e",
|
"m3primaryText": "#1e1e2e",
|
||||||
"m3primaryContainer": "#b3999e",
|
"m3primaryContainer": "#b3999e",
|
||||||
"m3secondary": "#98667c",
|
"m3secondary": "#98667c",
|
||||||
"m3surfaceTint": "#b3999e"
|
"m3surfaceTint": "#b3999e",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "pink",
|
"id": "pink",
|
||||||
@@ -169,29 +163,29 @@ _data = {
|
|||||||
"m3primaryText": "#eff1f5",
|
"m3primaryText": "#eff1f5",
|
||||||
"m3primaryContainer": "#eb9bd7",
|
"m3primaryContainer": "#eb9bd7",
|
||||||
"m3secondary": "#d9c7d5",
|
"m3secondary": "#d9c7d5",
|
||||||
"m3surfaceTint": "#eb9bd7"
|
"m3surfaceTint": "#eb9bd7",
|
||||||
},
|
},
|
||||||
"frappe": {
|
"frappe": {
|
||||||
"m3primary": "#f4b8e4",
|
"m3primary": "#f4b8e4",
|
||||||
"m3primaryText": "#303446",
|
"m3primaryText": "#303446",
|
||||||
"m3primaryContainer": "#b990b5",
|
"m3primaryContainer": "#b990b5",
|
||||||
"m3secondary": "#996e9e",
|
"m3secondary": "#996e9e",
|
||||||
"m3surfaceTint": "#b990b5"
|
"m3surfaceTint": "#b990b5",
|
||||||
},
|
},
|
||||||
"macchiato": {
|
"macchiato": {
|
||||||
"m3primary": "#f5bde6",
|
"m3primary": "#f5bde6",
|
||||||
"m3primaryText": "#24273a",
|
"m3primaryText": "#24273a",
|
||||||
"m3primaryContainer": "#b791b2",
|
"m3primaryContainer": "#b791b2",
|
||||||
"m3secondary": "#95689a",
|
"m3secondary": "#95689a",
|
||||||
"m3surfaceTint": "#b791b2"
|
"m3surfaceTint": "#b791b2",
|
||||||
},
|
},
|
||||||
"mocha": {
|
"mocha": {
|
||||||
"m3primary": "#f5c2e7",
|
"m3primary": "#f5c2e7",
|
||||||
"m3primaryText": "#1e1e2e",
|
"m3primaryText": "#1e1e2e",
|
||||||
"m3primaryContainer": "#b591b0",
|
"m3primaryContainer": "#b591b0",
|
||||||
"m3secondary": "#966597",
|
"m3secondary": "#966597",
|
||||||
"m3surfaceTint": "#b591b0"
|
"m3surfaceTint": "#b591b0",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "mauve",
|
"id": "mauve",
|
||||||
@@ -201,29 +195,29 @@ _data = {
|
|||||||
"m3primaryText": "#eff1f5",
|
"m3primaryText": "#eff1f5",
|
||||||
"m3primaryContainer": "#a670f1",
|
"m3primaryContainer": "#a670f1",
|
||||||
"m3secondary": "#c2b8d0",
|
"m3secondary": "#c2b8d0",
|
||||||
"m3surfaceTint": "#a670f1"
|
"m3surfaceTint": "#a670f1",
|
||||||
},
|
},
|
||||||
"frappe": {
|
"frappe": {
|
||||||
"m3primary": "#ca9ee6",
|
"m3primary": "#ca9ee6",
|
||||||
"m3primaryText": "#303446",
|
"m3primaryText": "#303446",
|
||||||
"m3primaryContainer": "#9c7eb6",
|
"m3primaryContainer": "#9c7eb6",
|
||||||
"m3secondary": "#7d6799",
|
"m3secondary": "#7d6799",
|
||||||
"m3surfaceTint": "#9c7eb6"
|
"m3surfaceTint": "#9c7eb6",
|
||||||
},
|
},
|
||||||
"macchiato": {
|
"macchiato": {
|
||||||
"m3primary": "#c6a0f6",
|
"m3primary": "#c6a0f6",
|
||||||
"m3primaryText": "#24273a",
|
"m3primaryText": "#24273a",
|
||||||
"m3primaryContainer": "#967cbe",
|
"m3primaryContainer": "#967cbe",
|
||||||
"m3secondary": "#766597",
|
"m3secondary": "#766597",
|
||||||
"m3surfaceTint": "#967cbe"
|
"m3surfaceTint": "#967cbe",
|
||||||
},
|
},
|
||||||
"mocha": {
|
"mocha": {
|
||||||
"m3primary": "#cba6f7",
|
"m3primary": "#cba6f7",
|
||||||
"m3primaryText": "#1e1e2e",
|
"m3primaryText": "#1e1e2e",
|
||||||
"m3primaryContainer": "#977ebb",
|
"m3primaryContainer": "#977ebb",
|
||||||
"m3secondary": "#756294",
|
"m3secondary": "#756294",
|
||||||
"m3surfaceTint": "#977ebb"
|
"m3surfaceTint": "#977ebb",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "red",
|
"id": "red",
|
||||||
@@ -233,29 +227,29 @@ _data = {
|
|||||||
"m3primaryText": "#eff1f5",
|
"m3primaryText": "#eff1f5",
|
||||||
"m3primaryContainer": "#da5371",
|
"m3primaryContainer": "#da5371",
|
||||||
"m3secondary": "#c0a0a8",
|
"m3secondary": "#c0a0a8",
|
||||||
"m3surfaceTint": "#da5371"
|
"m3surfaceTint": "#da5371",
|
||||||
},
|
},
|
||||||
"frappe": {
|
"frappe": {
|
||||||
"m3primary": "#e78284",
|
"m3primary": "#e78284",
|
||||||
"m3primaryText": "#303446",
|
"m3primaryText": "#303446",
|
||||||
"m3primaryContainer": "#b06a72",
|
"m3primaryContainer": "#b06a72",
|
||||||
"m3secondary": "#8b5d66",
|
"m3secondary": "#8b5d66",
|
||||||
"m3surfaceTint": "#b06a72"
|
"m3surfaceTint": "#b06a72",
|
||||||
},
|
},
|
||||||
"macchiato": {
|
"macchiato": {
|
||||||
"m3primary": "#ed8796",
|
"m3primary": "#ed8796",
|
||||||
"m3primaryText": "#24273a",
|
"m3primaryText": "#24273a",
|
||||||
"m3primaryContainer": "#b16b7a",
|
"m3primaryContainer": "#b16b7a",
|
||||||
"m3secondary": "#865a69",
|
"m3secondary": "#865a69",
|
||||||
"m3surfaceTint": "#b16b7a"
|
"m3surfaceTint": "#b16b7a",
|
||||||
},
|
},
|
||||||
"mocha": {
|
"mocha": {
|
||||||
"m3primary": "#f38ba8",
|
"m3primary": "#f38ba8",
|
||||||
"m3primaryText": "#1e1e2e",
|
"m3primaryText": "#1e1e2e",
|
||||||
"m3primaryContainer": "#b46b84",
|
"m3primaryContainer": "#b46b84",
|
||||||
"m3secondary": "#85596b",
|
"m3secondary": "#85596b",
|
||||||
"m3surfaceTint": "#b46b84"
|
"m3surfaceTint": "#b46b84",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "maroon",
|
"id": "maroon",
|
||||||
@@ -265,29 +259,29 @@ _data = {
|
|||||||
"m3primaryText": "#eff1f5",
|
"m3primaryText": "#eff1f5",
|
||||||
"m3primaryContainer": "#e87883",
|
"m3primaryContainer": "#e87883",
|
||||||
"m3secondary": "#cfb7ba",
|
"m3secondary": "#cfb7ba",
|
||||||
"m3surfaceTint": "#e87883"
|
"m3surfaceTint": "#e87883",
|
||||||
},
|
},
|
||||||
"frappe": {
|
"frappe": {
|
||||||
"m3primary": "#ea999c",
|
"m3primary": "#ea999c",
|
||||||
"m3primaryText": "#303446",
|
"m3primaryText": "#303446",
|
||||||
"m3primaryContainer": "#b27a83",
|
"m3primaryContainer": "#b27a83",
|
||||||
"m3secondary": "#92626f",
|
"m3secondary": "#92626f",
|
||||||
"m3surfaceTint": "#b27a83"
|
"m3surfaceTint": "#b27a83",
|
||||||
},
|
},
|
||||||
"macchiato": {
|
"macchiato": {
|
||||||
"m3primary": "#ee99a0",
|
"m3primary": "#ee99a0",
|
||||||
"m3primaryText": "#24273a",
|
"m3primaryText": "#24273a",
|
||||||
"m3primaryContainer": "#b27781",
|
"m3primaryContainer": "#b27781",
|
||||||
"m3secondary": "#8c5e6c",
|
"m3secondary": "#8c5e6c",
|
||||||
"m3surfaceTint": "#b27781"
|
"m3surfaceTint": "#b27781",
|
||||||
},
|
},
|
||||||
"mocha": {
|
"mocha": {
|
||||||
"m3primary": "#eba0ac",
|
"m3primary": "#eba0ac",
|
||||||
"m3primaryText": "#1e1e2e",
|
"m3primaryText": "#1e1e2e",
|
||||||
"m3primaryContainer": "#ae7987",
|
"m3primaryContainer": "#ae7987",
|
||||||
"m3secondary": "#895b6c",
|
"m3secondary": "#895b6c",
|
||||||
"m3surfaceTint": "#ae7987"
|
"m3surfaceTint": "#ae7987",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "peach",
|
"id": "peach",
|
||||||
@@ -297,29 +291,29 @@ _data = {
|
|||||||
"m3primaryText": "#eff1f5",
|
"m3primaryText": "#eff1f5",
|
||||||
"m3primaryContainer": "#f98e51",
|
"m3primaryContainer": "#f98e51",
|
||||||
"m3secondary": "#c9b7ad",
|
"m3secondary": "#c9b7ad",
|
||||||
"m3surfaceTint": "#f98e51"
|
"m3surfaceTint": "#f98e51",
|
||||||
},
|
},
|
||||||
"frappe": {
|
"frappe": {
|
||||||
"m3primary": "#ef9f76",
|
"m3primary": "#ef9f76",
|
||||||
"m3primaryText": "#303446",
|
"m3primaryText": "#303446",
|
||||||
"m3primaryContainer": "#b67f68",
|
"m3primaryContainer": "#b67f68",
|
||||||
"m3secondary": "#8f6a5f",
|
"m3secondary": "#8f6a5f",
|
||||||
"m3surfaceTint": "#b67f68"
|
"m3surfaceTint": "#b67f68",
|
||||||
},
|
},
|
||||||
"macchiato": {
|
"macchiato": {
|
||||||
"m3primary": "#f5a97f",
|
"m3primary": "#f5a97f",
|
||||||
"m3primaryText": "#24273a",
|
"m3primaryText": "#24273a",
|
||||||
"m3primaryContainer": "#b7836a",
|
"m3primaryContainer": "#b7836a",
|
||||||
"m3secondary": "#8c695e",
|
"m3secondary": "#8c695e",
|
||||||
"m3surfaceTint": "#b7836a"
|
"m3surfaceTint": "#b7836a",
|
||||||
},
|
},
|
||||||
"mocha": {
|
"mocha": {
|
||||||
"m3primary": "#fab387",
|
"m3primary": "#fab387",
|
||||||
"m3primaryText": "#1e1e2e",
|
"m3primaryText": "#1e1e2e",
|
||||||
"m3primaryContainer": "#b8876d",
|
"m3primaryContainer": "#b8876d",
|
||||||
"m3secondary": "#8b6a5d",
|
"m3secondary": "#8b6a5d",
|
||||||
"m3surfaceTint": "#b8876d"
|
"m3surfaceTint": "#b8876d",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "yellow",
|
"id": "yellow",
|
||||||
@@ -329,29 +323,29 @@ _data = {
|
|||||||
"m3primaryText": "#eff1f5",
|
"m3primaryText": "#eff1f5",
|
||||||
"m3primaryContainer": "#e4ac5d",
|
"m3primaryContainer": "#e4ac5d",
|
||||||
"m3secondary": "#c6baaa",
|
"m3secondary": "#c6baaa",
|
||||||
"m3surfaceTint": "#e4ac5d"
|
"m3surfaceTint": "#e4ac5d",
|
||||||
},
|
},
|
||||||
"frappe": {
|
"frappe": {
|
||||||
"m3primary": "#e5c890",
|
"m3primary": "#e5c890",
|
||||||
"m3primaryText": "#303446",
|
"m3primaryText": "#303446",
|
||||||
"m3primaryContainer": "#af9b7a",
|
"m3primaryContainer": "#af9b7a",
|
||||||
"m3secondary": "#948062",
|
"m3secondary": "#948062",
|
||||||
"m3surfaceTint": "#af9b7a"
|
"m3surfaceTint": "#af9b7a",
|
||||||
},
|
},
|
||||||
"macchiato": {
|
"macchiato": {
|
||||||
"m3primary": "#eed49f",
|
"m3primary": "#eed49f",
|
||||||
"m3primaryText": "#24273a",
|
"m3primaryText": "#24273a",
|
||||||
"m3primaryContainer": "#b2a181",
|
"m3primaryContainer": "#b2a181",
|
||||||
"m3secondary": "#947e62",
|
"m3secondary": "#947e62",
|
||||||
"m3surfaceTint": "#b2a181"
|
"m3surfaceTint": "#b2a181",
|
||||||
},
|
},
|
||||||
"mocha": {
|
"mocha": {
|
||||||
"m3primary": "#f9e2af",
|
"m3primary": "#f9e2af",
|
||||||
"m3primaryText": "#1e1e2e",
|
"m3primaryText": "#1e1e2e",
|
||||||
"m3primaryContainer": "#b8a889",
|
"m3primaryContainer": "#b8a889",
|
||||||
"m3secondary": "#978265",
|
"m3secondary": "#978265",
|
||||||
"m3surfaceTint": "#b8a889"
|
"m3surfaceTint": "#b8a889",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "green",
|
"id": "green",
|
||||||
@@ -361,29 +355,29 @@ _data = {
|
|||||||
"m3primaryText": "#eff1f5",
|
"m3primaryText": "#eff1f5",
|
||||||
"m3primaryContainer": "#74b867",
|
"m3primaryContainer": "#74b867",
|
||||||
"m3secondary": "#9fbd9b",
|
"m3secondary": "#9fbd9b",
|
||||||
"m3surfaceTint": "#74b867"
|
"m3surfaceTint": "#74b867",
|
||||||
},
|
},
|
||||||
"frappe": {
|
"frappe": {
|
||||||
"m3primary": "#a6d189",
|
"m3primary": "#a6d189",
|
||||||
"m3primaryText": "#303446",
|
"m3primaryText": "#303446",
|
||||||
"m3primaryContainer": "#83a275",
|
"m3primaryContainer": "#83a275",
|
||||||
"m3secondary": "#648e5e",
|
"m3secondary": "#648e5e",
|
||||||
"m3surfaceTint": "#83a275"
|
"m3surfaceTint": "#83a275",
|
||||||
},
|
},
|
||||||
"macchiato": {
|
"macchiato": {
|
||||||
"m3primary": "#a6da95",
|
"m3primary": "#a6da95",
|
||||||
"m3primaryText": "#24273a",
|
"m3primaryText": "#24273a",
|
||||||
"m3primaryContainer": "#80a57a",
|
"m3primaryContainer": "#80a57a",
|
||||||
"m3secondary": "#5c8a61",
|
"m3secondary": "#5c8a61",
|
||||||
"m3surfaceTint": "#80a57a"
|
"m3surfaceTint": "#80a57a",
|
||||||
},
|
},
|
||||||
"mocha": {
|
"mocha": {
|
||||||
"m3primary": "#a6e3a1",
|
"m3primary": "#a6e3a1",
|
||||||
"m3primaryText": "#1e1e2e",
|
"m3primaryText": "#1e1e2e",
|
||||||
"m3primaryContainer": "#7ea87f",
|
"m3primaryContainer": "#7ea87f",
|
||||||
"m3secondary": "#5b8964",
|
"m3secondary": "#5b8964",
|
||||||
"m3surfaceTint": "#7ea87f"
|
"m3surfaceTint": "#7ea87f",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "teal",
|
"id": "teal",
|
||||||
@@ -393,29 +387,29 @@ _data = {
|
|||||||
"m3primaryText": "#eff1f5",
|
"m3primaryText": "#eff1f5",
|
||||||
"m3primaryContainer": "#57aeb4",
|
"m3primaryContainer": "#57aeb4",
|
||||||
"m3secondary": "#93b4b7",
|
"m3secondary": "#93b4b7",
|
||||||
"m3surfaceTint": "#57aeb4"
|
"m3surfaceTint": "#57aeb4",
|
||||||
},
|
},
|
||||||
"frappe": {
|
"frappe": {
|
||||||
"m3primary": "#81c8be",
|
"m3primary": "#81c8be",
|
||||||
"m3primaryText": "#303446",
|
"m3primaryText": "#303446",
|
||||||
"m3primaryContainer": "#699b9a",
|
"m3primaryContainer": "#699b9a",
|
||||||
"m3secondary": "#588084",
|
"m3secondary": "#588084",
|
||||||
"m3surfaceTint": "#699b9a"
|
"m3surfaceTint": "#699b9a",
|
||||||
},
|
},
|
||||||
"macchiato": {
|
"macchiato": {
|
||||||
"m3primary": "#8bd5ca",
|
"m3primary": "#8bd5ca",
|
||||||
"m3primaryText": "#24273a",
|
"m3primaryText": "#24273a",
|
||||||
"m3primaryContainer": "#6da29f",
|
"m3primaryContainer": "#6da29f",
|
||||||
"m3secondary": "#577e83",
|
"m3secondary": "#577e83",
|
||||||
"m3surfaceTint": "#6da29f"
|
"m3surfaceTint": "#6da29f",
|
||||||
},
|
},
|
||||||
"mocha": {
|
"mocha": {
|
||||||
"m3primary": "#94e2d5",
|
"m3primary": "#94e2d5",
|
||||||
"m3primaryText": "#1e1e2e",
|
"m3primaryText": "#1e1e2e",
|
||||||
"m3primaryContainer": "#71a8a4",
|
"m3primaryContainer": "#71a8a4",
|
||||||
"m3secondary": "#588284",
|
"m3secondary": "#588284",
|
||||||
"m3surfaceTint": "#71a8a4"
|
"m3surfaceTint": "#71a8a4",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "sky",
|
"id": "sky",
|
||||||
@@ -425,29 +419,29 @@ _data = {
|
|||||||
"m3primaryText": "#eff1f5",
|
"m3primaryText": "#eff1f5",
|
||||||
"m3primaryContainer": "#4abcea",
|
"m3primaryContainer": "#4abcea",
|
||||||
"m3secondary": "#a4b9c2",
|
"m3secondary": "#a4b9c2",
|
||||||
"m3surfaceTint": "#4abcea"
|
"m3surfaceTint": "#4abcea",
|
||||||
},
|
},
|
||||||
"frappe": {
|
"frappe": {
|
||||||
"m3primary": "#99d1db",
|
"m3primary": "#99d1db",
|
||||||
"m3primaryText": "#303446",
|
"m3primaryText": "#303446",
|
||||||
"m3primaryContainer": "#79a2af",
|
"m3primaryContainer": "#79a2af",
|
||||||
"m3secondary": "#628494",
|
"m3secondary": "#628494",
|
||||||
"m3surfaceTint": "#79a2af"
|
"m3surfaceTint": "#79a2af",
|
||||||
},
|
},
|
||||||
"macchiato": {
|
"macchiato": {
|
||||||
"m3primary": "#91d7e3",
|
"m3primary": "#91d7e3",
|
||||||
"m3primaryText": "#24273a",
|
"m3primaryText": "#24273a",
|
||||||
"m3primaryContainer": "#71a3b0",
|
"m3primaryContainer": "#71a3b0",
|
||||||
"m3secondary": "#5e7e8c",
|
"m3secondary": "#5e7e8c",
|
||||||
"m3surfaceTint": "#71a3b0"
|
"m3surfaceTint": "#71a3b0",
|
||||||
},
|
},
|
||||||
"mocha": {
|
"mocha": {
|
||||||
"m3primary": "#89dceb",
|
"m3primary": "#89dceb",
|
||||||
"m3primaryText": "#1e1e2e",
|
"m3primaryText": "#1e1e2e",
|
||||||
"m3primaryContainer": "#69a3b3",
|
"m3primaryContainer": "#69a3b3",
|
||||||
"m3secondary": "#5a7b88",
|
"m3secondary": "#5a7b88",
|
||||||
"m3surfaceTint": "#69a3b3"
|
"m3surfaceTint": "#69a3b3",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "sapphire",
|
"id": "sapphire",
|
||||||
@@ -457,29 +451,29 @@ _data = {
|
|||||||
"m3primaryText": "#eff1f5",
|
"m3primaryText": "#eff1f5",
|
||||||
"m3primaryContainer": "#5db8c8",
|
"m3primaryContainer": "#5db8c8",
|
||||||
"m3secondary": "#9eb9be",
|
"m3secondary": "#9eb9be",
|
||||||
"m3surfaceTint": "#5db8c8"
|
"m3surfaceTint": "#5db8c8",
|
||||||
},
|
},
|
||||||
"frappe": {
|
"frappe": {
|
||||||
"m3primary": "#85c1dc",
|
"m3primary": "#85c1dc",
|
||||||
"m3primaryText": "#303446",
|
"m3primaryText": "#303446",
|
||||||
"m3primaryContainer": "#6b96af",
|
"m3primaryContainer": "#6b96af",
|
||||||
"m3secondary": "#5e7b8e",
|
"m3secondary": "#5e7b8e",
|
||||||
"m3surfaceTint": "#6b96af"
|
"m3surfaceTint": "#6b96af",
|
||||||
},
|
},
|
||||||
"macchiato": {
|
"macchiato": {
|
||||||
"m3primary": "#7dc4e4",
|
"m3primary": "#7dc4e4",
|
||||||
"m3primaryText": "#24273a",
|
"m3primaryText": "#24273a",
|
||||||
"m3primaryContainer": "#6396b1",
|
"m3primaryContainer": "#6396b1",
|
||||||
"m3secondary": "#5a7486",
|
"m3secondary": "#5a7486",
|
||||||
"m3surfaceTint": "#6396b1"
|
"m3surfaceTint": "#6396b1",
|
||||||
},
|
},
|
||||||
"mocha": {
|
"mocha": {
|
||||||
"m3primary": "#74c7ec",
|
"m3primary": "#74c7ec",
|
||||||
"m3primaryText": "#1e1e2e",
|
"m3primaryText": "#1e1e2e",
|
||||||
"m3primaryContainer": "#5a95b4",
|
"m3primaryContainer": "#5a95b4",
|
||||||
"m3secondary": "#567080",
|
"m3secondary": "#567080",
|
||||||
"m3surfaceTint": "#5a95b4"
|
"m3surfaceTint": "#5a95b4",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "blue",
|
"id": "blue",
|
||||||
@@ -489,29 +483,29 @@ _data = {
|
|||||||
"m3primaryText": "#eff1f5",
|
"m3primaryText": "#eff1f5",
|
||||||
"m3primaryContainer": "#5c90f5",
|
"m3primaryContainer": "#5c90f5",
|
||||||
"m3secondary": "#b1bacb",
|
"m3secondary": "#b1bacb",
|
||||||
"m3surfaceTint": "#5c90f5"
|
"m3surfaceTint": "#5c90f5",
|
||||||
},
|
},
|
||||||
"frappe": {
|
"frappe": {
|
||||||
"m3primary": "#8caaee",
|
"m3primary": "#8caaee",
|
||||||
"m3primaryText": "#303446",
|
"m3primaryText": "#303446",
|
||||||
"m3primaryContainer": "#7086bc",
|
"m3primaryContainer": "#7086bc",
|
||||||
"m3secondary": "#637195",
|
"m3secondary": "#637195",
|
||||||
"m3surfaceTint": "#7086bc"
|
"m3surfaceTint": "#7086bc",
|
||||||
},
|
},
|
||||||
"macchiato": {
|
"macchiato": {
|
||||||
"m3primary": "#8aadf4",
|
"m3primary": "#8aadf4",
|
||||||
"m3primaryText": "#24273a",
|
"m3primaryText": "#24273a",
|
||||||
"m3primaryContainer": "#6c85bc",
|
"m3primaryContainer": "#6c85bc",
|
||||||
"m3secondary": "#5f6d8f",
|
"m3secondary": "#5f6d8f",
|
||||||
"m3surfaceTint": "#6c85bc"
|
"m3surfaceTint": "#6c85bc",
|
||||||
},
|
},
|
||||||
"mocha": {
|
"mocha": {
|
||||||
"m3primary": "#89b4fa",
|
"m3primary": "#89b4fa",
|
||||||
"m3primaryText": "#1e1e2e",
|
"m3primaryText": "#1e1e2e",
|
||||||
"m3primaryContainer": "#6987bd",
|
"m3primaryContainer": "#6987bd",
|
||||||
"m3secondary": "#5d6c8b",
|
"m3secondary": "#5d6c8b",
|
||||||
"m3surfaceTint": "#6987bd"
|
"m3surfaceTint": "#6987bd",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "lavender",
|
"id": "lavender",
|
||||||
@@ -521,30 +515,30 @@ _data = {
|
|||||||
"m3primaryText": "#eff1f5",
|
"m3primaryText": "#eff1f5",
|
||||||
"m3primaryContainer": "#97a7fb",
|
"m3primaryContainer": "#97a7fb",
|
||||||
"m3secondary": "#cdcfdd",
|
"m3secondary": "#cdcfdd",
|
||||||
"m3surfaceTint": "#97a7fb"
|
"m3surfaceTint": "#97a7fb",
|
||||||
},
|
},
|
||||||
"frappe": {
|
"frappe": {
|
||||||
"m3primary": "#babbf1",
|
"m3primary": "#babbf1",
|
||||||
"m3primaryText": "#303446",
|
"m3primaryText": "#303446",
|
||||||
"m3primaryContainer": "#9192be",
|
"m3primaryContainer": "#9192be",
|
||||||
"m3secondary": "#7175a1",
|
"m3secondary": "#7175a1",
|
||||||
"m3surfaceTint": "#9192be"
|
"m3surfaceTint": "#9192be",
|
||||||
},
|
},
|
||||||
"macchiato": {
|
"macchiato": {
|
||||||
"m3primary": "#b7bdf8",
|
"m3primary": "#b7bdf8",
|
||||||
"m3primaryText": "#24273a",
|
"m3primaryText": "#24273a",
|
||||||
"m3primaryContainer": "#8b91bf",
|
"m3primaryContainer": "#8b91bf",
|
||||||
"m3secondary": "#6b709d",
|
"m3secondary": "#6b709d",
|
||||||
"m3surfaceTint": "#8b91bf"
|
"m3surfaceTint": "#8b91bf",
|
||||||
},
|
},
|
||||||
"mocha": {
|
"mocha": {
|
||||||
"m3primary": "#b4befe",
|
"m3primary": "#b4befe",
|
||||||
"m3primaryText": "#1e1e2e",
|
"m3primaryText": "#1e1e2e",
|
||||||
"m3primaryContainer": "#878ec0",
|
"m3primaryContainer": "#878ec0",
|
||||||
"m3secondary": "#676d99",
|
"m3secondary": "#676d99",
|
||||||
"m3surfaceTint": "#878ec0"
|
"m3surfaceTint": "#878ec0",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
import json
|
# import json
|
||||||
import typer
|
# import typer
|
||||||
from zshell.assets.schemes.catppuccin import catppuccin
|
# from zshell.assets.schemes.catppuccin import catppuccin
|
||||||
|
#
|
||||||
|
# app = typer.Typer()
|
||||||
|
#
|
||||||
|
# SCHEMES = catppuccin.variants.flavors
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# @app.command()
|
||||||
|
# def set():
|
||||||
|
|
||||||
app = typer.Typer()
|
# TODO: Currently unsused
|
||||||
|
|
||||||
SCHEMES = catppuccin.variants.flavors
|
|
||||||
|
|
||||||
|
|
||||||
@app.command()
|
|
||||||
def set():
|
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
import typer
|
# import typer
|
||||||
import subprocess
|
# import subprocess
|
||||||
|
#
|
||||||
|
# from typing import Optional
|
||||||
|
#
|
||||||
|
# app = typer.Typer()
|
||||||
|
#
|
||||||
|
# RECORDER = "gpu-screen-recorder"
|
||||||
|
# HOME = str(os.getenv("HOME"))
|
||||||
|
# CONFIG = Path(HOME + "/.config/zshell/config.json")
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# @app.command()
|
||||||
|
# def start():
|
||||||
|
|
||||||
from typing import Optional
|
# TODO: Currently unused
|
||||||
|
|
||||||
app = typer.Typer()
|
|
||||||
|
|
||||||
RECORDER = "gpu-screen-recorder"
|
|
||||||
HOME = str(os.getenv("HOME"))
|
|
||||||
CONFIG = Path(HOME + "/.config/zshell/config.json")
|
|
||||||
|
|
||||||
|
|
||||||
@app.command()
|
|
||||||
def start():
|
|
||||||
|
|||||||
@@ -23,64 +23,71 @@ app = typer.Typer()
|
|||||||
@app.command()
|
@app.command()
|
||||||
def generate(
|
def generate(
|
||||||
# image inputs (optional - used for image mode)
|
# image inputs (optional - used for image mode)
|
||||||
image_path: Optional[Path] = typer.Option(
|
image_path: Optional[Path] = typer.Option(None, help="Path to source image. Required for image mode."),
|
||||||
None, help="Path to source image. Required for image mode."),
|
|
||||||
scheme: Optional[str] = typer.Option(
|
scheme: Optional[str] = typer.Option(
|
||||||
None, help="Color scheme algorithm to use for image mode. Ignored in preset mode."),
|
None, help="Color scheme algorithm to use for image mode. Ignored in preset mode."
|
||||||
|
),
|
||||||
# preset inputs (optional - used for preset mode)
|
# preset inputs (optional - used for preset mode)
|
||||||
preset: Optional[str] = typer.Option(
|
preset: Optional[str] = typer.Option(
|
||||||
None, help="Name of a premade scheme in this format: <preset_name>:<preset_flavor>"),
|
None, help="Name of a premade scheme in this format: <preset_name>:<preset_flavor>"
|
||||||
mode: Optional[str] = typer.Option(
|
),
|
||||||
None, help="Mode of the preset scheme (dark or light)."),
|
mode: Optional[str] = typer.Option(None, help="Mode of the preset scheme (dark or light)."),
|
||||||
):
|
):
|
||||||
|
|
||||||
HOME = str(os.getenv("HOME"))
|
HOME = str(os.getenv("HOME"))
|
||||||
OUTPUT = Path(HOME + "/.local/state/zshell/scheme.json")
|
OUTPUT = Path(HOME + "/.local/state/zshell/scheme.json")
|
||||||
SEQ_STATE = Path(HOME + "/.local/state/zshell/sequences.txt")
|
SEQ_STATE = Path(HOME + "/.local/state/zshell/sequences.txt")
|
||||||
THUMB_PATH = Path(HOME +
|
THUMB_PATH = Path(HOME + "/.cache/zshell/imagecache/thumbnail.jpg")
|
||||||
"/.cache/zshell/imagecache/thumbnail.jpg")
|
WALL_DIR_PATH = Path(HOME + "/.local/state/zshell/wallpaper_path.json")
|
||||||
WALL_DIR_PATH = Path(HOME +
|
|
||||||
"/.local/state/zshell/wallpaper_path.json")
|
|
||||||
|
|
||||||
TEMPLATE_DIR = Path(HOME + "/.config/zshell/templates")
|
TEMPLATE_DIR = Path(HOME + "/.config/zshell/templates")
|
||||||
WALL_PATH = Path()
|
WALL_PATH = Path()
|
||||||
CONFIG = Path(HOME + "/.config/zshell/config.json")
|
CONFIG = Path(HOME + "/.config/zshell/config.json")
|
||||||
|
|
||||||
if preset is not None and image_path is not None:
|
if preset is not None and image_path is not None:
|
||||||
raise typer.BadParameter(
|
raise typer.BadParameter("Use either --image-path or --preset, not both.")
|
||||||
"Use either --image-path or --preset, not both.")
|
|
||||||
|
|
||||||
def get_scheme_class(scheme_name: str):
|
def get_scheme_class(scheme_name: str):
|
||||||
match scheme_name:
|
match scheme_name:
|
||||||
case "fruit-salad":
|
case "fruit-salad":
|
||||||
from materialyoucolor.scheme.scheme_fruit_salad import SchemeFruitSalad
|
from materialyoucolor.scheme.scheme_fruit_salad import SchemeFruitSalad
|
||||||
|
|
||||||
return SchemeFruitSalad
|
return SchemeFruitSalad
|
||||||
case "expressive":
|
case "expressive":
|
||||||
from materialyoucolor.scheme.scheme_expressive import SchemeExpressive
|
from materialyoucolor.scheme.scheme_expressive import SchemeExpressive
|
||||||
|
|
||||||
return SchemeExpressive
|
return SchemeExpressive
|
||||||
case "monochrome":
|
case "monochrome":
|
||||||
from materialyoucolor.scheme.scheme_monochrome import SchemeMonochrome
|
from materialyoucolor.scheme.scheme_monochrome import SchemeMonochrome
|
||||||
|
|
||||||
return SchemeMonochrome
|
return SchemeMonochrome
|
||||||
case "rainbow":
|
case "rainbow":
|
||||||
from materialyoucolor.scheme.scheme_rainbow import SchemeRainbow
|
from materialyoucolor.scheme.scheme_rainbow import SchemeRainbow
|
||||||
|
|
||||||
return SchemeRainbow
|
return SchemeRainbow
|
||||||
case "tonal-spot":
|
case "tonal-spot":
|
||||||
from materialyoucolor.scheme.scheme_tonal_spot import SchemeTonalSpot
|
from materialyoucolor.scheme.scheme_tonal_spot import SchemeTonalSpot
|
||||||
|
|
||||||
return SchemeTonalSpot
|
return SchemeTonalSpot
|
||||||
case "neutral":
|
case "neutral":
|
||||||
from materialyoucolor.scheme.scheme_neutral import SchemeNeutral
|
from materialyoucolor.scheme.scheme_neutral import SchemeNeutral
|
||||||
|
|
||||||
return SchemeNeutral
|
return SchemeNeutral
|
||||||
case "fidelity":
|
case "fidelity":
|
||||||
from materialyoucolor.scheme.scheme_fidelity import SchemeFidelity
|
from materialyoucolor.scheme.scheme_fidelity import SchemeFidelity
|
||||||
|
|
||||||
return SchemeFidelity
|
return SchemeFidelity
|
||||||
case "content":
|
case "content":
|
||||||
from materialyoucolor.scheme.scheme_content import SchemeContent
|
from materialyoucolor.scheme.scheme_content import SchemeContent
|
||||||
|
|
||||||
return SchemeContent
|
return SchemeContent
|
||||||
case "vibrant":
|
case "vibrant":
|
||||||
from materialyoucolor.scheme.scheme_vibrant import SchemeVibrant
|
from materialyoucolor.scheme.scheme_vibrant import SchemeVibrant
|
||||||
|
|
||||||
return SchemeVibrant
|
return SchemeVibrant
|
||||||
case _:
|
case _:
|
||||||
from materialyoucolor.scheme.scheme_fruit_salad import SchemeFruitSalad
|
from materialyoucolor.scheme.scheme_fruit_salad import SchemeFruitSalad
|
||||||
|
|
||||||
return SchemeFruitSalad
|
return SchemeFruitSalad
|
||||||
|
|
||||||
def hex_to_hct(hex_color: str) -> Hct:
|
def hex_to_hct(hex_color: str) -> Hct:
|
||||||
@@ -163,16 +170,11 @@ def generate(
|
|||||||
def harmonize(from_hct: Hct, to_hct: Hct, tone_boost: float) -> Hct:
|
def harmonize(from_hct: Hct, to_hct: Hct, tone_boost: float) -> Hct:
|
||||||
diff = difference_degrees(from_hct.hue, to_hct.hue)
|
diff = difference_degrees(from_hct.hue, to_hct.hue)
|
||||||
rotation = min(diff * 0.8, 100)
|
rotation = min(diff * 0.8, 100)
|
||||||
output_hue = sanitize_degrees_double(
|
output_hue = sanitize_degrees_double(from_hct.hue + rotation * rotation_direction(from_hct.hue, to_hct.hue))
|
||||||
from_hct.hue
|
|
||||||
+ rotation * rotation_direction(from_hct.hue, to_hct.hue)
|
|
||||||
)
|
|
||||||
tone = max(0.0, min(100.0, from_hct.tone * (1 + tone_boost)))
|
tone = max(0.0, min(100.0, from_hct.tone * (1 + tone_boost)))
|
||||||
return Hct.from_hct(output_hue, from_hct.chroma, tone)
|
return Hct.from_hct(output_hue, from_hct.chroma, tone)
|
||||||
|
|
||||||
def terminal_palette(
|
def terminal_palette(colors: dict[str, str], mode: str, variant: str) -> dict[str, str]:
|
||||||
colors: dict[str, str], mode: str, variant: str
|
|
||||||
) -> dict[str, str]:
|
|
||||||
light = mode.lower() == "light"
|
light = mode.lower() == "light"
|
||||||
|
|
||||||
key_hex = (
|
key_hex = (
|
||||||
@@ -307,7 +309,7 @@ def generate(
|
|||||||
"seed": seed.to_int(),
|
"seed": seed.to_int(),
|
||||||
"flavor": flavor,
|
"flavor": flavor,
|
||||||
"variant": variant,
|
"variant": variant,
|
||||||
"colors": colors
|
"colors": colors,
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, v in colors.items():
|
for k, v in colors.items():
|
||||||
@@ -349,7 +351,7 @@ def generate(
|
|||||||
|
|
||||||
def tmux_wrap_sequences(seq: str) -> str:
|
def tmux_wrap_sequences(seq: str) -> str:
|
||||||
ESC = "\x1b"
|
ESC = "\x1b"
|
||||||
return f"{ESC}Ptmux;{seq.replace(ESC, ESC+ESC)}{ESC}\\"
|
return f"{ESC}Ptmux;{seq.replace(ESC, ESC + ESC)}{ESC}\\"
|
||||||
|
|
||||||
def parse_output_directive(first_line: str) -> Optional[Path]:
|
def parse_output_directive(first_line: str) -> Optional[Path]:
|
||||||
s = first_line.strip()
|
s = first_line.strip()
|
||||||
@@ -406,8 +408,7 @@ def generate(
|
|||||||
template = env.from_string(body)
|
template = env.from_string(body)
|
||||||
text = template.render(**context)
|
text = template.render(**context)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise RuntimeError(
|
raise RuntimeError(f"Template render failed for '{rel}': {e}") from e
|
||||||
f"Template render failed for '{rel}': {e}") from e
|
|
||||||
|
|
||||||
out_path.write_text(text, encoding="utf-8")
|
out_path.write_text(text, encoding="utf-8")
|
||||||
|
|
||||||
@@ -435,18 +436,13 @@ def generate(
|
|||||||
try:
|
try:
|
||||||
return PRESETS[name].primary
|
return PRESETS[name].primary
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise typer.BadParameter(
|
raise typer.BadParameter(f"Preset '{name}' not found. Available presets: {', '.join(PRESETS.keys())}")
|
||||||
f"Preset '{name}' not found. Available presets: {', '.join(PRESETS.keys())}")
|
|
||||||
|
|
||||||
def generate_color_scheme(seed: Hct, mode: str, scheme_class) -> dict[str, str]:
|
def generate_color_scheme(seed: Hct, mode: str, scheme_class) -> dict[str, str]:
|
||||||
|
|
||||||
is_dark = mode.lower() == "dark"
|
is_dark = mode.lower() == "dark"
|
||||||
|
|
||||||
scheme = scheme_class(
|
scheme = scheme_class(seed, is_dark, 0.0)
|
||||||
seed,
|
|
||||||
is_dark,
|
|
||||||
0.0
|
|
||||||
)
|
|
||||||
|
|
||||||
color_dict = {}
|
color_dict = {}
|
||||||
for color in vars(MaterialDynamicColors).keys():
|
for color in vars(MaterialDynamicColors).keys():
|
||||||
@@ -499,7 +495,7 @@ def generate(
|
|||||||
"mode": effective_mode,
|
"mode": effective_mode,
|
||||||
"variant": scheme,
|
"variant": scheme,
|
||||||
"colors": colors,
|
"colors": colors,
|
||||||
"seed": seed.to_int()
|
"seed": seed.to_int(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if TEMPLATE_DIR is not None:
|
if TEMPLATE_DIR is not None:
|
||||||
@@ -511,7 +507,7 @@ def generate(
|
|||||||
wallpaper_path=wp,
|
wallpaper_path=wp,
|
||||||
name=name,
|
name=name,
|
||||||
flavor=flavor,
|
flavor=flavor,
|
||||||
variant=scheme
|
variant=scheme,
|
||||||
)
|
)
|
||||||
|
|
||||||
rendered = render_all_templates(
|
rendered = render_all_templates(
|
||||||
|
|||||||
@@ -8,11 +8,9 @@ app = typer.Typer()
|
|||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
def start():
|
def start():
|
||||||
subprocess.run(args + ["ipc"] + ["call"] +
|
subprocess.run(args + ["ipc"] + ["call"] + ["picker"] + ["open"], check=True)
|
||||||
["picker"] + ["open"], check=True)
|
|
||||||
|
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
def start_freeze():
|
def start_freeze():
|
||||||
subprocess.run(args + ["ipc"] + ["call"] +
|
subprocess.run(args + ["ipc"] + ["call"] + ["picker"] + ["openFreeze"], check=True)
|
||||||
["picker"] + ["openFreeze"], check=True)
|
|
||||||
|
|||||||
@@ -33,5 +33,4 @@ def lock():
|
|||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
def call(target: str, method: str, method_args: list[str] = typer.Argument(None)):
|
def call(target: str, method: str, method_args: list[str] = typer.Argument(None)):
|
||||||
subprocess.run(args + ["ipc"] + ["call"] + [target] +
|
subprocess.run(args + ["ipc"] + ["call"] + [target] + [method] + method_args, check=True)
|
||||||
[method] + method_args, check=True)
|
|
||||||
|
|||||||
@@ -12,29 +12,28 @@ app = typer.Typer()
|
|||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
def set(wallpaper: Path):
|
def set(wallpaper: Path):
|
||||||
subprocess.run(args + ["ipc"] + ["call"] +
|
subprocess.run(args + ["ipc"] + ["call"] + ["wallpaper"] + ["set"] + [wallpaper], check=True)
|
||||||
["wallpaper"] + ["set"] + [wallpaper], check=True)
|
|
||||||
|
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
def lockscreen(
|
def lockscreen(
|
||||||
input_image: Annotated[
|
input_image: Annotated[
|
||||||
Path,
|
Path,
|
||||||
typer.Option(),
|
typer.Option(),
|
||||||
],
|
],
|
||||||
output_path: Annotated[
|
output_path: Annotated[
|
||||||
Path,
|
Path,
|
||||||
typer.Option(),
|
typer.Option(),
|
||||||
],
|
],
|
||||||
blur_amount: int = 20
|
blur_amount: int = 20,
|
||||||
):
|
):
|
||||||
img = Image.open(input_image)
|
img = Image.open(input_image)
|
||||||
size = img.size
|
size = img.size
|
||||||
if (blur_amount == 0):
|
if blur_amount == 0:
|
||||||
img.save(output_path, "PNG")
|
img.save(output_path, "PNG")
|
||||||
return
|
return
|
||||||
|
|
||||||
if (size[0] < 3840 or size[1] < 2160):
|
if size[0] < 3840 or size[1] < 2160:
|
||||||
img = img.resize((size[0] // 2, size[1] // 2), Image.NEAREST)
|
img = img.resize((size[0] // 2, size[1] // 2), Image.NEAREST)
|
||||||
else:
|
else:
|
||||||
img = img.resize((size[0] // 4, size[1] // 4), Image.NEAREST)
|
img = img.resize((size[0] // 4, size[1] // 4), Image.NEAREST)
|
||||||
|
|||||||
+12
-10
@@ -1,14 +1,16 @@
|
|||||||
export default [
|
export default [
|
||||||
{
|
{
|
||||||
files: ["**/*.{js,jsx,ts,tsx,mjs,cjs}"],
|
ignores: ["scripts/fzf.js", "scripts/fuzzysort.js"],
|
||||||
languageOptions: {
|
|
||||||
ecmaVersion: 2021,
|
|
||||||
sourceType: "module"
|
|
||||||
},
|
},
|
||||||
linterOptions: {
|
{
|
||||||
reportUnusedDisableDirectives: true
|
files: ["**/*.{js,jsx,ts,tsx,mjs,cjs}"],
|
||||||
|
languageOptions: {
|
||||||
|
ecmaVersion: 2021,
|
||||||
|
sourceType: "module",
|
||||||
|
},
|
||||||
|
linterOptions: {
|
||||||
|
reportUnusedDisableDirectives: true,
|
||||||
|
},
|
||||||
|
rules: {},
|
||||||
},
|
},
|
||||||
rules: {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
];
|
||||||
|
|||||||
+95
-95
@@ -3,141 +3,141 @@
|
|||||||
// Translated to Js from Cython with an LLM and reviewed
|
// Translated to Js from Cython with an LLM and reviewed
|
||||||
|
|
||||||
function min3(a, b, c) {
|
function min3(a, b, c) {
|
||||||
return a < b && a < c ? a : b < c ? b : c;
|
return a < b && a < c ? a : b < c ? b : c;
|
||||||
}
|
}
|
||||||
|
|
||||||
function max3(a, b, c) {
|
function max3(a, b, c) {
|
||||||
return a > b && a > c ? a : b > c ? b : c;
|
return a > b && a > c ? a : b > c ? b : c;
|
||||||
}
|
}
|
||||||
|
|
||||||
function min2(a, b) {
|
function min2(a, b) {
|
||||||
return a < b ? a : b;
|
return a < b ? a : b;
|
||||||
}
|
}
|
||||||
|
|
||||||
function max2(a, b) {
|
function max2(a, b) {
|
||||||
return a > b ? a : b;
|
return a > b ? a : b;
|
||||||
}
|
}
|
||||||
|
|
||||||
function levenshteinDistance(s1, s2) {
|
function levenshteinDistance(s1, s2) {
|
||||||
let len1 = s1.length;
|
let len1 = s1.length;
|
||||||
let len2 = s2.length;
|
let len2 = s2.length;
|
||||||
|
|
||||||
if (len1 === 0) return len2;
|
if (len1 === 0) return len2;
|
||||||
if (len2 === 0) return len1;
|
if (len2 === 0) return len1;
|
||||||
|
|
||||||
if (len2 > len1) {
|
if (len2 > len1) {
|
||||||
[s1, s2] = [s2, s1];
|
[s1, s2] = [s2, s1];
|
||||||
[len1, len2] = [len2, len1];
|
[len1, len2] = [len2, len1];
|
||||||
}
|
|
||||||
|
|
||||||
let prev = new Array(len2 + 1);
|
|
||||||
let curr = new Array(len2 + 1);
|
|
||||||
|
|
||||||
for (let j = 0; j <= len2; j++) {
|
|
||||||
prev[j] = j;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 1; i <= len1; i++) {
|
|
||||||
curr[0] = i;
|
|
||||||
for (let j = 1; j <= len2; j++) {
|
|
||||||
let cost = s1[i - 1] === s2[j - 1] ? 0 : 1;
|
|
||||||
curr[j] = min3(prev[j] + 1, curr[j - 1] + 1, prev[j - 1] + cost);
|
|
||||||
}
|
}
|
||||||
[prev, curr] = [curr, prev];
|
|
||||||
}
|
|
||||||
|
|
||||||
return prev[len2];
|
let prev = new Array(len2 + 1);
|
||||||
|
let curr = new Array(len2 + 1);
|
||||||
|
|
||||||
|
for (let j = 0; j <= len2; j++) {
|
||||||
|
prev[j] = j;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 1; i <= len1; i++) {
|
||||||
|
curr[0] = i;
|
||||||
|
for (let j = 1; j <= len2; j++) {
|
||||||
|
let cost = s1[i - 1] === s2[j - 1] ? 0 : 1;
|
||||||
|
curr[j] = min3(prev[j] + 1, curr[j - 1] + 1, prev[j - 1] + cost);
|
||||||
|
}
|
||||||
|
[prev, curr] = [curr, prev];
|
||||||
|
}
|
||||||
|
|
||||||
|
return prev[len2];
|
||||||
}
|
}
|
||||||
|
|
||||||
function partialRatio(shortS, longS) {
|
function partialRatio(shortS, longS) {
|
||||||
let lenS = shortS.length;
|
let lenS = shortS.length;
|
||||||
let lenL = longS.length;
|
let lenL = longS.length;
|
||||||
let best = 0.0;
|
let best = 0.0;
|
||||||
|
|
||||||
if (lenS === 0) return 1.0;
|
if (lenS === 0) return 1.0;
|
||||||
|
|
||||||
for (let i = 0; i <= lenL - lenS; i++) {
|
for (let i = 0; i <= lenL - lenS; i++) {
|
||||||
let sub = longS.slice(i, i + lenS);
|
let sub = longS.slice(i, i + lenS);
|
||||||
let dist = levenshteinDistance(shortS, sub);
|
let dist = levenshteinDistance(shortS, sub);
|
||||||
let score = 1.0 - dist / lenS;
|
let score = 1.0 - dist / lenS;
|
||||||
if (score > best) best = score;
|
if (score > best) best = score;
|
||||||
}
|
}
|
||||||
|
|
||||||
return best;
|
return best;
|
||||||
}
|
}
|
||||||
|
|
||||||
function computeScore(s1, s2) {
|
function computeScore(s1, s2) {
|
||||||
if (s1 === s2) return 1.0;
|
if (s1 === s2) return 1.0;
|
||||||
|
|
||||||
let dist = levenshteinDistance(s1, s2);
|
let dist = levenshteinDistance(s1, s2);
|
||||||
let maxLen = max2(s1.length, s2.length);
|
let maxLen = max2(s1.length, s2.length);
|
||||||
if (maxLen === 0) return 1.0;
|
if (maxLen === 0) return 1.0;
|
||||||
|
|
||||||
let full = 1.0 - dist / maxLen;
|
let full = 1.0 - dist / maxLen;
|
||||||
let part =
|
let part =
|
||||||
s1.length < s2.length ? partialRatio(s1, s2) : partialRatio(s2, s1);
|
s1.length < s2.length ? partialRatio(s1, s2) : partialRatio(s2, s1);
|
||||||
|
|
||||||
let score = 0.85 * full + 0.15 * part;
|
let score = 0.85 * full + 0.15 * part;
|
||||||
|
|
||||||
if (s1 && s2 && s1[0] !== s2[0]) {
|
if (s1 && s2 && s1[0] !== s2[0]) {
|
||||||
score -= 0.05;
|
score -= 0.05;
|
||||||
}
|
|
||||||
|
|
||||||
let lenDiff = Math.abs(s1.length - s2.length);
|
|
||||||
if (lenDiff >= 3) {
|
|
||||||
score -= (0.05 * lenDiff) / maxLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
let commonPrefixLen = 0;
|
|
||||||
let minLen = min2(s1.length, s2.length);
|
|
||||||
for (let i = 0; i < minLen; i++) {
|
|
||||||
if (s1[i] === s2[i]) {
|
|
||||||
commonPrefixLen++;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
score += 0.02 * commonPrefixLen;
|
|
||||||
|
|
||||||
if (s1.includes(s2) || s2.includes(s1)) {
|
let lenDiff = Math.abs(s1.length - s2.length);
|
||||||
score += 0.06;
|
if (lenDiff >= 3) {
|
||||||
}
|
score -= (0.05 * lenDiff) / maxLen;
|
||||||
|
}
|
||||||
|
|
||||||
return Math.max(0.0, Math.min(1.0, score));
|
let commonPrefixLen = 0;
|
||||||
|
let minLen = min2(s1.length, s2.length);
|
||||||
|
for (let i = 0; i < minLen; i++) {
|
||||||
|
if (s1[i] === s2[i]) {
|
||||||
|
commonPrefixLen++;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
score += 0.02 * commonPrefixLen;
|
||||||
|
|
||||||
|
if (s1.includes(s2) || s2.includes(s1)) {
|
||||||
|
score += 0.06;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.max(0.0, Math.min(1.0, score));
|
||||||
}
|
}
|
||||||
|
|
||||||
function computeTextMatchScore(s1, s2) {
|
function computeTextMatchScore(s1, s2) {
|
||||||
if (s1 === s2) return 1.0;
|
if (s1 === s2) return 1.0;
|
||||||
|
|
||||||
let dist = levenshteinDistance(s1, s2);
|
let dist = levenshteinDistance(s1, s2);
|
||||||
let maxLen = max2(s1.length, s2.length);
|
let maxLen = max2(s1.length, s2.length);
|
||||||
if (maxLen === 0) return 1.0;
|
if (maxLen === 0) return 1.0;
|
||||||
|
|
||||||
let full = 1.0 - dist / maxLen;
|
let full = 1.0 - dist / maxLen;
|
||||||
let part =
|
let part =
|
||||||
s1.length < s2.length ? partialRatio(s1, s2) : partialRatio(s2, s1);
|
s1.length < s2.length ? partialRatio(s1, s2) : partialRatio(s2, s1);
|
||||||
|
|
||||||
let score = 0.4 * full + 0.6 * part;
|
let score = 0.4 * full + 0.6 * part;
|
||||||
|
|
||||||
let lenDiff = Math.abs(s1.length - s2.length);
|
let lenDiff = Math.abs(s1.length - s2.length);
|
||||||
if (lenDiff >= 10) {
|
if (lenDiff >= 10) {
|
||||||
score -= (0.02 * lenDiff) / maxLen;
|
score -= (0.02 * lenDiff) / maxLen;
|
||||||
}
|
|
||||||
|
|
||||||
let commonPrefixLen = 0;
|
|
||||||
let minLen = min2(s1.length, s2.length);
|
|
||||||
for (let i = 0; i < minLen; i++) {
|
|
||||||
if (s1[i] === s2[i]) {
|
|
||||||
commonPrefixLen++;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
score += 0.01 * commonPrefixLen;
|
|
||||||
|
|
||||||
if (s1.includes(s2) || s2.includes(s1)) {
|
let commonPrefixLen = 0;
|
||||||
score += 0.2;
|
let minLen = min2(s1.length, s2.length);
|
||||||
}
|
for (let i = 0; i < minLen; i++) {
|
||||||
|
if (s1[i] === s2[i]) {
|
||||||
|
commonPrefixLen++;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
score += 0.01 * commonPrefixLen;
|
||||||
|
|
||||||
return Math.max(0.0, Math.min(1.0, score));
|
if (s1.includes(s2) || s2.includes(s1)) {
|
||||||
|
score += 0.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.max(0.0, Math.min(1.0, score));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,8 +39,10 @@ pub fn apply_rounded_corners(img: RgbaImage, radius: f32) -> RgbaImage {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let mut pixmap = rgba_image_to_pixmap(&img);
|
let mut pixmap = rgba_image_to_pixmap(&img);
|
||||||
let mut dst_paint = PixmapPaint::default();
|
let dst_paint = PixmapPaint {
|
||||||
dst_paint.blend_mode = BlendMode::DestinationIn;
|
blend_mode: BlendMode::DestinationIn,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
pixmap.draw_pixmap(0, 0, mask.as_ref(), &dst_paint, Transform::identity(), None);
|
pixmap.draw_pixmap(0, 0, mask.as_ref(), &dst_paint, Transform::identity(), None);
|
||||||
pixmap_to_rgba_image(pixmap)
|
pixmap_to_rgba_image(pixmap)
|
||||||
}
|
}
|
||||||
@@ -69,8 +71,10 @@ pub fn apply_drop_shadow(
|
|||||||
let shadow_x = (extra_left as f32 + offset_x) as i32;
|
let shadow_x = (extra_left as f32 + offset_x) as i32;
|
||||||
let shadow_y = (extra_top as f32 + offset_y) as i32;
|
let shadow_y = (extra_top as f32 + offset_y) as i32;
|
||||||
|
|
||||||
let mut sp = PixmapPaint::default();
|
let sp = PixmapPaint {
|
||||||
sp.blend_mode = BlendMode::Source;
|
blend_mode: BlendMode::Source,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
shadow_pixmap.draw_pixmap(
|
shadow_pixmap.draw_pixmap(
|
||||||
shadow_x,
|
shadow_x,
|
||||||
shadow_y,
|
shadow_y,
|
||||||
@@ -87,8 +91,10 @@ pub fn apply_drop_shadow(
|
|||||||
let blurred_pixmap = rgba_image_to_pixmap(&blurred);
|
let blurred_pixmap = rgba_image_to_pixmap(&blurred);
|
||||||
|
|
||||||
let mut canvas = Pixmap::new(canvas_w, canvas_h).expect("canvas pixmap");
|
let mut canvas = Pixmap::new(canvas_w, canvas_h).expect("canvas pixmap");
|
||||||
let mut p = PixmapPaint::default();
|
let p = PixmapPaint {
|
||||||
p.blend_mode = BlendMode::Source;
|
blend_mode: BlendMode::Source,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
canvas.draw_pixmap(
|
canvas.draw_pixmap(
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
@@ -98,8 +104,10 @@ pub fn apply_drop_shadow(
|
|||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut p2 = PixmapPaint::default();
|
let p2 = PixmapPaint {
|
||||||
p2.blend_mode = BlendMode::SourceOver;
|
blend_mode: BlendMode::SourceOver,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
canvas.draw_pixmap(
|
canvas.draw_pixmap(
|
||||||
extra_left as i32,
|
extra_left as i32,
|
||||||
extra_top as i32,
|
extra_top as i32,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
mod config;
|
mod config;
|
||||||
mod effects;
|
mod effects;
|
||||||
|
|
||||||
use anyhow::{bail, Context, Result};
|
use anyhow::{Context, Result, bail};
|
||||||
use std::io::Write as _;
|
use std::io::Write as _;
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user