mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 761869a561 | |||
| eb2b53ddaa | |||
| 3bbf31945d | |||
| f38756d562 | |||
| 7d03576831 | |||
| 6b48834dd6 | |||
| f0469d2d6f | |||
| 9f8dd48c8d | |||
| 6773c4750a | |||
| a50c92167c | |||
| 2c1808f9f8 | |||
| d7b68652e7 | |||
| 22d8b1e8ee | |||
| 48d656580f | |||
| 06a19262be | |||
| 4f24f8a725 | |||
| f7932c45e3 | |||
| b254383634 | |||
| fc43ab5c38 | |||
| fdc422e6a6 | |||
| c9a3533312 | |||
| ed1fff6260 | |||
| 4cf7938482 | |||
| f7394b7c44 | |||
| 478e941e4f | |||
| 513ad72ee8 | |||
| 5f7d56d865 | |||
| b8781aef49 | |||
| deff8a9425 | |||
| d9531258d9 | |||
| 131f23aab4 | |||
| 4fa29ff386 | |||
| 7f0962523d | |||
| ccb04bf01d | |||
| 5826a293ad | |||
| a7c724181f | |||
| 76b03be489 | |||
| b452772feb | |||
| 2bf74d385e | |||
| f37dd3c2ac | |||
| c6ca3a663d |
@@ -1,32 +0,0 @@
|
||||
---
|
||||
name: Bug Report
|
||||
about: Report a bug from noctalia-shell
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
### Description
|
||||
A clear and concise description of the bug.
|
||||
|
||||
### Steps to Reproduce
|
||||
1. Go to '...'
|
||||
2. Click on '...'
|
||||
3. See the error.
|
||||
|
||||
### Expected Behavior
|
||||
Explain what you expected to happen.
|
||||
|
||||
### Screenshots
|
||||
Add screenshots if applicable.
|
||||
|
||||
### Environment
|
||||
- Distro: [e.g., CachyOS, NixOS, Arch, ...]
|
||||
- Compositor: [ e.g., Hyprland, Niri, ...]
|
||||
- Noctalia-shell Version: [e.g., 1.0.0, available in About tab]
|
||||
- Noctalia QS Version: [e.g., 0.0.4, please check your package manager]
|
||||
- Monitor resolution: [e.g., 1920x1080]
|
||||
|
||||
### Additional Context
|
||||
Add any other context about the problem here.
|
||||
@@ -0,0 +1,128 @@
|
||||
name: Bug Report
|
||||
description: Report a bug or regression in Noctalia
|
||||
title: "[BUG] "
|
||||
labels: ["bug"]
|
||||
assignees: [Ly-sec, ItsLemmy]
|
||||
|
||||
body:
|
||||
- type: checkboxes
|
||||
id: submission-checklist
|
||||
attributes:
|
||||
label: Submission checklist
|
||||
description: Please confirm the following before submitting.
|
||||
options:
|
||||
- label: I have searched existing issues and confirmed this is not a duplicate.
|
||||
required: true
|
||||
- label: I am using the latest available version of Noctalia.
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Bug description
|
||||
description: A clear and concise description of the issue.
|
||||
placeholder: Describe the problem...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: steps
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: Steps required to reproduce the issue.
|
||||
placeholder: |
|
||||
1. Open ...
|
||||
2. Click ...
|
||||
3. Observe ...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: Expected behavior
|
||||
description: What did you expect to happen?
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: actual
|
||||
attributes:
|
||||
label: Actual behavior
|
||||
description: What actually happened?
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Logs / error output
|
||||
description: |
|
||||
Paste any relevant logs, terminal output, or stack traces here.
|
||||
|
||||
Examples:
|
||||
- journalctl output
|
||||
- terminal errors
|
||||
- crash logs
|
||||
|
||||
Large outputs can be wrapped in a `<details>` block.
|
||||
render: text
|
||||
|
||||
- type: dropdown
|
||||
id: compositor
|
||||
attributes:
|
||||
label: Compositor
|
||||
description: Select the compositor where the issue occurs.
|
||||
options:
|
||||
- Niri
|
||||
- Hyprland
|
||||
- Sway
|
||||
- Scroll
|
||||
- Labwc
|
||||
- Mango
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: distribution
|
||||
attributes:
|
||||
label: Distribution
|
||||
description: Select the Linux distribution family where the issue occurs.
|
||||
options:
|
||||
- Arch-based
|
||||
- Fedora-based
|
||||
- Debian-based
|
||||
- Gentoo-based
|
||||
- NixOS
|
||||
- openSUSE-based
|
||||
- Void
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: environment
|
||||
attributes:
|
||||
label: Environment information
|
||||
description: |
|
||||
Please provide relevant system information:
|
||||
|
||||
If you selected `Other` for distribution and/or compositor, please specify the exact one(s) here.
|
||||
- Noctalia version or commit:
|
||||
- Installation method:
|
||||
- GPU:
|
||||
placeholder: |
|
||||
Noctalia version: main / commit hash
|
||||
Installation method: AUR
|
||||
GPU: AMD RX 7800 XT (amdgpu)
|
||||
render: text
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: |
|
||||
Add any other context, screenshots, or relevant information here.
|
||||
@@ -1,12 +1,8 @@
|
||||
blank_issues_enabled: false
|
||||
issue_templates:
|
||||
- name: "Bug Report"
|
||||
description: "Report a bug in the system."
|
||||
title: "[Bug]: "
|
||||
labels: ["bug"]
|
||||
body: "./ISSUE_TEMPLATE/bug_report.md"
|
||||
- name: "Feature Request"
|
||||
description: "Propose a new feature or improvement."
|
||||
title: "[Feature]: "
|
||||
labels: ["enhancement"]
|
||||
body: "./ISSUE_TEMPLATE/feature_request.md"
|
||||
contact_links:
|
||||
- name: Noctalia Fluxer
|
||||
url: https://fluxer.gg/Noctalia
|
||||
about: Join the community for support, discussions, and quick help.
|
||||
- name: Noctalia Docs
|
||||
url: https://docs.noctalia.dev
|
||||
about: Browse the documentation, guides, and frequently asked questions.
|
||||
@@ -1,20 +0,0 @@
|
||||
---
|
||||
name: Feature Request
|
||||
about: Suggest a new feature or improvement
|
||||
title: ''
|
||||
labels: feature
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
### Feature Description
|
||||
What feature would you like to see?
|
||||
|
||||
### Why Is This Needed?
|
||||
Explain the problem or need for this feature.
|
||||
|
||||
### Suggested Solutions
|
||||
Describe how this feature could be implemented.
|
||||
|
||||
### Additional Context
|
||||
Add any relevant screenshots, links, or resources.
|
||||
@@ -0,0 +1,92 @@
|
||||
name: Feature Request
|
||||
description: Suggest an improvement, new feature, or enhancement for Noctalia
|
||||
title: "[FEATURE] "
|
||||
labels: ["feature"]
|
||||
assignees: [Ly-sec, ItsLemmy]
|
||||
|
||||
body:
|
||||
- type: checkboxes
|
||||
id: submission-checklist
|
||||
attributes:
|
||||
label: Submission checklist
|
||||
description: Please confirm the following before submitting.
|
||||
options:
|
||||
- label: I have searched existing issues and confirmed this has not been requested before.
|
||||
required: true
|
||||
- label: I have checked existing pull requests for similar changes.
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: feature-type
|
||||
attributes:
|
||||
label: Feature type
|
||||
description: What kind of feature or improvement is this?
|
||||
options:
|
||||
- UI / visual improvement
|
||||
- New functionality
|
||||
- Performance improvement
|
||||
- Configuration / customization
|
||||
- Accessibility improvement
|
||||
- Developer / API improvement
|
||||
- Integration support
|
||||
- Documentation improvement
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: summary
|
||||
attributes:
|
||||
label: Feature summary
|
||||
description: A concise description of the feature or enhancement.
|
||||
placeholder: What would you like to see added or changed?
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: motivation
|
||||
attributes:
|
||||
label: Motivation / use case
|
||||
description: |
|
||||
Why would this feature be useful?
|
||||
What problem does it solve or improve?
|
||||
placeholder: Explain the benefit or real-world use case...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: proposed-solution
|
||||
attributes:
|
||||
label: Proposed solution
|
||||
description: |
|
||||
Describe how you think this could work.
|
||||
|
||||
Mockups, examples, screenshots, or references are welcome.
|
||||
placeholder: Describe your idea...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: alternatives
|
||||
attributes:
|
||||
label: Alternatives considered
|
||||
description: |
|
||||
Have you considered any alternative solutions or workarounds?
|
||||
placeholder: Optional...
|
||||
|
||||
- type: textarea
|
||||
id: references
|
||||
attributes:
|
||||
label: References / related projects
|
||||
description: |
|
||||
Link any related projects, concepts, screenshots, issues, or examples here.
|
||||
placeholder: |
|
||||
https://github.com/...
|
||||
https://example.com/...
|
||||
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: |
|
||||
Add any additional information, screenshots, mockups, or context here.
|
||||
@@ -0,0 +1,128 @@
|
||||
name: Label Issue Metadata
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, edited]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
label-issue-metadata:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Apply compositor and distribution labels from issue form
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const issue = context.payload.issue;
|
||||
const body = issue.body || "";
|
||||
const issueNumber = issue.number;
|
||||
const { owner, repo } = context.repo;
|
||||
|
||||
const extractValue = (heading) => {
|
||||
const escapedHeading = heading.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||
const match = body.match(new RegExp(`^\\s*(?:###\\s*)?${escapedHeading}\\s*\\r?\\n+([^\\n\\r]+)`, "im"));
|
||||
return match ? match[1].trim() : null;
|
||||
};
|
||||
|
||||
const compositorValue = extractValue("Compositor");
|
||||
const distributionValue = extractValue("Distribution");
|
||||
|
||||
const compositorLabelMap = {
|
||||
"Niri": "compositor:niri",
|
||||
"Hyprland": "compositor:hyprland",
|
||||
"Sway": "compositor:sway",
|
||||
"Scroll": "compositor:scroll",
|
||||
"Labwc": "compositor:labwc",
|
||||
"Mango": "compositor:mango",
|
||||
"MangoWC": "compositor:mango",
|
||||
"Other": "compositor:other"
|
||||
};
|
||||
|
||||
const distributionLabelMap = {
|
||||
"Arch-based": "distro:arch-based",
|
||||
"Fedora-based": "distro:fedora-based",
|
||||
"Debian-based": "distro:debian-based",
|
||||
"NixOS": "distro:nixos",
|
||||
"openSUSE-based": "distro:opensuse",
|
||||
"Gentoo-based": "distro:gentoo",
|
||||
"Void": "distro:void",
|
||||
"Void-based": "distro:void",
|
||||
"Other": "distro:other"
|
||||
};
|
||||
|
||||
const mappings = [
|
||||
{
|
||||
kind: "compositor",
|
||||
prefix: "compositor:",
|
||||
selectedValue: compositorValue,
|
||||
labelMap: compositorLabelMap,
|
||||
description: "Issue reported for this compositor stack"
|
||||
},
|
||||
{
|
||||
kind: "distribution",
|
||||
prefix: "distro:",
|
||||
selectedValue: distributionValue,
|
||||
labelMap: distributionLabelMap,
|
||||
description: "Issue reported for this Linux distribution family"
|
||||
}
|
||||
];
|
||||
|
||||
async function ensureLabelExists(name, description) {
|
||||
try {
|
||||
await github.rest.issues.getLabel({ owner, repo, name });
|
||||
} catch (error) {
|
||||
if (error.status !== 404) throw error;
|
||||
await github.rest.issues.createLabel({
|
||||
owner,
|
||||
repo,
|
||||
name,
|
||||
color: "5319e7",
|
||||
description
|
||||
});
|
||||
core.info(`Created missing label "${name}".`);
|
||||
}
|
||||
}
|
||||
|
||||
const existingLabels = issue.labels.map((label) => label.name);
|
||||
|
||||
for (const mapping of mappings) {
|
||||
if (!mapping.selectedValue) {
|
||||
core.info(`${mapping.kind} field not found in issue body; skipping.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const targetLabel = mapping.labelMap[mapping.selectedValue];
|
||||
if (!targetLabel) {
|
||||
core.info(`No ${mapping.kind} label mapping found for value: "${mapping.selectedValue}"`);
|
||||
continue;
|
||||
}
|
||||
|
||||
await ensureLabelExists(targetLabel, mapping.description);
|
||||
|
||||
const currentKindLabels = existingLabels.filter((name) => name.startsWith(mapping.prefix));
|
||||
for (const label of currentKindLabels) {
|
||||
if (label === targetLabel) continue;
|
||||
try {
|
||||
await github.rest.issues.removeLabel({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber,
|
||||
name: label
|
||||
});
|
||||
} catch (error) {
|
||||
core.info(`Could not remove label "${label}": ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
await github.rest.issues.addLabels({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber,
|
||||
labels: [targetLabel]
|
||||
});
|
||||
|
||||
core.info(`Applied ${mapping.kind} label "${targetLabel}" from value "${mapping.selectedValue}".`);
|
||||
}
|
||||
@@ -3,6 +3,6 @@
|
||||
#https://doc.qt.io/qt-6/qpalette.html - Qt6 didn't add/delete/change any of the color functions or docs
|
||||
# functions that correspond to the colors definition location
|
||||
# windowText,button,light,midlight,dark,mid,text,brightText,buttonText,base,window,shadow,highlight,highlightedText,link,linkVisited,alternateBase,NO_IDEA (just use some sane default),toolTipBase,toolTipText,placeholderText,accent
|
||||
active_colors={{colors.on_background.default.hex}}, {{colors.surface.default.hex}}, #ffffff, #cacaca, #9f9f9f, #b8b8b8, {{colors.on_background.default.hex}}, #ffffff, {{colors.on_surface.default.hex}}, {{colors.background.default.hex}}, {{colors.background.default.hex}}, {{colors.shadow.default.hex}}, {{colors.primary_container.default.hex}}, {{colors.on_primary_container.default.hex}}, {{colors.secondary.default.hex}}, {{colors.primary.default.hex}}, {{colors.surface_variant.default.hex}}, {{colors.surface.default.hex}}, {{colors.surface_variant.default.hex}}, {{colors.on_surface.default.hex}}, {{colors.on_surface.default.hex}}, {{colors.primary.default.hex}}
|
||||
disabled_colors={{colors.on_background.default.hex}}, {{colors.surface.default.hex}}, #ffffff, #cacaca, #9f9f9f, #b8b8b8, {{colors.on_background.default.hex}}, #ffffff, {{colors.on_surface.default.hex}}, {{colors.background.default.hex}}, {{colors.background.default.hex}}, {{colors.shadow.default.hex}}, {{colors.primary_container.default.hex}}, {{colors.on_primary_container.default.hex}}, {{colors.secondary.default.hex}}, {{colors.primary.default.hex}}, {{colors.surface_variant.default.hex}}, {{colors.surface.default.hex}}, {{colors.surface_variant.default.hex}}, {{colors.on_surface.default.hex}}, {{colors.on_surface.default.hex}}, {{colors.primary.default.hex}}
|
||||
inactive_colors={{colors.on_background.default.hex}}, {{colors.surface.default.hex}}, #ffffff, #cacaca, #9f9f9f, #b8b8b8, {{colors.on_background.default.hex}}, #ffffff, {{colors.on_surface.default.hex}}, {{colors.background.default.hex}}, {{colors.background.default.hex}}, {{colors.shadow.default.hex}}, {{colors.primary_container.default.hex}}, {{colors.on_primary_container.default.hex}}, {{colors.secondary.default.hex}}, {{colors.primary.default.hex}}, {{colors.surface_variant.default.hex}}, {{colors.surface.default.hex}}, {{colors.surface_variant.default.hex}}, {{colors.on_surface.default.hex}}, {{colors.on_surface.default.hex}}, {{colors.primary.default.hex}}
|
||||
active_colors={{colors.on_background.default.hex}}, {{colors.surface.default.hex}}, {{colors.surface_variant.default.hex}}, #cacaca, #9f9f9f, {{colors.surface_container.default.hex}}, {{colors.on_background.default.hex}}, #ffffff, {{colors.on_surface.default.hex}}, {{colors.background.default.hex}}, {{colors.background.default.hex}}, {{colors.shadow.default.hex}}, {{colors.primary_container.default.hex}}, {{colors.on_primary_container.default.hex}}, {{colors.secondary.default.hex}}, {{colors.primary.default.hex}}, {{colors.surface_variant.default.hex}}, {{colors.surface.default.hex}}, {{colors.surface_variant.default.hex}}, {{colors.on_surface.default.hex}}, {{colors.on_surface.default.hex}}, {{colors.primary.default.hex}}
|
||||
disabled_colors={{colors.on_background.default.hex}}, {{colors.surface.default.hex}}, {{colors.surface_variant.default.hex}}, #cacaca, #9f9f9f, {{colors.surface_container.default.hex}}, {{colors.on_background.default.hex}}, #ffffff, {{colors.on_surface.default.hex}}, {{colors.background.default.hex}}, {{colors.background.default.hex}}, {{colors.shadow.default.hex}}, {{colors.primary_container.default.hex}}, {{colors.on_primary_container.default.hex}}, {{colors.secondary.default.hex}}, {{colors.primary.default.hex}}, {{colors.surface_variant.default.hex}}, {{colors.surface.default.hex}}, {{colors.surface_variant.default.hex}}, {{colors.on_surface.default.hex}}, {{colors.on_surface.default.hex}}, {{colors.primary.default.hex}}
|
||||
inactive_colors={{colors.on_background.default.hex}}, {{colors.surface.default.hex}}, {{colors.surface_variant.default.hex}}, #cacaca, #9f9f9f, {{colors.surface_container.default.hex}}, {{colors.on_background.default.hex}}, #ffffff, {{colors.on_surface.default.hex}}, {{colors.background.default.hex}}, {{colors.background.default.hex}}, {{colors.shadow.default.hex}}, {{colors.primary_container.default.hex}}, {{colors.on_primary_container.default.hex}}, {{colors.secondary.default.hex}}, {{colors.primary.default.hex}}, {{colors.surface_variant.default.hex}}, {{colors.surface.default.hex}}, {{colors.surface_variant.default.hex}}, {{colors.on_surface.default.hex}}, {{colors.on_surface.default.hex}}, {{colors.primary.default.hex}}
|
||||
|
||||
@@ -108,7 +108,13 @@ toolbar .toolbarbutton-1 {
|
||||
}
|
||||
}
|
||||
}
|
||||
.tab-text {
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
toolbarbutton#tabs-newtab-button {
|
||||
color: var(--text) !important;
|
||||
}
|
||||
/* --- URL Bar --- */
|
||||
|
||||
#urlbar-input {
|
||||
@@ -141,6 +147,10 @@ toolbar .toolbarbutton-1 {
|
||||
color: var(--text) !important;
|
||||
}
|
||||
|
||||
.urlbarView-row:not([selected]) :is(.urlbarView-title, .urlbarView-action) {
|
||||
color: var(--text) !important;
|
||||
}
|
||||
|
||||
/* --- UI Components --- */
|
||||
|
||||
#zen-toast-container {
|
||||
@@ -175,3 +185,12 @@ toolbar .toolbarbutton-1 {
|
||||
hbox#titlebar {
|
||||
background-color: var(--base) !important;
|
||||
}
|
||||
|
||||
.zen-current-workspace-indicator-name {
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.zen-current-workspace-indicator-icon {
|
||||
fill: var(--text) !important;
|
||||
}
|
||||
|
||||
|
||||
+38
-5
@@ -412,7 +412,10 @@ Item {
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.RightButton | Qt.MiddleButton
|
||||
enabled: bar.barRightClickAction !== "none" || Settings.data.bar.middleClickAction !== "none"
|
||||
// Keep enabled even when actions are "none" so we still swallow right/middle on
|
||||
// empty bar gaps. Otherwise Qt Quick's context-menu path can crash on Wayland
|
||||
// (QQuickDeliveryAgentPrivate::contextMenuTargets / mapToScene).
|
||||
enabled: true
|
||||
hoverEnabled: false
|
||||
preventStealing: true
|
||||
onClicked: mouse => {
|
||||
@@ -420,12 +423,14 @@ Item {
|
||||
if (bar.isPointOverWidget(mouse.x, mouse.y))
|
||||
return;
|
||||
bar.handleEmptyBarClick(bar.barRightClickAction, Settings.data.bar.rightClickFollowMouse, Settings.data.bar.rightClickCommand, mouse);
|
||||
mouse.accepted = true;
|
||||
return;
|
||||
}
|
||||
if (mouse.button === Qt.MiddleButton) {
|
||||
if (bar.isPointOverWidget(mouse.x, mouse.y))
|
||||
return;
|
||||
bar.handleEmptyBarClick(Settings.data.bar.middleClickAction || "none", Settings.data.bar.middleClickFollowMouse, Settings.data.bar.middleClickCommand, mouse);
|
||||
mouse.accepted = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -518,7 +523,14 @@ Item {
|
||||
height: Style.marginS
|
||||
x: 0
|
||||
y: 0
|
||||
onClicked: root.triggerFirstWidgetInSection("left")
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
||||
onClicked: function (mouse) {
|
||||
if (mouse.button !== Qt.LeftButton) {
|
||||
mouse.accepted = true;
|
||||
return;
|
||||
}
|
||||
root.triggerFirstWidgetInSection("left");
|
||||
}
|
||||
}
|
||||
|
||||
// Bottom edge hot corner - triggers last widget in right (bottom) section
|
||||
@@ -527,7 +539,14 @@ Item {
|
||||
height: Style.marginS
|
||||
x: 0
|
||||
anchors.bottom: parent.bottom
|
||||
onClicked: root.triggerLastWidgetInSection("right")
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
||||
onClicked: function (mouse) {
|
||||
if (mouse.button !== Qt.LeftButton) {
|
||||
mouse.accepted = true;
|
||||
return;
|
||||
}
|
||||
root.triggerLastWidgetInSection("right");
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate margin to center widgets vertically within the bar height
|
||||
@@ -625,7 +644,14 @@ Item {
|
||||
height: parent.height
|
||||
x: 0
|
||||
y: 0
|
||||
onClicked: root.triggerFirstWidgetInSection("left")
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
||||
onClicked: function (mouse) {
|
||||
if (mouse.button !== Qt.LeftButton) {
|
||||
mouse.accepted = true;
|
||||
return;
|
||||
}
|
||||
root.triggerFirstWidgetInSection("left");
|
||||
}
|
||||
}
|
||||
|
||||
// Right edge hot corner - triggers last widget in right section
|
||||
@@ -634,7 +660,14 @@ Item {
|
||||
height: parent.height
|
||||
anchors.right: parent.right
|
||||
y: 0
|
||||
onClicked: root.triggerLastWidgetInSection("right")
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
||||
onClicked: function (mouse) {
|
||||
if (mouse.button !== Qt.LeftButton) {
|
||||
mouse.accepted = true;
|
||||
return;
|
||||
}
|
||||
root.triggerLastWidgetInSection("right");
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate margin to center widgets horizontally within the bar height
|
||||
|
||||
@@ -413,12 +413,12 @@ Item {
|
||||
try {
|
||||
const app = DesktopEntries.byId(appId);
|
||||
|
||||
if (Settings.data.appLauncher.customLaunchPrefixEnabled && Settings.data.appLauncher.customLaunchPrefix) {
|
||||
if (Settings.data.appLauncher.customLaunchPrefixEnabled && Settings.data.appLauncher.customLaunchPrefix.trim() !== "") {
|
||||
// Use custom launch prefix
|
||||
const prefix = Settings.data.appLauncher.customLaunchPrefix.split(" ");
|
||||
const prefix = Settings.data.appLauncher.customLaunchPrefix.trim().split(" ");
|
||||
|
||||
if (app.runInTerminal) {
|
||||
const terminal = Settings.data.appLauncher.terminalCommand.split(" ");
|
||||
if (app.runInTerminal && Settings.data.appLauncher.terminalCommand.trim() !== "") {
|
||||
const terminal = Settings.data.appLauncher.terminalCommand.trim().split(" ");
|
||||
const command = prefix.concat(terminal.concat(app.command));
|
||||
Quickshell.execDetached(command);
|
||||
} else {
|
||||
@@ -426,9 +426,9 @@ Item {
|
||||
Quickshell.execDetached(command);
|
||||
}
|
||||
} else {
|
||||
if (app.runInTerminal) {
|
||||
if (app.runInTerminal && Settings.data.appLauncher.terminalCommand.trim() !== "") {
|
||||
Logger.d("Taskbar", "Executing terminal app manually: " + app.name);
|
||||
const terminal = Settings.data.appLauncher.terminalCommand.split(" ");
|
||||
const terminal = Settings.data.appLauncher.terminalCommand.trim().split(" ");
|
||||
const command = terminal.concat(app.command);
|
||||
CompositorService.spawn(command);
|
||||
} else if (app.command && app.command.length > 0) {
|
||||
|
||||
@@ -145,11 +145,11 @@ Item {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Settings.data.appLauncher.customLaunchPrefixEnabled && Settings.data.appLauncher.customLaunchPrefix) {
|
||||
const prefix = Settings.data.appLauncher.customLaunchPrefix.split(" ");
|
||||
if (Settings.data.appLauncher.customLaunchPrefixEnabled && Settings.data.appLauncher.customLaunchPrefix.trim() !== "") {
|
||||
const prefix = Settings.data.appLauncher.customLaunchPrefix.trim().split(" ");
|
||||
|
||||
if (app.runInTerminal) {
|
||||
const terminal = Settings.data.appLauncher.terminalCommand.split(" ");
|
||||
if (app.runInTerminal && Settings.data.appLauncher.terminalCommand.trim() !== "") {
|
||||
const terminal = Settings.data.appLauncher.terminalCommand.trim().split(" ");
|
||||
const command = prefix.concat(terminal.concat(app.command));
|
||||
Quickshell.execDetached(command);
|
||||
} else {
|
||||
@@ -157,9 +157,9 @@ Item {
|
||||
Quickshell.execDetached(command);
|
||||
}
|
||||
} else {
|
||||
if (app.runInTerminal) {
|
||||
if (app.runInTerminal && Settings.data.appLauncher.terminalCommand.trim() !== "") {
|
||||
Logger.d("Dock", "Executing terminal app manually: " + app.name);
|
||||
const terminal = Settings.data.appLauncher.terminalCommand.split(" ");
|
||||
const terminal = Settings.data.appLauncher.terminalCommand.trim().split(" ");
|
||||
const command = terminal.concat(app.command);
|
||||
CompositorService.spawn(command);
|
||||
} else if (app.command && app.command.length > 0) {
|
||||
@@ -584,6 +584,7 @@ Item {
|
||||
|
||||
// Apply dock-specific colorization shader only to non-focused apps
|
||||
layer.enabled: !appButton.isActive && Settings.data.dock.colorizeIcons
|
||||
layer.smooth: true
|
||||
layer.effect: ShaderEffect {
|
||||
property color targetColor: Settings.data.colorSchemes.darkMode ? Color.mOnSurface : Color.mSurfaceVariant
|
||||
property real colorizeMode: 0.0 // Dock mode (grayscale)
|
||||
|
||||
@@ -45,6 +45,19 @@ PanelWindow {
|
||||
id: triggerArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
// Default MouseArea only accepts left; right/middle would fall through to Qt Quick's
|
||||
// Wayland context-menu delivery, which can SIGSEGV in contextMenuTargets/mapToScene.
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
||||
|
||||
onPressed: function (mouse) {
|
||||
if (mouse.button === Qt.RightButton || mouse.button === Qt.MiddleButton)
|
||||
mouse.accepted = true;
|
||||
}
|
||||
|
||||
onClicked: function (mouse) {
|
||||
if (mouse.button === Qt.RightButton || mouse.button === Qt.MiddleButton)
|
||||
mouse.accepted = true;
|
||||
}
|
||||
|
||||
onEntered: {
|
||||
if (root.isBeingDestroyed)
|
||||
|
||||
@@ -553,13 +553,13 @@ Item {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Settings.data.appLauncher.customLaunchPrefixEnabled && Settings.data.appLauncher.customLaunchPrefix) {
|
||||
if (Settings.data.appLauncher.customLaunchPrefixEnabled && Settings.data.appLauncher.customLaunchPrefix.trim() !== "") {
|
||||
// Use custom launch prefix
|
||||
const prefix = Settings.data.appLauncher.customLaunchPrefix.split(" ");
|
||||
Logger.d("ApplicationsProvider", `Using custom launch prefix: ${Settings.data.appLauncher.customLaunchPrefix}`);
|
||||
const prefix = Settings.data.appLauncher.customLaunchPrefix.trim().split(" ");
|
||||
Logger.d("ApplicationsProvider", `Using custom launch prefix: ${Settings.data.appLauncher.customLaunchPrefix.trim()}`);
|
||||
|
||||
if (app.runInTerminal) {
|
||||
const terminal = Settings.data.appLauncher.terminalCommand.split(" ");
|
||||
if (app.runInTerminal && Settings.data.appLauncher.terminalCommand.trim() !== "") {
|
||||
const terminal = Settings.data.appLauncher.terminalCommand.trim().split(" ");
|
||||
const command = prefix.concat(terminal.concat(app.command));
|
||||
Logger.d("ApplicationsProvider", `Executing command (with prefix and terminal): ${command.join(" ")}`);
|
||||
Quickshell.execDetached(command);
|
||||
@@ -569,9 +569,9 @@ Item {
|
||||
Quickshell.execDetached(command);
|
||||
}
|
||||
} else {
|
||||
if (app.runInTerminal) {
|
||||
if (app.runInTerminal && Settings.data.appLauncher.terminalCommand.trim() !== "") {
|
||||
Logger.d("ApplicationsProvider", "Executing terminal app manually: " + app.name);
|
||||
const terminal = Settings.data.appLauncher.terminalCommand.split(" ");
|
||||
const terminal = Settings.data.appLauncher.terminalCommand.trim().split(" ");
|
||||
const command = terminal.concat(app.command);
|
||||
Logger.d("ApplicationsProvider", "Executing command (manual terminal): " + command.join(" "));
|
||||
CompositorService.spawn(command);
|
||||
|
||||
@@ -385,12 +385,12 @@ Item {
|
||||
var actions = [];
|
||||
|
||||
// Annotation tool for images
|
||||
if (item.isImage && Settings.data.appLauncher.screenshotAnnotationTool !== "") {
|
||||
if (item.isImage && Settings.data.appLauncher.screenshotAnnotationTool.trim() !== "") {
|
||||
actions.push({
|
||||
"icon": "pencil",
|
||||
"tooltip": I18n.tr("tooltips.open-annotation-tool"),
|
||||
"action": function () {
|
||||
var tool = Settings.data.appLauncher.screenshotAnnotationTool;
|
||||
var tool = Settings.data.appLauncher.screenshotAnnotationTool.trim();
|
||||
Quickshell.execDetached(["sh", "-c", "cliphist decode " + item.clipboardId + " | " + tool]);
|
||||
if (launcher)
|
||||
launcher.close();
|
||||
|
||||
@@ -122,6 +122,7 @@ ColumnLayout {
|
||||
label: I18n.tr("panels.color-scheme.sync-gsettings-label")
|
||||
description: I18n.tr("panels.color-scheme.sync-gsettings-description")
|
||||
checked: Settings.data.colorSchemes.syncGsettings
|
||||
defaultValue: Settings.getDefaultValue("colorSchemes.syncGsettings")
|
||||
onToggled: checked => {
|
||||
Settings.data.colorSchemes.syncGsettings = checked;
|
||||
if (checked)
|
||||
@@ -149,6 +150,7 @@ ColumnLayout {
|
||||
]
|
||||
|
||||
currentKey: Settings.data.colorSchemes.schedulingMode
|
||||
defaultValue: Settings.getDefaultValue("colorSchemes.schedulingMode")
|
||||
|
||||
onSelected: key => {
|
||||
Settings.data.colorSchemes.schedulingMode = key;
|
||||
@@ -211,6 +213,7 @@ ColumnLayout {
|
||||
label: I18n.tr("panels.color-scheme.color-source-use-wallpaper-colors-label")
|
||||
description: I18n.tr("panels.color-scheme.color-source-use-wallpaper-colors-description")
|
||||
checked: Settings.data.colorSchemes.useWallpaperColors
|
||||
defaultValue: Settings.getDefaultValue("colorSchemes.useWallpaperColors")
|
||||
onToggled: checked => {
|
||||
Settings.data.colorSchemes.useWallpaperColors = checked;
|
||||
if (checked) {
|
||||
@@ -249,7 +252,6 @@ ColumnLayout {
|
||||
Settings.data.colorSchemes.monitorForColors = key;
|
||||
AppThemeService.generate();
|
||||
}
|
||||
defaultValue: ""
|
||||
}
|
||||
|
||||
NComboBox {
|
||||
|
||||
@@ -161,7 +161,7 @@ Item {
|
||||
label: I18n.tr("common.bluetooth")
|
||||
icon: BluetoothService.enabled ? "bluetooth" : "bluetooth-off"
|
||||
checked: BluetoothService.enabled
|
||||
enabled: !NetworkService.airplaneModeEnabled && BluetoothService.bluetoothAvailable
|
||||
enabled: !NetworkService.airplaneModeEnabled && BluetoothService.bluetoothAvailable && !BluetoothService.blocked
|
||||
onToggled: checked => BluetoothService.setBluetoothEnabled(checked)
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
|
||||
@@ -148,8 +148,8 @@ Item {
|
||||
label: I18n.tr("common.wifi")
|
||||
icon: NetworkService.wifiEnabled ? "wifi" : "wifi-off"
|
||||
checked: NetworkService.wifiEnabled
|
||||
onToggled: checked => NetworkService.setWifiEnabled(checked)
|
||||
enabled: !NetworkService.airplaneModeEnabled && NetworkService.wifiAvailable
|
||||
onToggled: checked => NetworkService.setWifiEnabled(checked)
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
}
|
||||
@@ -324,7 +324,7 @@ Item {
|
||||
// Airplane Mode
|
||||
NBox {
|
||||
id: miscSettingsBox
|
||||
visible: !root.showOnlyLists && miscSettingsCol.visibleChildren.length > 0
|
||||
visible: !root.showOnlyLists && NetworkService.wifiAvailable && BluetoothService.bluetoothAvailable
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: miscSettingsCol.implicitHeight + Style.margin2XL
|
||||
color: Color.mSurface
|
||||
|
||||
@@ -15,9 +15,7 @@ ColumnLayout {
|
||||
description: I18n.tr("panels.launcher.settings-terminal-command-description")
|
||||
Layout.fillWidth: true
|
||||
text: Settings.data.appLauncher.terminalCommand
|
||||
onTextChanged: {
|
||||
Settings.data.appLauncher.terminalCommand = text;
|
||||
}
|
||||
onTextChanged: Settings.data.appLauncher.terminalCommand = text
|
||||
}
|
||||
|
||||
NToggle {
|
||||
|
||||
@@ -298,8 +298,8 @@ SmartPanel {
|
||||
|
||||
NIconButton {
|
||||
visible: Settings.data.wallpaper.enabled
|
||||
icon: "sun"
|
||||
tooltipText: Settings.data.wallpaper.linkLightAndDarkWallpapers ? I18n.tr("wallpaper.panel.header-sun-linked-tooltip") : I18n.tr("wallpaper.panel.header-sun-separate-tooltip")
|
||||
icon: "dark-mode"
|
||||
tooltipText: Settings.data.wallpaper.linkLightAndDarkWallpapers ? I18n.tr("wallpaper.panel.header-separate-light-dark-tooltip") : I18n.tr("wallpaper.panel.header-link-light-dark-tooltip")
|
||||
baseSize: Style.baseWidgetSize * 0.8
|
||||
colorBg: !Settings.data.wallpaper.linkLightAndDarkWallpapers ? Color.mPrimary : Color.smartAlpha(Color.mSurfaceVariant)
|
||||
colorFg: !Settings.data.wallpaper.linkLightAndDarkWallpapers ? Color.mOnPrimary : Color.mPrimary
|
||||
|
||||
@@ -14,6 +14,15 @@ MODE="${2:-}" # Optional second argument for dark/light mode
|
||||
# --- Apply theme based on the application name ---
|
||||
case "$APP_NAME" in
|
||||
kitty)
|
||||
# Many configs use: include ./current-theme.conf
|
||||
# Point it at the generated theme whenever the hook runs (including when noctalia.conf
|
||||
# was unchanged on disk and the hook was forced from the template processor).
|
||||
NOCTALIA_THEME="$HOME/.config/kitty/themes/noctalia.conf"
|
||||
CURRENT_THEME="$HOME/.config/kitty/current-theme.conf"
|
||||
if [ -f "$NOCTALIA_THEME" ]; then
|
||||
mkdir -p "$HOME/.config/kitty"
|
||||
ln -sf "themes/noctalia.conf" "$CURRENT_THEME"
|
||||
fi
|
||||
KITTY_CONF="$HOME/.config/kitty/kitty.conf"
|
||||
if [ -w "$KITTY_CONF" ]; then
|
||||
kitty +kitten themes --reload-in=all noctalia
|
||||
@@ -535,57 +544,73 @@ zathura)
|
||||
;;
|
||||
|
||||
starship)
|
||||
# Check if the nested starship config exists first
|
||||
if [ -f "$HOME/.config/starship/starship.toml" ]; then
|
||||
CONFIG_FILE="$HOME/.config/starship/starship.toml"
|
||||
else
|
||||
# Fallback to the default path
|
||||
CONFIG_FILE="$HOME/.config/starship.toml"
|
||||
fi
|
||||
PALETTE_FILE="$HOME/.cache/noctalia/starship-palette.toml"
|
||||
|
||||
# Check if the generated palette file exists
|
||||
if [ ! -f "$PALETTE_FILE" ]; then
|
||||
echo "Error: Starship palette file not found at $PALETTE_FILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
# Respect STARSHIP_CONFIG env var, then fall back to standard lookup order
|
||||
if [ -n "$STARSHIP_CONFIG" ]; then
|
||||
CONFIG_FILE="$STARSHIP_CONFIG"
|
||||
elif [ -f "$HOME/.config/starship.toml" ]; then
|
||||
CONFIG_FILE="$HOME/.config/starship.toml"
|
||||
elif [ -f "$HOME/.config/starship/starship.toml" ]; then
|
||||
CONFIG_FILE="$HOME/.config/starship/starship.toml"
|
||||
else
|
||||
CONFIG_FILE="$HOME/.config/starship.toml"
|
||||
fi
|
||||
|
||||
MARKER_BEGIN="# >>> NOCTALIA STARSHIP PALETTE >>>"
|
||||
MARKER_END="# <<< NOCTALIA STARSHIP PALETTE <<<"
|
||||
if [ ! -f "$PALETTE_FILE" ]; then
|
||||
echo "Error: Starship palette file not found at $PALETTE_FILE" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Create config file if it doesn't exist
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
mkdir -p "$(dirname "$CONFIG_FILE")"
|
||||
echo 'palette = "noctalia"' > "$CONFIG_FILE"
|
||||
echo "" >> "$CONFIG_FILE"
|
||||
echo "$MARKER_BEGIN" >> "$CONFIG_FILE"
|
||||
cat "$PALETTE_FILE" >> "$CONFIG_FILE"
|
||||
echo "$MARKER_END" >> "$CONFIG_FILE"
|
||||
exit 0
|
||||
fi
|
||||
MARKER_BEGIN='# >>> NOCTALIA STARSHIP PALETTE >>>'
|
||||
MARKER_END='# <<< NOCTALIA STARSHIP PALETTE <<<'
|
||||
|
||||
# 1. Set palette = "noctalia" at top level
|
||||
if grep -qE '^palette\s*=' "$CONFIG_FILE"; then
|
||||
sed -i -E 's/^palette\s*=.*/palette = "noctalia"/' "$CONFIG_FILE"
|
||||
else
|
||||
# Insert after schema line if present, otherwise at line 1
|
||||
if grep -qE '^\"\$schema\"' "$CONFIG_FILE"; then
|
||||
sed -i '/^\"\$schema\"/a palette = "noctalia"' "$CONFIG_FILE"
|
||||
else
|
||||
sed -i '1i palette = "noctalia"' "$CONFIG_FILE"
|
||||
fi
|
||||
fi
|
||||
# Create config file from scratch if it doesn't exist yet
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
mkdir -p "$(dirname "$CONFIG_FILE")"
|
||||
{
|
||||
printf 'palette = "noctalia"\n\n'
|
||||
printf '%s\n' "$MARKER_BEGIN"
|
||||
cat "$PALETTE_FILE"
|
||||
printf '%s\n' "$MARKER_END"
|
||||
} > "$CONFIG_FILE"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# 2. Remove existing noctalia palette block (between markers)
|
||||
if grep -qF "$MARKER_BEGIN" "$CONFIG_FILE"; then
|
||||
sed -i "/$(echo "$MARKER_BEGIN" | sed 's/[[\.*^$()+?{|]/\\&/g')/,/$(echo "$MARKER_END" | sed 's/[[\.*^$()+?{|]/\\&/g')/d" "$CONFIG_FILE"
|
||||
fi
|
||||
# Follow symlinks so we edit the real file (safe for stow / dotfile managers)
|
||||
if [ -L "$CONFIG_FILE" ]; then
|
||||
CONFIG_FILE="$(readlink -f "$CONFIG_FILE")"
|
||||
fi
|
||||
|
||||
# 3. Append the new palette block
|
||||
echo "" >> "$CONFIG_FILE"
|
||||
echo "$MARKER_BEGIN" >> "$CONFIG_FILE"
|
||||
cat "$PALETTE_FILE" >> "$CONFIG_FILE"
|
||||
echo "$MARKER_END" >> "$CONFIG_FILE"
|
||||
;;
|
||||
# Set or insert top-level palette = "noctalia"
|
||||
if grep -qE '^[[:space:]]*palette[[:space:]]*=' "$CONFIG_FILE"; then
|
||||
sed -i -E 's/^([[:space:]]*)palette([[:space:]]*)=.*/\1palette\2= "noctalia"/' "$CONFIG_FILE"
|
||||
elif grep -qE '^[[:space:]]*"\$schema"' "$CONFIG_FILE"; then
|
||||
sed -i '/^[[:space:]]*"\$schema"/a palette = "noctalia"' "$CONFIG_FILE"
|
||||
else
|
||||
sed -i '1i palette = "noctalia"' "$CONFIG_FILE"
|
||||
fi
|
||||
|
||||
# Remove existing palette block using awk for literal string matching
|
||||
# (avoids sed misinterpreting >, #, or other chars in the markers as regex)
|
||||
if grep -qF "$MARKER_BEGIN" "$CONFIG_FILE"; then
|
||||
awk -v begin="$MARKER_BEGIN" -v end="$MARKER_END" '
|
||||
$0 == begin { skip = 1; next }
|
||||
$0 == end { skip = 0; next }
|
||||
!skip
|
||||
' "$CONFIG_FILE" > "${CONFIG_FILE}.noctalia.tmp" \
|
||||
&& mv "${CONFIG_FILE}.noctalia.tmp" "$CONFIG_FILE"
|
||||
fi
|
||||
|
||||
# Append fresh palette block, ensuring a clean newline boundary
|
||||
{
|
||||
printf '\n%s\n' "$MARKER_BEGIN"
|
||||
cat "$PALETTE_FILE"
|
||||
# Guard: ensure palette file ends with newline before closing marker
|
||||
tail -c1 "$PALETTE_FILE" | grep -q $'\n' || printf '\n'
|
||||
printf '%s\n' "$MARKER_END"
|
||||
} >> "$CONFIG_FILE"
|
||||
;;
|
||||
|
||||
*)
|
||||
# Handle unknown application names.
|
||||
|
||||
@@ -1128,6 +1128,17 @@ class TemplateRenderer:
|
||||
"""Substitute {{closest_color}} in text."""
|
||||
return re.sub(r"\{\{\s*closest_color\s*\}\}", self.closest_color, text)
|
||||
|
||||
def _kitty_needs_current_theme_link(self, noctalia_theme_path: Path) -> bool:
|
||||
"""True if generated kitty theme exists but ~/.config/kitty/current-theme.conf is absent.
|
||||
|
||||
Many kitty.conf snippets use `include ./current-theme.conf`; template-apply.sh maintains
|
||||
that link. When noctalia.conf is skipped as identical, hooks must still run once to create it.
|
||||
"""
|
||||
if not noctalia_theme_path.is_file():
|
||||
return False
|
||||
current = Path.home() / ".config" / "kitty" / "current-theme.conf"
|
||||
return not current.is_file()
|
||||
|
||||
def process_config_file(self, config_path: Path):
|
||||
"""Process Matugen TOML configuration file."""
|
||||
if not tomllib:
|
||||
@@ -1167,21 +1178,29 @@ class TemplateRenderer:
|
||||
if not ok:
|
||||
continue
|
||||
|
||||
# Hooks reload external apps (e.g. Discord); skip when output unchanged
|
||||
if not wrote:
|
||||
out_path = Path(output_path).expanduser()
|
||||
# Hooks are skipped when the rendered file is unchanged (avoids mtime noise).
|
||||
# Kitty setups often use `include ./current-theme.conf` pointing at the live
|
||||
# theme; that file is created in the post_hook. If noctalia.conf is unchanged
|
||||
# (e.g. wallpaper palette tweak that doesn't affect terminal colors), the hook
|
||||
# never ran and current-theme.conf never appears — while predefined schemes
|
||||
# usually change bytes so hooks always run. Force hooks when that include is missing.
|
||||
force_hooks = name == "kitty" and self._kitty_needs_current_theme_link(out_path)
|
||||
if not wrote and not force_hooks:
|
||||
continue
|
||||
|
||||
# Execute pre_hook if specified
|
||||
pre_hook = template.get("pre_hook")
|
||||
if pre_hook:
|
||||
import subprocess
|
||||
if self.closest_color:
|
||||
pre_hook = self._substitute_closest_color(pre_hook)
|
||||
pre_hook = self.render(pre_hook)
|
||||
try:
|
||||
subprocess.run(pre_hook, shell=True, check=False)
|
||||
except Exception as e:
|
||||
print(f"Error running pre_hook for {name}: {e}", file=sys.stderr)
|
||||
# Execute pre_hook only when the template output was regenerated
|
||||
if wrote:
|
||||
pre_hook = template.get("pre_hook")
|
||||
if pre_hook:
|
||||
import subprocess
|
||||
if self.closest_color:
|
||||
pre_hook = self._substitute_closest_color(pre_hook)
|
||||
pre_hook = self.render(pre_hook)
|
||||
try:
|
||||
subprocess.run(pre_hook, shell=True, check=False)
|
||||
except Exception as e:
|
||||
print(f"Error running pre_hook for {name}: {e}", file=sys.stderr)
|
||||
|
||||
# Execute post_hook if specified
|
||||
post_hook = template.get("post_hook")
|
||||
|
||||
@@ -104,7 +104,8 @@ Singleton {
|
||||
"system": SettingsPanel.Tab.System,
|
||||
"systemmonitor": SettingsPanel.Tab.System,
|
||||
"userinterface": SettingsPanel.Tab.UserInterface,
|
||||
"wallpaper": SettingsPanel.Tab.Wallpaper
|
||||
"wallpaper": SettingsPanel.Tab.Wallpaper,
|
||||
"idle": SettingsPanel.Tab.Idle
|
||||
})
|
||||
|
||||
function _parseSettingsTabArg(tabArg) {
|
||||
|
||||
@@ -71,11 +71,10 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
// Handle system wakeup to force-poll and ensure state is up-to-date
|
||||
// Handle potential case where Quickshell doesnt't properly update adapter after system wakeup
|
||||
Connections {
|
||||
target: Time
|
||||
function onResumed() {
|
||||
Logger.i("Bluetooth", "System resumed - forcing state poll");
|
||||
ctlPollTimer.restart();
|
||||
}
|
||||
}
|
||||
@@ -90,7 +89,7 @@ Singleton {
|
||||
checkAirplaneMode();
|
||||
}
|
||||
function onEnabledChanged() {
|
||||
if (adapter && adapter.enabled && Settings.data.network.bluetoothAutoConnect) {
|
||||
if (adapter?.enabled && Settings.data.network.bluetoothAutoConnect) {
|
||||
autoConnectTimer.restart();
|
||||
}
|
||||
}
|
||||
@@ -99,7 +98,7 @@ Singleton {
|
||||
Connections {
|
||||
target: Settings.data.network
|
||||
function onBluetoothAutoConnectChanged() {
|
||||
if (Settings.data.network.bluetoothAutoConnect && adapter && adapter.enabled) {
|
||||
if (Settings.data.network.bluetoothAutoConnect && adapter?.enabled) {
|
||||
autoConnectTimer.restart();
|
||||
} else {
|
||||
autoConnectTimer.stop();
|
||||
@@ -137,7 +136,7 @@ Singleton {
|
||||
|
||||
Timer {
|
||||
id: ctlPollTimer
|
||||
interval: 250
|
||||
interval: 2000
|
||||
running: false
|
||||
onTriggered: {
|
||||
if (!adapter || !ProgramCheckerService.bluetoothctlAvailable) {
|
||||
|
||||
@@ -114,7 +114,7 @@ Singleton {
|
||||
|
||||
Component.onCompleted: {
|
||||
Logger.i("Network", "Service started");
|
||||
wifiInitTimer.running = true;
|
||||
wifiInitTimer.restart();
|
||||
|
||||
// Ensure initial detection if nmcli is already available at startup
|
||||
if (ProgramCheckerService.nmcliAvailable) {
|
||||
@@ -155,23 +155,6 @@ Singleton {
|
||||
}
|
||||
return;
|
||||
}
|
||||
var isAirplaneModeActive = !root.wifiEnabled && BluetoothService.blocked;
|
||||
// Extra check for Airplane Mode if Bluetooth has been blocked before Wi-Fi
|
||||
if (isAirplaneModeActive && !root.airplaneModeEnabled) {
|
||||
root.airplaneModeEnabled = true;
|
||||
ToastService.showNotice(I18n.tr("toast.airplane-mode.title"), I18n.tr("common.enabled"), "plane");
|
||||
Logger.i("AirplaneMode", "Enabled");
|
||||
root.networks = ({});
|
||||
return;
|
||||
}
|
||||
// Extra check for Airplane Mode if Wi-Fi has been unblocked before Bluetooth
|
||||
if (!isAirplaneModeActive && root.airplaneModeEnabled) {
|
||||
root.airplaneModeEnabled = false;
|
||||
ToastService.showNotice(I18n.tr("toast.airplane-mode.title"), I18n.tr("common.disabled"), "plane-off");
|
||||
Logger.i("AirplaneMode", "Disabled");
|
||||
scan();
|
||||
return;
|
||||
}
|
||||
if (root.wifiEnabled) {
|
||||
ToastService.showNotice(I18n.tr("common.wifi"), I18n.tr("common.enabled"), "wifi");
|
||||
scan();
|
||||
|
||||
@@ -11,8 +11,8 @@ Singleton {
|
||||
id: root
|
||||
|
||||
// Version properties
|
||||
readonly property string baseVersion: "4.7.6"
|
||||
readonly property bool isDevelopment: false
|
||||
readonly property string baseVersion: "4.7.7"
|
||||
readonly property bool isDevelopment: true
|
||||
readonly property string developmentSuffix: "-git"
|
||||
readonly property string currentVersion: `v${!isDevelopment ? baseVersion : baseVersion + developmentSuffix}`
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@ Item {
|
||||
implicitWidth: size
|
||||
implicitHeight: size
|
||||
|
||||
onColorChanged: canvas.requestPaint()
|
||||
|
||||
// GPU-optimized spinner - draw once, rotate with GPU transform
|
||||
Item {
|
||||
id: spinner
|
||||
|
||||
Generated
+6
-6
@@ -2,11 +2,11 @@
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1775710090,
|
||||
"narHash": "sha256-ar3rofg+awPB8QXDaFJhJ2jJhu+KqN/PRCXeyuXR76E=",
|
||||
"lastModified": 1777954456,
|
||||
"narHash": "sha256-hGdgeU2Nk87RAuZyYjyDjFL6LK7dAZN5RE9+hrDTkDU=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "4c1018dae018162ec878d42fec712642d214fdfa",
|
||||
"rev": "549bd84d6279f9852cae6225e372cc67fb91a4c1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -25,11 +25,11 @@
|
||||
"treefmt-nix": "treefmt-nix"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1775957204,
|
||||
"narHash": "sha256-d4CVRtAty2GzDYXx4xYQmR+nlOjjKovyprQfZhgLckU=",
|
||||
"lastModified": 1778377995,
|
||||
"narHash": "sha256-uUzHDHqQF1rdVNiTa05L0mML3/d7fpbAShjCRWxbrBQ=",
|
||||
"owner": "noctalia-dev",
|
||||
"repo": "noctalia-qs",
|
||||
"rev": "68e82fe34c68ee839a9c37e3466820e266af0c86",
|
||||
"rev": "d8327a723eed6dd9aebe8e0b162126f390e827df",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
@@ -182,6 +182,13 @@ in
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
warnings = lib.mkIf cfg.systemd.enable [
|
||||
''
|
||||
Running noctalia-shell as a systemd service has been deprecated!
|
||||
See https://docs.noctalia.dev/getting-started/nixos/#running-the-shell for details.
|
||||
''
|
||||
];
|
||||
|
||||
systemd.user.services.noctalia-shell = lib.mkIf cfg.systemd.enable {
|
||||
Unit = {
|
||||
Description = "Noctalia Shell - Wayland desktop shell";
|
||||
|
||||
@@ -24,6 +24,12 @@ in
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
warnings = [
|
||||
''
|
||||
Running noctalia-shell as a systemd service has been deprecated!
|
||||
See https://docs.noctalia.dev/getting-started/nixos/#running-the-shell for details.
|
||||
''
|
||||
];
|
||||
systemd.user.services.noctalia-shell = {
|
||||
description = "Noctalia Shell - Wayland desktop shell";
|
||||
documentation = [ "https://docs.noctalia.dev" ];
|
||||
|
||||
Reference in New Issue
Block a user