├── website ├── static │ ├── .nojekyll │ ├── img │ │ ├── main_bar.png │ │ ├── gallery │ │ │ ├── ashell.png │ │ │ ├── opacity.png │ │ │ ├── tray-menu.png │ │ │ ├── vpn-menu.png │ │ │ ├── power-menu.png │ │ │ ├── system-menu.png │ │ │ ├── ashell-solid.png │ │ │ ├── bluetooth-menu.png │ │ │ ├── network-menu.png │ │ │ ├── updates-panel.png │ │ │ ├── ashell-gradient.png │ │ │ └── sinks-selection.png │ │ ├── main_bar_small.png │ │ ├── ashell_social_card.png │ │ ├── iced.svg │ │ ├── logo.svg │ │ ├── favicon.svg │ │ └── rocket.svg │ └── Boogaloo-Regular.ttf ├── docs │ ├── configuration │ │ ├── _category_.yml │ │ ├── appearance │ │ │ ├── _category_.yml │ │ │ ├── index.md │ │ │ ├── theme.md │ │ │ ├── palette.md │ │ │ └── general.md │ │ ├── modules │ │ │ ├── _category_.yml │ │ │ ├── privacy.md │ │ │ ├── tray.md │ │ │ ├── media_player.md │ │ │ ├── window_title.md │ │ │ ├── app_launcher.md │ │ │ ├── clock.md │ │ │ ├── clipboard.md │ │ │ ├── updates.md │ │ │ ├── keyboard.md │ │ │ ├── custom_module.md │ │ │ └── index.md │ │ ├── index.md │ │ ├── full_config.md │ │ └── main.md │ ├── intro.md │ └── installation.md ├── versions.json ├── versioned_docs │ ├── version-0.6.0 │ │ ├── configuration │ │ │ ├── _category_.yml │ │ │ ├── appearance │ │ │ │ ├── _category_.yml │ │ │ │ ├── index.md │ │ │ │ ├── theme.md │ │ │ │ ├── palette.md │ │ │ │ └── general.md │ │ │ ├── modules │ │ │ │ ├── _category_.yml │ │ │ │ ├── privacy.md │ │ │ │ ├── tray.md │ │ │ │ ├── media_player.md │ │ │ │ ├── window_title.md │ │ │ │ ├── app_launcher.md │ │ │ │ ├── clock.md │ │ │ │ ├── clipboard.md │ │ │ │ ├── keyboard.md │ │ │ │ ├── updates.md │ │ │ │ ├── workspaces.md │ │ │ │ ├── custom_module.md │ │ │ │ ├── settings.md │ │ │ │ ├── index.md │ │ │ │ └── system_info.md │ │ │ ├── index.md │ │ │ ├── full_config.md │ │ │ └── main.md │ │ ├── intro.md │ │ └── installation.md │ └── version-0.7.0 │ │ ├── configuration │ │ ├── _category_.yml │ │ ├── appearance │ │ │ ├── _category_.yml │ │ │ ├── index.md │ │ │ ├── theme.md │ │ │ ├── palette.md │ │ │ └── general.md │ │ ├── modules │ │ │ ├── _category_.yml │ │ │ ├── privacy.md │ │ │ ├── tray.md │ │ │ ├── media_player.md │ │ │ ├── window_title.md │ │ │ ├── app_launcher.md │ │ │ ├── clock.md │ │ │ ├── clipboard.md │ │ │ ├── updates.md │ │ │ ├── keyboard.md │ │ │ ├── custom_module.md │ │ │ └── index.md │ │ ├── index.md │ │ ├── full_config.md │ │ └── main.md │ │ ├── intro.md │ │ └── installation.md ├── versioned_sidebars │ ├── version-0.6.0-sidebars.json │ └── version-0.7.0-sidebars.json ├── tsconfig.json ├── src │ ├── components │ │ └── HomepageFeatures │ │ │ ├── styles.module.css │ │ │ └── index.tsx │ ├── pages │ │ ├── index.module.css │ │ ├── index.tsx │ │ └── gallery.module.css │ └── css │ │ └── custom.css ├── .gitignore ├── sidebars.ts ├── README.md └── package.json ├── src ├── components │ └── mod.rs ├── services │ ├── mpris │ │ └── dbus.rs │ ├── mod.rs │ ├── network │ │ └── iwd_dbus │ │ │ ├── basic_service_set.rs │ │ │ ├── daemon.rs │ │ │ ├── station_diagnostic.rs │ │ │ ├── service_manager.rs │ │ │ ├── simple_configuration.rs │ │ │ ├── adapter.rs │ │ │ ├── agent_manager.rs │ │ │ ├── device.rs │ │ │ ├── known_network.rs │ │ │ ├── device_provisioning.rs │ │ │ ├── network.rs │ │ │ ├── access_point.rs │ │ │ ├── shared_code_device_provisioning.rs │ │ │ └── station.rs │ ├── throttle.rs │ └── compositor │ │ └── types.rs ├── modules │ ├── clipboard.rs │ ├── app_launcher.rs │ ├── keyboard_submap.rs │ ├── clock.rs │ ├── privacy.rs │ ├── keyboard_layout.rs │ ├── window_title.rs │ └── settings │ │ └── brightness.rs ├── utils │ ├── mod.rs │ └── launcher.rs ├── password_dialog.rs └── main.rs ├── screenshots ├── ashell.png ├── opacity.png ├── vpn-menu.png ├── power-menu.png ├── airplane-mode.png ├── ashell-solid.png ├── bluetooth-menu.png ├── network-menu.png ├── settings-panel.png ├── updates-panel.png ├── ashell-gradient.png └── sinks-selection.png ├── assets ├── AshellCustomIcon-Regular.otf ├── SymbolsNerdFont-Regular.ttf ├── SymbolsNerdFontMono-Regular.ttf └── font_README.md ├── .gitignore ├── .github ├── workflows │ ├── update-arch-package.yml │ ├── release-drafter.yml │ ├── remove-manifest-assets.yml │ ├── gh-pages-test.yml │ ├── ci.yml │ ├── gh-pages-deploy.yml │ ├── nix-ci.yml │ ├── copr-build.yml │ └── generate-installers.yml ├── dependabot.yml └── release-drafter.yml ├── Makefile ├── .rpm └── ashell.spec ├── LICENSE ├── flake.lock ├── dist-workspace.toml ├── Cargo.toml ├── flake.nix └── README.md /website/static/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod icons; 2 | -------------------------------------------------------------------------------- /website/docs/configuration/_category_.yml: -------------------------------------------------------------------------------- 1 | position: 3 2 | -------------------------------------------------------------------------------- /website/versions.json: -------------------------------------------------------------------------------- 1 | [ 2 | "0.7.0", 3 | "0.6.0" 4 | ] 5 | -------------------------------------------------------------------------------- /website/docs/configuration/appearance/_category_.yml: -------------------------------------------------------------------------------- 1 | position: 3 2 | -------------------------------------------------------------------------------- /website/docs/configuration/modules/_category_.yml: -------------------------------------------------------------------------------- 1 | position: 2 2 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.6.0/configuration/_category_.yml: -------------------------------------------------------------------------------- 1 | position: 3 2 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.7.0/configuration/_category_.yml: -------------------------------------------------------------------------------- 1 | position: 3 2 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.6.0/configuration/appearance/_category_.yml: -------------------------------------------------------------------------------- 1 | position: 3 2 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.6.0/configuration/modules/_category_.yml: -------------------------------------------------------------------------------- 1 | position: 2 2 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.7.0/configuration/appearance/_category_.yml: -------------------------------------------------------------------------------- 1 | position: 3 2 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.7.0/configuration/modules/_category_.yml: -------------------------------------------------------------------------------- 1 | position: 2 2 | -------------------------------------------------------------------------------- /screenshots/ashell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/screenshots/ashell.png -------------------------------------------------------------------------------- /screenshots/opacity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/screenshots/opacity.png -------------------------------------------------------------------------------- /screenshots/vpn-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/screenshots/vpn-menu.png -------------------------------------------------------------------------------- /screenshots/power-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/screenshots/power-menu.png -------------------------------------------------------------------------------- /screenshots/airplane-mode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/screenshots/airplane-mode.png -------------------------------------------------------------------------------- /screenshots/ashell-solid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/screenshots/ashell-solid.png -------------------------------------------------------------------------------- /screenshots/bluetooth-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/screenshots/bluetooth-menu.png -------------------------------------------------------------------------------- /screenshots/network-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/screenshots/network-menu.png -------------------------------------------------------------------------------- /screenshots/settings-panel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/screenshots/settings-panel.png -------------------------------------------------------------------------------- /screenshots/updates-panel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/screenshots/updates-panel.png -------------------------------------------------------------------------------- /screenshots/ashell-gradient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/screenshots/ashell-gradient.png -------------------------------------------------------------------------------- /screenshots/sinks-selection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/screenshots/sinks-selection.png -------------------------------------------------------------------------------- /website/static/img/main_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/website/static/img/main_bar.png -------------------------------------------------------------------------------- /assets/AshellCustomIcon-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/assets/AshellCustomIcon-Regular.otf -------------------------------------------------------------------------------- /assets/SymbolsNerdFont-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/assets/SymbolsNerdFont-Regular.ttf -------------------------------------------------------------------------------- /website/static/Boogaloo-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/website/static/Boogaloo-Regular.ttf -------------------------------------------------------------------------------- /website/static/img/gallery/ashell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/website/static/img/gallery/ashell.png -------------------------------------------------------------------------------- /website/static/img/main_bar_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/website/static/img/main_bar_small.png -------------------------------------------------------------------------------- /assets/SymbolsNerdFontMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/assets/SymbolsNerdFontMono-Regular.ttf -------------------------------------------------------------------------------- /website/static/img/gallery/opacity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/website/static/img/gallery/opacity.png -------------------------------------------------------------------------------- /website/static/img/gallery/tray-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/website/static/img/gallery/tray-menu.png -------------------------------------------------------------------------------- /website/static/img/gallery/vpn-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/website/static/img/gallery/vpn-menu.png -------------------------------------------------------------------------------- /website/static/img/ashell_social_card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/website/static/img/ashell_social_card.png -------------------------------------------------------------------------------- /website/static/img/gallery/power-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/website/static/img/gallery/power-menu.png -------------------------------------------------------------------------------- /website/static/img/gallery/system-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/website/static/img/gallery/system-menu.png -------------------------------------------------------------------------------- /website/static/img/gallery/ashell-solid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/website/static/img/gallery/ashell-solid.png -------------------------------------------------------------------------------- /website/static/img/gallery/bluetooth-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/website/static/img/gallery/bluetooth-menu.png -------------------------------------------------------------------------------- /website/static/img/gallery/network-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/website/static/img/gallery/network-menu.png -------------------------------------------------------------------------------- /website/static/img/gallery/updates-panel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/website/static/img/gallery/updates-panel.png -------------------------------------------------------------------------------- /website/static/img/gallery/ashell-gradient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/website/static/img/gallery/ashell-gradient.png -------------------------------------------------------------------------------- /website/static/img/gallery/sinks-selection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MalpenZibo/ashell/HEAD/website/static/img/gallery/sinks-selection.png -------------------------------------------------------------------------------- /website/versioned_sidebars/version-0.6.0-sidebars.json: -------------------------------------------------------------------------------- 1 | { 2 | "docsSidebar": [ 3 | { 4 | "type": "autogenerated", 5 | "dirName": "." 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /website/versioned_sidebars/version-0.7.0-sidebars.json: -------------------------------------------------------------------------------- 1 | { 2 | "docsSidebar": [ 3 | { 4 | "type": "autogenerated", 5 | "dirName": "." 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | vendor 3 | 4 | # Local Copr build artifacts 5 | /copr_build_*/ 6 | 7 | # Ignore cargo-rpm workspace except tracked spec 8 | /.rpm/* 9 | !.rpm/ashell.spec 10 | -------------------------------------------------------------------------------- /website/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // This file is not used in compilation. It is here just for a nice editor experience. 3 | "extends": "@docusaurus/tsconfig", 4 | "compilerOptions": { 5 | "baseUrl": "." 6 | }, 7 | "exclude": [".docusaurus", "build"] 8 | } 9 | -------------------------------------------------------------------------------- /website/src/components/HomepageFeatures/styles.module.css: -------------------------------------------------------------------------------- 1 | .features { 2 | display: flex; 3 | align-items: center; 4 | padding: 64px 0; 5 | width: 100%; 6 | } 7 | 8 | .featureSvg { 9 | height: 200px; 10 | width: 200px; 11 | 12 | margin-bottom: 24px; 13 | } 14 | -------------------------------------------------------------------------------- /website/docs/configuration/modules/privacy.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 10 3 | --- 4 | 5 | # Privacy 6 | 7 | This module provides a way to show if the microphone, 8 | the webcam or the screen-sharing is currently in use. 9 | 10 | There are no additional configurations available for this module. 11 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.6.0/configuration/modules/privacy.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 10 3 | --- 4 | 5 | # Privacy 6 | 7 | This module provides a way to show if the microphone, 8 | the webcam or the screen-sharing is currently in use. 9 | 10 | There are no additional configurations available for this module. 11 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.7.0/configuration/modules/privacy.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 10 3 | --- 4 | 5 | # Privacy 6 | 7 | This module provides a way to show if the microphone, 8 | the webcam or the screen-sharing is currently in use. 9 | 10 | There are no additional configurations available for this module. 11 | -------------------------------------------------------------------------------- /website/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /website/docs/configuration/modules/tray.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 8 3 | --- 4 | 5 | # Tray 6 | 7 | This module provides a system tray for displaying icons of running applications. 8 | 9 | Clicking on an icon will open the corresponding application or menu. 10 | 11 | There are no additional configuration options available for this module. 12 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.6.0/configuration/modules/tray.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 8 3 | --- 4 | 5 | # Tray 6 | 7 | This module provides a system tray for displaying icons of running applications. 8 | 9 | Clicking on an icon will open the corresponding application or menu. 10 | 11 | There are no additional configuration options available for this module. 12 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.7.0/configuration/modules/tray.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 8 3 | --- 4 | 5 | # Tray 6 | 7 | This module provides a system tray for displaying icons of running applications. 8 | 9 | Clicking on an icon will open the corresponding application or menu. 10 | 11 | There are no additional configuration options available for this module. 12 | -------------------------------------------------------------------------------- /.github/workflows/update-arch-package.yml: -------------------------------------------------------------------------------- 1 | name: Update Arch Package 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | plan: 7 | required: true 8 | type: string 9 | 10 | jobs: 11 | update-arch-package: 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - name: WIP 16 | run: echo "Automatic update of the arch package will come in the future" 17 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | # Rust (Cargo) 4 | - package-ecosystem: cargo 5 | directory: "/" 6 | schedule: 7 | interval: quarterly 8 | 9 | # NPM 10 | - package-ecosystem: npm 11 | directory: "/website" 12 | schedule: 13 | interval: quarterly 14 | 15 | # GitHub Actions 16 | - package-ecosystem: github-actions 17 | directory: "/" 18 | schedule: 19 | interval: quarterly 20 | -------------------------------------------------------------------------------- /website/docs/configuration/modules/media_player.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 11 3 | --- 4 | 5 | # Media Player 6 | 7 | This module displays the current media playback status in the status bar. 8 | 9 | You can configure the max media title length after which the title will be truncated 10 | using the `max_title_length` field. 11 | 12 | The default value is 100 characters. 13 | 14 | ## Example 15 | 16 | ```toml 17 | [media_player] 18 | max_title_length = 50 19 | ``` 20 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.6.0/configuration/modules/media_player.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 11 3 | --- 4 | 5 | # Media Player 6 | 7 | This module displays the current media playback status in the status bar. 8 | 9 | You can configure the max media title length after which the title will be truncated 10 | using the `max_title_length` field. 11 | 12 | The default value is 100 characters. 13 | 14 | ## Example 15 | 16 | ```toml 17 | [media_player] 18 | max_title_length = 50 19 | ``` 20 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.7.0/configuration/modules/media_player.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 11 3 | --- 4 | 5 | # Media Player 6 | 7 | This module displays the current media playback status in the status bar. 8 | 9 | You can configure the max media title length after which the title will be truncated 10 | using the `max_title_length` field. 11 | 12 | The default value is 100 characters. 13 | 14 | ## Example 15 | 16 | ```toml 17 | [media_player] 18 | max_title_length = 50 19 | ``` 20 | -------------------------------------------------------------------------------- /website/docs/configuration/appearance/index.md: -------------------------------------------------------------------------------- 1 | # 🎨 Appearance 2 | 3 | With these configurations, you can change the appearance of ashell. 4 | 5 | It's possible to modify the color palette and other general visual aspects. 6 | 7 | All of these configurations should be placed in the `appearance` section 8 | of the configuration file. 9 | 10 | You can customize things like: 11 | 12 | - The color palette 13 | - The font used 14 | - The scaling factor of the status bar 15 | - The style of the status bar 16 | - The opacity of the status bar components 17 | - The opacity of the status bar menus 18 | -------------------------------------------------------------------------------- /.github/workflows/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name: Draft Release 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request_target: 7 | types: [opened, reopened, edited, synchronize] 8 | 9 | permissions: 10 | contents: read 11 | 12 | jobs: 13 | update-release-draft: 14 | name: Update release 15 | permissions: 16 | contents: write 17 | pull-requests: write 18 | runs-on: ubuntu-latest 19 | steps: 20 | - uses: actions/checkout@v5 21 | 22 | - uses: release-drafter/release-drafter@v6 23 | env: 24 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 25 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.6.0/configuration/appearance/index.md: -------------------------------------------------------------------------------- 1 | # 🎨 Appearance 2 | 3 | With these configurations, you can change the appearance of ashell. 4 | 5 | It's possible to modify the color palette and other general visual aspects. 6 | 7 | All of these configurations should be placed in the `appearance` section 8 | of the configuration file. 9 | 10 | You can customize things like: 11 | 12 | - The color palette 13 | - The font used 14 | - The scaling factor of the status bar 15 | - The style of the status bar 16 | - The opacity of the status bar components 17 | - The opacity of the status bar menus 18 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.7.0/configuration/appearance/index.md: -------------------------------------------------------------------------------- 1 | # 🎨 Appearance 2 | 3 | With these configurations, you can change the appearance of ashell. 4 | 5 | It's possible to modify the color palette and other general visual aspects. 6 | 7 | All of these configurations should be placed in the `appearance` section 8 | of the configuration file. 9 | 10 | You can customize things like: 11 | 12 | - The color palette 13 | - The font used 14 | - The scaling factor of the status bar 15 | - The style of the status bar 16 | - The opacity of the status bar components 17 | - The opacity of the status bar menus 18 | -------------------------------------------------------------------------------- /website/sidebars.ts: -------------------------------------------------------------------------------- 1 | import type { SidebarsConfig } from "@docusaurus/plugin-content-docs"; 2 | 3 | // This runs in Node.js - Don't use client-side code here (browser APIs, JSX...) 4 | 5 | /** 6 | * Creating a sidebar enables you to: 7 | - create an ordered group of docs 8 | - render a sidebar for each doc of that group 9 | - provide next/previous navigation 10 | 11 | The sidebars can be generated from the filesystem, or explicitly defined here. 12 | 13 | Create as many sidebars as you want. 14 | */ 15 | const sidebars: SidebarsConfig = { 16 | docsSidebar: [{ type: "autogenerated", dirName: "." }], 17 | }; 18 | 19 | export default sidebars; 20 | -------------------------------------------------------------------------------- /website/docs/configuration/modules/window_title.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 5 3 | --- 4 | 5 | # Window Title 6 | 7 | Displays the title of the currently focused window. 8 | 9 | Using the `mode` field, you can configure what information to show: 10 | 11 | - `Title`: the window title, which is the default 12 | - `Class`: the window class 13 | 14 | You can also configure the maximum title length, after which the title will be 15 | truncated, using the `truncate_title_after_length` field. 16 | 17 | The default value is 150 characters. 18 | 19 | ## Example 20 | 21 | ```toml 22 | [window_title] 23 | mode = "Title" 24 | truncate_title_after_length = 75 25 | ``` 26 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.6.0/configuration/modules/window_title.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 5 3 | --- 4 | 5 | # Window Title 6 | 7 | Displays the title of the currently focused window. 8 | 9 | Using the `mode` field, you can configure what information to show: 10 | 11 | - `Title`: the window title, which is the default 12 | - `Class`: the window class 13 | 14 | You can also configure the maximum title length, after which the title will be 15 | truncated, using the `truncate_title_after_length` field. 16 | 17 | The default value is 150 characters. 18 | 19 | ## Example 20 | 21 | ```toml 22 | [window_title] 23 | mode = "Title" 24 | truncate_title_after_length = 75 25 | ``` 26 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.7.0/configuration/modules/window_title.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 5 3 | --- 4 | 5 | # Window Title 6 | 7 | Displays the title of the currently focused window. 8 | 9 | Using the `mode` field, you can configure what information to show: 10 | 11 | - `Title`: the window title, which is the default 12 | - `Class`: the window class 13 | 14 | You can also configure the maximum title length, after which the title will be 15 | truncated, using the `truncate_title_after_length` field. 16 | 17 | The default value is 150 characters. 18 | 19 | ## Example 20 | 21 | ```toml 22 | [window_title] 23 | mode = "Title" 24 | truncate_title_after_length = 75 25 | ``` 26 | -------------------------------------------------------------------------------- /website/docs/configuration/modules/app_launcher.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # App Launcher 6 | 7 | :::warning 8 | 9 | This module will be deprecated in future releases. 10 | 11 | ::: 12 | 13 | Provides a way to launch applications from the status bar. 14 | 15 | To configure this module, you need to specify a command that will 16 | start your launcher when the module is clicked. 17 | 18 | :::info 19 | 20 | Without this configuration, the module will not appear in the status bar. 21 | 22 | ::: 23 | 24 | ## Example 25 | 26 | In this example, I use [Walker](https://github.com/abenz1267/walker) 27 | as my application launcher. 28 | 29 | ```toml 30 | app_launcher_cmd = "walker" 31 | ``` 32 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: help build start install fmt check 2 | 3 | help: 4 | @echo "Usage: make [target]" 5 | @echo "" 6 | @echo "Targets:" 7 | @echo " help Show this help message" 8 | @echo " build Build the project" 9 | @echo " start Run the build" 10 | @echo " install Install the build to /usr/bin" 11 | @echo " fmt Format the code" 12 | @echo " check Format, check and lint the code" 13 | 14 | build: 15 | cargo build --release 16 | 17 | start: build 18 | ./target/release/ashell 19 | 20 | install: build 21 | sudo cp -f target/release/ashell /usr/bin 22 | 23 | fmt: 24 | cargo fmt 25 | 26 | check: fmt 27 | cargo check 28 | cargo clippy -- -D warnings 29 | -------------------------------------------------------------------------------- /website/docs/configuration/modules/clock.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 9 3 | --- 4 | 5 | # Clock 6 | 7 | This module displays the current time and date in the status bar. 8 | 9 | Using the `format` configuration, you can customize how the time and date are displayed. 10 | 11 | For more information about the available format options, see the [chrono documentation](https://docs.rs/chrono/latest/chrono/format/strftime/index.html). 12 | 13 | By default, the clock displays the time using this format: `%a %d %b %R`, 14 | which prints the date as `Tue 08 Jul 11:04`. 15 | 16 | ## Example 17 | 18 | This configuration shows the date in the format: `07/22/25 11:11:43 AM` 19 | 20 | ```toml 21 | [clock] 22 | format = "%D %r" 23 | ``` 24 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.6.0/configuration/modules/app_launcher.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # App Launcher 6 | 7 | :::warning 8 | 9 | This module will be deprecated in future releases. 10 | 11 | ::: 12 | 13 | Provides a way to launch applications from the status bar. 14 | 15 | To configure this module, you need to specify a command that will 16 | start your launcher when the module is clicked. 17 | 18 | :::info 19 | 20 | Without this configuration, the module will not appear in the status bar. 21 | 22 | ::: 23 | 24 | ## Example 25 | 26 | In this example, I use [Walker](https://github.com/abenz1267/walker) 27 | as my application launcher. 28 | 29 | ```toml 30 | app_launcher_cmd = "walker" 31 | ``` 32 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.7.0/configuration/modules/app_launcher.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # App Launcher 6 | 7 | :::warning 8 | 9 | This module will be deprecated in future releases. 10 | 11 | ::: 12 | 13 | Provides a way to launch applications from the status bar. 14 | 15 | To configure this module, you need to specify a command that will 16 | start your launcher when the module is clicked. 17 | 18 | :::info 19 | 20 | Without this configuration, the module will not appear in the status bar. 21 | 22 | ::: 23 | 24 | ## Example 25 | 26 | In this example, I use [Walker](https://github.com/abenz1267/walker) 27 | as my application launcher. 28 | 29 | ```toml 30 | app_launcher_cmd = "walker" 31 | ``` 32 | -------------------------------------------------------------------------------- /website/docs/configuration/modules/clipboard.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | --- 4 | 5 | # Clipboard 6 | 7 | :::warning 8 | 9 | This module will be deprecated in future releases. 10 | 11 | ::: 12 | 13 | Provides a way to open your clipboard manager from the status bar. 14 | 15 | To configure this module, you need to specify a command that will 16 | start your clipboard manager when the module is clicked. 17 | 18 | :::info 19 | 20 | Without this configuration, the module will not appear in the status bar. 21 | 22 | ::: 23 | 24 | ## Example 25 | 26 | In this example, I use [cliphist](https://github.com/sentriz/cliphist) 27 | as my clipboard manager. 28 | 29 | ```toml 30 | clipboard_cmd = "cliphist-rofi-img | wl-copy" 31 | ``` 32 | -------------------------------------------------------------------------------- /.github/workflows/remove-manifest-assets.yml: -------------------------------------------------------------------------------- 1 | name: Remove manifest asset 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | plan: 7 | required: true 8 | type: string 9 | 10 | permissions: 11 | contents: write 12 | 13 | jobs: 14 | remove-manifest-asset: 15 | runs-on: ubuntu-latest 16 | env: 17 | REPO: ${{ github.repository }} 18 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 19 | 20 | steps: 21 | - uses: actions/checkout@v4 22 | 23 | - name: Remove manifest 24 | run: | 25 | tag=$(echo '${{ inputs.plan }}' | jq -r '.announcement_tag') 26 | echo "Deleting asset from release: $tag" 27 | 28 | gh release delete-asset "$tag" "dist-manifest.json" --yes 29 | -------------------------------------------------------------------------------- /.rpm/ashell.spec: -------------------------------------------------------------------------------- 1 | %define __spec_install_post %{nil} 2 | %define __os_install_post %{_dbpath}/brp-compress 3 | %define debug_package %{nil} 4 | 5 | Name: ashell 6 | Summary: A ready to go Wayland status bar for Hyprland 7 | Version: @@VERSION@@ 8 | Release: @@RELEASE@@%{?dist} 9 | License: MIT 10 | Group: Applications/System 11 | Source0: %{name}-%{version}.tar.gz 12 | URL: https://github.com/MalpenZibo/ashell 13 | 14 | BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root 15 | 16 | %description 17 | %{summary} 18 | 19 | %prep 20 | %setup -q 21 | 22 | %install 23 | rm -rf %{buildroot} 24 | mkdir -p %{buildroot} 25 | cp -a * %{buildroot} 26 | 27 | %clean 28 | rm -rf %{buildroot} 29 | 30 | %files 31 | %defattr(-,root,root,-) 32 | %{_bindir}/* 33 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.6.0/configuration/modules/clock.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 9 3 | --- 4 | 5 | # Clock 6 | 7 | This module displays the current time and date in the status bar. 8 | 9 | Using the `format` configuration, you can customize how the time and date are displayed. 10 | 11 | For more information about the available format options, see the [chrono documentation](https://docs.rs/chrono/latest/chrono/format/strftime/index.html). 12 | 13 | By default, the clock displays the time using this format: `%a %d %b %R`, 14 | which prints the date as `Tue 08 Jul 11:04`. 15 | 16 | ## Example 17 | 18 | This configuration shows the date in the format: `07/22/25 11:11:43 AM` 19 | 20 | ```toml 21 | [clock] 22 | format = "%D %r" 23 | ``` 24 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.7.0/configuration/modules/clock.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 9 3 | --- 4 | 5 | # Clock 6 | 7 | This module displays the current time and date in the status bar. 8 | 9 | Using the `format` configuration, you can customize how the time and date are displayed. 10 | 11 | For more information about the available format options, see the [chrono documentation](https://docs.rs/chrono/latest/chrono/format/strftime/index.html). 12 | 13 | By default, the clock displays the time using this format: `%a %d %b %R`, 14 | which prints the date as `Tue 08 Jul 11:04`. 15 | 16 | ## Example 17 | 18 | This configuration shows the date in the format: `07/22/25 11:11:43 AM` 19 | 20 | ```toml 21 | [clock] 22 | format = "%D %r" 23 | ``` 24 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.6.0/configuration/modules/clipboard.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | --- 4 | 5 | # Clipboard 6 | 7 | :::warning 8 | 9 | This module will be deprecated in future releases. 10 | 11 | ::: 12 | 13 | Provides a way to open your clipboard manager from the status bar. 14 | 15 | To configure this module, you need to specify a command that will 16 | start your clipboard manager when the module is clicked. 17 | 18 | :::info 19 | 20 | Without this configuration, the module will not appear in the status bar. 21 | 22 | ::: 23 | 24 | ## Example 25 | 26 | In this example, I use [cliphist](https://github.com/sentriz/cliphist) 27 | as my clipboard manager. 28 | 29 | ```toml 30 | clipboard_cmd = "cliphist-rofi-img | wl-copy" 31 | ``` 32 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.7.0/configuration/modules/clipboard.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | --- 4 | 5 | # Clipboard 6 | 7 | :::warning 8 | 9 | This module will be deprecated in future releases. 10 | 11 | ::: 12 | 13 | Provides a way to open your clipboard manager from the status bar. 14 | 15 | To configure this module, you need to specify a command that will 16 | start your clipboard manager when the module is clicked. 17 | 18 | :::info 19 | 20 | Without this configuration, the module will not appear in the status bar. 21 | 22 | ::: 23 | 24 | ## Example 25 | 26 | In this example, I use [cliphist](https://github.com/sentriz/cliphist) 27 | as my clipboard manager. 28 | 29 | ```toml 30 | clipboard_cmd = "cliphist-rofi-img | wl-copy" 31 | ``` 32 | -------------------------------------------------------------------------------- /src/services/mpris/dbus.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use zbus::{Result, proxy, zvariant::OwnedValue}; 3 | 4 | #[proxy( 5 | interface = "org.mpris.MediaPlayer2.Player", 6 | default_path = "/org/mpris/MediaPlayer2" 7 | )] 8 | pub trait MprisPlayer { 9 | fn next(&self) -> Result<()>; 10 | fn play_pause(&self) -> Result<()>; 11 | fn previous(&self) -> Result<()>; 12 | 13 | #[zbus(property)] 14 | fn playback_status(&self) -> Result; 15 | #[zbus(property)] 16 | fn metadata(&self) -> Result>; 17 | #[zbus(property)] 18 | fn set_volume(&self, v: f64) -> Result<()>; 19 | #[zbus(property)] 20 | fn volume(&self) -> Result; 21 | #[zbus(property)] 22 | fn can_control(&self) -> Result; 23 | } 24 | -------------------------------------------------------------------------------- /src/modules/clipboard.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | components::icons::{StaticIcon, icon}, 3 | utils::launcher::execute_command, 4 | }; 5 | use iced::Element; 6 | 7 | #[derive(Debug, Clone)] 8 | pub enum Message { 9 | Launch, 10 | } 11 | 12 | #[derive(Debug, Clone)] 13 | pub struct Clipboard { 14 | command: String, 15 | } 16 | 17 | impl Clipboard { 18 | pub fn new(command: String) -> Self { 19 | Self { command } 20 | } 21 | 22 | pub fn update(&mut self, message: Message) { 23 | match message { 24 | Message::Launch => { 25 | execute_command(self.command.clone()); 26 | } 27 | } 28 | } 29 | 30 | pub fn view(&'_ self) -> Element<'_, Message> { 31 | icon(StaticIcon::Clipboard).into() 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/modules/app_launcher.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | components::icons::{StaticIcon, icon}, 3 | utils::launcher::execute_command, 4 | }; 5 | use iced::Element; 6 | 7 | #[derive(Debug, Clone)] 8 | pub enum Message { 9 | Launch, 10 | } 11 | 12 | #[derive(Debug, Clone)] 13 | pub struct AppLauncher { 14 | command: String, 15 | } 16 | 17 | impl AppLauncher { 18 | pub fn new(command: String) -> Self { 19 | Self { command } 20 | } 21 | 22 | pub fn update(&mut self, message: Message) { 23 | match message { 24 | Message::Launch => { 25 | execute_command(self.command.clone()); 26 | } 27 | } 28 | } 29 | 30 | pub fn view(&'_ self) -> Element<'_, Message> { 31 | icon(StaticIcon::AppLauncher).into() 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /website/docs/configuration/index.md: -------------------------------------------------------------------------------- 1 | # ⚙️ Configuration 2 | 3 | All configuration options are stored in the `config.toml` file, located at: 4 | 5 | ```bash 6 | ~/.config/ashell 7 | ``` 8 | 9 | :::info 10 | 11 | Ashell does **not** create this file automatically. 12 | 13 | ::: 14 | 15 | Ashell watches this file for changes and will apply updates 16 | immediately—so you can tweak the configuration while Ashell is running. 17 | 18 | See more about the [TOML format](https://toml.io/en/). 19 | 20 | ## Command-line parameters 21 | 22 | You can pass a configuration file to Ashell using the `--config-path` parameter: 23 | 24 | ```bash 25 | ashell --config-path /path/to/config.toml 26 | ``` 27 | 28 | This allows you to use a different configuration file instead of the default one. 29 | 30 | Ashell will still watch this file for changes and apply updates immediately. 31 | -------------------------------------------------------------------------------- /src/services/mod.rs: -------------------------------------------------------------------------------- 1 | use iced::{Subscription, Task}; 2 | 3 | pub mod audio; 4 | pub mod bluetooth; 5 | pub mod brightness; 6 | pub mod compositor; 7 | pub mod idle_inhibitor; 8 | pub mod mpris; 9 | pub mod network; 10 | pub mod privacy; 11 | mod throttle; 12 | pub mod tray; 13 | pub mod upower; 14 | 15 | #[allow(unused)] 16 | #[derive(Debug, Clone)] 17 | pub enum ServiceEvent { 18 | Init(S), 19 | Update(S::UpdateEvent), 20 | Error(S::Error), 21 | } 22 | 23 | pub trait Service: ReadOnlyService { 24 | type Command; 25 | 26 | fn command(&mut self, command: Self::Command) -> Task>; 27 | } 28 | 29 | pub trait ReadOnlyService: Sized { 30 | type UpdateEvent; 31 | type Error: Clone; 32 | 33 | fn update(&mut self, event: Self::UpdateEvent); 34 | 35 | fn subscribe() -> Subscription>; 36 | } 37 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.6.0/configuration/index.md: -------------------------------------------------------------------------------- 1 | # ⚙️ Configuration 2 | 3 | All configuration options are stored in the `config.toml` file, located at: 4 | 5 | ```bash 6 | ~/.config/ashell 7 | ``` 8 | 9 | :::info 10 | 11 | Ashell does **not** create this file automatically. 12 | 13 | ::: 14 | 15 | Ashell watches this file for changes and will apply updates 16 | immediately—so you can tweak the configuration while Ashell is running. 17 | 18 | See more about the [TOML format](https://toml.io/en/). 19 | 20 | ## Command-line parameters 21 | 22 | You can pass a configuration file to Ashell using the `--config-path` parameter: 23 | 24 | ```bash 25 | ashell --config-path /path/to/config.toml 26 | ``` 27 | 28 | This allows you to use a different configuration file instead of the default one. 29 | 30 | Ashell will still watch this file for changes and apply updates immediately. 31 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.7.0/configuration/index.md: -------------------------------------------------------------------------------- 1 | # ⚙️ Configuration 2 | 3 | All configuration options are stored in the `config.toml` file, located at: 4 | 5 | ```bash 6 | ~/.config/ashell 7 | ``` 8 | 9 | :::info 10 | 11 | Ashell does **not** create this file automatically. 12 | 13 | ::: 14 | 15 | Ashell watches this file for changes and will apply updates 16 | immediately—so you can tweak the configuration while Ashell is running. 17 | 18 | See more about the [TOML format](https://toml.io/en/). 19 | 20 | ## Command-line parameters 21 | 22 | You can pass a configuration file to Ashell using the `--config-path` parameter: 23 | 24 | ```bash 25 | ashell --config-path /path/to/config.toml 26 | ``` 27 | 28 | This allows you to use a different configuration file instead of the default one. 29 | 30 | Ashell will still watch this file for changes and apply updates immediately. 31 | -------------------------------------------------------------------------------- /assets/font_README.md: -------------------------------------------------------------------------------- 1 | # Icons Font 2 | 3 | ashell uses a subset of [Nerd Fonts](https://www.nerdfonts.com/) 4 | and some custom icons for its terminal UI. 5 | 6 | The Nerd Fonts subset is created during the build process. 7 | 8 | This custom font is created from the svg files present in this folder 9 | using [GlyphrStudio](https://www.glyphrstudio.com/app/) and it's 10 | project file `ashell_custom_icon_project.gs2`. 11 | 12 | ## Custom Icons creation 13 | 14 | I'm not an expert in font creation. 15 | Right now I created svg icons using the svg resources in `raw_custom_icons_resources.svg` 16 | using [Inkscape](https://inkscape.org/) with icons for peripherals devices like keyboard, 17 | mouse, headset, etc. that combines the peripheral icon with the battery icon. 18 | 19 | To produce the final otf file i used [GlyphrStudio](https://www.glyphrstudio.com/app/). 20 | The project file is `ashell_custom_icon_project.gs2`. 21 | -------------------------------------------------------------------------------- /.github/workflows/gh-pages-test.yml: -------------------------------------------------------------------------------- 1 | name: Website CI 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | test-deploy: 10 | name: Test Docusaurus build 11 | runs-on: ubuntu-latest 12 | defaults: 13 | run: 14 | working-directory: website 15 | 16 | steps: 17 | - uses: actions/checkout@v5 18 | with: 19 | fetch-depth: 0 20 | 21 | - name: Install pnpm 22 | uses: pnpm/action-setup@v4 23 | with: 24 | version: 10 25 | 26 | - uses: actions/setup-node@v6 27 | with: 28 | node-version: 20 29 | cache: pnpm 30 | cache-dependency-path: ./website/pnpm-lock.yaml 31 | 32 | - name: Install dependencies 33 | run: pnpm i 34 | working-directory: ./website 35 | 36 | - name: Build website 37 | run: pnpm build 38 | working-directory: ./website 39 | -------------------------------------------------------------------------------- /src/utils/mod.rs: -------------------------------------------------------------------------------- 1 | use std::time::Duration; 2 | 3 | pub mod launcher; 4 | 5 | pub enum IndicatorState { 6 | Normal, 7 | Success, 8 | Warning, 9 | Danger, 10 | } 11 | 12 | pub fn format_duration(duration: &Duration) -> String { 13 | let h = duration.as_secs() / 60 / 60; 14 | let m = duration.as_secs() / 60 % 60; 15 | if h > 0 { 16 | format!("{h}h {m:>2}m") 17 | } else { 18 | format!("{m:>2}m") 19 | } 20 | } 21 | 22 | pub fn truncate_text(value: &str, max_length: u32) -> String { 23 | let length = value.len(); 24 | 25 | if length > max_length as usize { 26 | let split = max_length as usize / 2; 27 | let first_part = value.chars().take(split).collect::(); 28 | let last_part = value.chars().skip(length - split).collect::(); 29 | format!("{first_part}...{last_part}") 30 | } else { 31 | value.to_string() 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: ["main"] 6 | pull_request: 7 | branches: ["main"] 8 | types: 9 | - opened 10 | - reopened 11 | - synchronize 12 | - ready_for_review 13 | 14 | env: 15 | CARGO_TERM_COLOR: always 16 | 17 | jobs: 18 | checks: 19 | runs-on: ubuntu-24.04 20 | 21 | steps: 22 | - uses: actions/checkout@v5 23 | 24 | - name: Install dependencies 25 | run: | 26 | export DEBIAN_FRONTED=noninteractive 27 | sudo apt-get update 28 | sudo apt-get install -y pkg-config llvm-dev libclang-dev clang libxkbcommon-dev libwayland-dev dbus libpipewire-0.3-dev libpulse-dev libudev-dev 29 | 30 | - name: Format 31 | run: cargo fmt --all -- --check 32 | 33 | - name: Clippy 34 | run: cargo clippy --all-features -- -D warnings 35 | 36 | - name: Build 37 | run: cargo build 38 | -------------------------------------------------------------------------------- /website/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator. 4 | 5 | ## Installation 6 | 7 | ```bash 8 | yarn 9 | ``` 10 | 11 | ## Local Development 12 | 13 | ```bash 14 | yarn start 15 | ``` 16 | 17 | This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. 18 | 19 | ## Build 20 | 21 | ```bash 22 | yarn build 23 | ``` 24 | 25 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 26 | 27 | ## Deployment 28 | 29 | Using SSH: 30 | 31 | ```bash 32 | USE_SSH=true yarn deploy 33 | ``` 34 | 35 | Not using SSH: 36 | 37 | ```bash 38 | GIT_USER= yarn deploy 39 | ``` 40 | 41 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. 42 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.6.0/configuration/modules/keyboard.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 7 3 | --- 4 | 5 | # Keyboard 6 | 7 | There are two keyboard modules available in the status bar. 8 | 9 | ## Keyboard Layout 10 | 11 | The Keyboard Layout module displays the current keyboard layout and allows 12 | switching between layouts by clicking on the module. 13 | 14 | You can add an optional configuration to map a keyboard layout label 15 | to another label using the `labels` configuration. 16 | 17 | ### Example 18 | 19 | In this example we're mapping the "English (US)" layout to the 🇺🇸 flag and 20 | the "Italian" layout to the 🇮🇹 flag. 21 | 22 | ```toml 23 | [keyboard_layout.labels] 24 | "English (US)" = "🇺🇸" 25 | "Italian" = "🇮🇹" 26 | ``` 27 | 28 | ## Keyboard Submap 29 | 30 | This module displays the current keyboard submap in use. You can find more information 31 | about submap in the [Hyprland documentation](https://wiki.hyprland.org/Hyprland-Submaps/). 32 | -------------------------------------------------------------------------------- /website/src/pages/index.module.css: -------------------------------------------------------------------------------- 1 | .mainBar { 2 | background-image: url("/img/main_bar.png"); 3 | background-size: 90%; 4 | background-position: center 12px; 5 | background-repeat: no-repeat; 6 | } 7 | 8 | .container { 9 | display: flex; 10 | flex-direction: column; 11 | padding-top: 48px; 12 | gap: 48px; 13 | align-items: center; 14 | justify-content: center; 15 | } 16 | 17 | .logo { 18 | display: flex; 19 | flex-direction: row; 20 | gap: 48px; 21 | align-items: center; 22 | justify-content: center; 23 | } 24 | 25 | .logoText { 26 | height: 150px; 27 | } 28 | 29 | .tagline { 30 | margin: 0; 31 | } 32 | 33 | @media screen and (max-width: 996px) { 34 | .logo { 35 | flex-direction: column; 36 | } 37 | 38 | .mainBar { 39 | background-image: url("/img/main_bar_small.png"); 40 | background-size: 96%; 41 | background-position: center 12px; 42 | background-repeat: no-repeat; 43 | } 44 | } 45 | 46 | .buttons { 47 | display: flex; 48 | align-items: center; 49 | justify-content: center; 50 | } 51 | -------------------------------------------------------------------------------- /website/docs/configuration/modules/updates.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | --- 4 | 5 | # Updates 6 | 7 | This module provides information about available updates for the system. 8 | 9 | To configure this module, you need to specify a command that 10 | will check for new system updates and a command that will launch the system updates. 11 | 12 | :::info 13 | 14 | Without this configuration, the module will not appear in the status bar. 15 | 16 | ::: 17 | 18 | The check command should return a list of updates, 19 | one package per line in the following format: 20 | 21 | `package_name version_from -> version_to` 22 | 23 | ## Output Example 24 | 25 | ```text 26 | calf 0.90.7-1 -> 0.90.8-1 27 | hyprutils 0.8.0-1 -> 0.8.1-1 28 | lazygit 0.52.0-1 -> 0.53.0-1 29 | ``` 30 | 31 | ## Example 32 | 33 | In this example, I am using an Arch Linux distribution, with `paru` as my 34 | AUR package manager and `alacritty` as a terminal emulator. 35 | 36 | ```toml 37 | [updates] 38 | check_cmd = "checkupdates; paru -Qua" 39 | update_cmd = 'alacritty -e bash -c "paru; echo Done - Press enter to exit; read" &' 40 | ``` 41 | -------------------------------------------------------------------------------- /website/docs/configuration/appearance/theme.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | --- 4 | 5 | # Theme 6 | 7 | ## Catppuccin Mocha 8 | 9 | ```toml 10 | [appearance] 11 | 12 | success_color = "#a6e3a1" 13 | text_color = "#cdd6f4" 14 | 15 | workspace_colors = [ "#fab387", "#b4befe", "#cba6f7" ] 16 | 17 | [appearance.primary_color] 18 | base = "#fab387" 19 | text = "#1e1e2e" 20 | 21 | [appearance.danger_color] 22 | base = "#f38ba8" 23 | weak = "#f9e2af" 24 | 25 | [appearance.background_color] 26 | base = "#1e1e2e" 27 | weak = "#313244" 28 | strong = "#45475a" 29 | 30 | [appearance.secondary_color] 31 | base = "#11111b" 32 | strong = "#1b1b25" 33 | ``` 34 | 35 | ## Tokyo Night - night 36 | 37 | ```toml 38 | [appearance] 39 | 40 | primary_color = "#7aa2f7" 41 | success_color = "#9ece6a" 42 | text_color = "#a9b1d6" 43 | 44 | workspace_colors = [ "#7aa2f7", "#9ece6a" ] 45 | 46 | [appearance.danger_color] 47 | base = "#f7768e" 48 | weak = "#e0af68" 49 | 50 | [appearance.background_color] 51 | base = "#1a1b26" 52 | weak = "#24273a" 53 | strong = "#414868" 54 | 55 | [appearance.secondary_color] 56 | base = "#0c0d14" 57 | ``` 58 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.6.0/configuration/modules/updates.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | --- 4 | 5 | # Updates 6 | 7 | This module provides information about available updates for the system. 8 | 9 | To configure this module, you need to specify a command that 10 | will check for new system updates and a command that will launch the system updates. 11 | 12 | :::info 13 | 14 | Without this configuration, the module will not appear in the status bar. 15 | 16 | ::: 17 | 18 | The check command should return a list of updates, 19 | one package per line in the following format: 20 | 21 | `package_name version_from -> version_to` 22 | 23 | ## Output Example 24 | 25 | ```text 26 | calf 0.90.7-1 -> 0.90.8-1 27 | hyprutils 0.8.0-1 -> 0.8.1-1 28 | lazygit 0.52.0-1 -> 0.53.0-1 29 | ``` 30 | 31 | ## Example 32 | 33 | In this example, I am using an Arch Linux distribution, with `paru` as my 34 | AUR package manager and `alacritty` as a terminal emulator. 35 | 36 | ```toml 37 | [updates] 38 | check_cmd = "checkupdates; paru -Qua" 39 | update_cmd = 'alacritty -e bash -c "paru; echo Done - Press enter to exit; read" &' 40 | ``` 41 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.7.0/configuration/modules/updates.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | --- 4 | 5 | # Updates 6 | 7 | This module provides information about available updates for the system. 8 | 9 | To configure this module, you need to specify a command that 10 | will check for new system updates and a command that will launch the system updates. 11 | 12 | :::info 13 | 14 | Without this configuration, the module will not appear in the status bar. 15 | 16 | ::: 17 | 18 | The check command should return a list of updates, 19 | one package per line in the following format: 20 | 21 | `package_name version_from -> version_to` 22 | 23 | ## Output Example 24 | 25 | ```text 26 | calf 0.90.7-1 -> 0.90.8-1 27 | hyprutils 0.8.0-1 -> 0.8.1-1 28 | lazygit 0.52.0-1 -> 0.53.0-1 29 | ``` 30 | 31 | ## Example 32 | 33 | In this example, I am using an Arch Linux distribution, with `paru` as my 34 | AUR package manager and `alacritty` as a terminal emulator. 35 | 36 | ```toml 37 | [updates] 38 | check_cmd = "checkupdates; paru -Qua" 39 | update_cmd = 'alacritty -e bash -c "paru; echo Done - Press enter to exit; read" &' 40 | ``` 41 | -------------------------------------------------------------------------------- /.github/workflows/gh-pages-deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy to GitHub Pages 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | jobs: 8 | deploy: 9 | name: Deploy Docusaurus 10 | runs-on: ubuntu-latest 11 | defaults: 12 | run: 13 | working-directory: website 14 | permissions: 15 | contents: write 16 | 17 | steps: 18 | - uses: actions/checkout@v5 19 | with: 20 | fetch-depth: 0 21 | 22 | - name: Install pnpm 23 | uses: pnpm/action-setup@v4 24 | with: 25 | version: 10 26 | 27 | - uses: actions/setup-node@v6 28 | with: 29 | node-version: 20 30 | cache: pnpm 31 | cache-dependency-path: ./website/pnpm-lock.yaml 32 | 33 | - name: Install dependencies 34 | run: pnpm i 35 | 36 | - name: Build website 37 | run: pnpm build 38 | 39 | - name: Deploy 40 | id: deployment 41 | uses: peaceiris/actions-gh-pages@v4 42 | with: 43 | github_token: ${{ secrets.GITHUB_TOKEN }} 44 | enable_jekyll: false 45 | publish_dir: ./website/build 46 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.6.0/configuration/appearance/theme.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | --- 4 | 5 | # Theme 6 | 7 | ## Catppuccin Mocha 8 | 9 | ```toml 10 | [appearance] 11 | 12 | success_color = "#a6e3a1" 13 | text_color = "#cdd6f4" 14 | 15 | workspace_colors = [ "#fab387", "#b4befe", "#cba6f7" ] 16 | 17 | [appearance.primary_color] 18 | base = "#fab387" 19 | text = "#1e1e2e" 20 | 21 | [appearance.danger_color] 22 | base = "#f38ba8" 23 | weak = "#f9e2af" 24 | 25 | [appearance.background_color] 26 | base = "#1e1e2e" 27 | weak = "#313244" 28 | strong = "#45475a" 29 | 30 | [appearance.secondary_color] 31 | base = "#11111b" 32 | strong = "#1b1b25" 33 | ``` 34 | 35 | ## Tokyo Night - night 36 | 37 | ```toml 38 | [appearance] 39 | 40 | primary_color = "#7aa2f7" 41 | success_color = "#9ece6a" 42 | text_color = "#a9b1d6" 43 | 44 | workspace_colors = [ "#7aa2f7", "#9ece6a" ] 45 | 46 | [appearance.danger_color] 47 | base = "#f7768e" 48 | weak = "#e0af68" 49 | 50 | [appearance.background_color] 51 | base = "#1a1b26" 52 | weak = "#24273a" 53 | strong = "#414868" 54 | 55 | [appearance.secondary_color] 56 | base = "#0c0d14" 57 | ``` 58 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.7.0/configuration/appearance/theme.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | --- 4 | 5 | # Theme 6 | 7 | ## Catppuccin Mocha 8 | 9 | ```toml 10 | [appearance] 11 | 12 | success_color = "#a6e3a1" 13 | text_color = "#cdd6f4" 14 | 15 | workspace_colors = [ "#fab387", "#b4befe", "#cba6f7" ] 16 | 17 | [appearance.primary_color] 18 | base = "#fab387" 19 | text = "#1e1e2e" 20 | 21 | [appearance.danger_color] 22 | base = "#f38ba8" 23 | weak = "#f9e2af" 24 | 25 | [appearance.background_color] 26 | base = "#1e1e2e" 27 | weak = "#313244" 28 | strong = "#45475a" 29 | 30 | [appearance.secondary_color] 31 | base = "#11111b" 32 | strong = "#1b1b25" 33 | ``` 34 | 35 | ## Tokyo Night - night 36 | 37 | ```toml 38 | [appearance] 39 | 40 | primary_color = "#7aa2f7" 41 | success_color = "#9ece6a" 42 | text_color = "#a9b1d6" 43 | 44 | workspace_colors = [ "#7aa2f7", "#9ece6a" ] 45 | 46 | [appearance.danger_color] 47 | base = "#f7768e" 48 | weak = "#e0af68" 49 | 50 | [appearance.background_color] 51 | base = "#1a1b26" 52 | weak = "#24273a" 53 | strong = "#414868" 54 | 55 | [appearance.secondary_color] 56 | base = "#0c0d14" 57 | ``` 58 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Simone Camito (Zibo) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/services/network/iwd_dbus/basic_service_set.rs: -------------------------------------------------------------------------------- 1 | //! # D-Bus interface proxy for: `net.connman.iwd.BasicServiceSet` 2 | //! 3 | //! This code was generated by `zbus-xmlgen` `5.1.0` from D-Bus introspection data. 4 | //! 5 | //! You may prefer to adapt it, instead of using it verbatim. 6 | //! 7 | //! More information can be found in the [Writing a client proxy] section of the zbus 8 | //! documentation. 9 | //! 10 | //! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the 11 | //! following zbus API can be used: 12 | //! 13 | //! * [`zbus::fdo::IntrospectableProxy`] 14 | //! * [`zbus::fdo::PropertiesProxy`] 15 | //! 16 | //! Consequently `zbus-xmlgen` did not generate code for the above interfaces. 17 | //! 18 | //! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html 19 | //! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces, 20 | use zbus::proxy; 21 | #[proxy(interface = "net.connman.iwd.BasicServiceSet", assume_defaults = true)] 22 | pub trait BasicServiceSet { 23 | /// Address property 24 | #[zbus(property)] 25 | fn address(&self) -> zbus::Result; 26 | } 27 | -------------------------------------------------------------------------------- /src/services/network/iwd_dbus/daemon.rs: -------------------------------------------------------------------------------- 1 | //! # D-Bus interface proxy for: `net.connman.iwd.Daemon` 2 | //! 3 | //! This code was generated by `zbus-xmlgen` `5.1.0` from D-Bus introspection data. 4 | //! 5 | //! You may prefer to adapt it, instead of using it verbatim. 6 | //! 7 | //! More information can be found in the [Writing a client proxy] section of the zbus 8 | //! documentation. 9 | //! 10 | //! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the 11 | //! following zbus API can be used: 12 | //! 13 | //! * [`zbus::fdo::IntrospectableProxy`] 14 | //! * [`zbus::fdo::PropertiesProxy`] 15 | //! 16 | //! Consequently `zbus-xmlgen` did not generate code for the above interfaces. 17 | //! 18 | //! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html 19 | //! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces, 20 | use zbus::proxy; 21 | #[proxy(interface = "net.connman.iwd.Daemon", assume_defaults = true)] 22 | pub trait Daemon { 23 | /// GetInfo method 24 | fn get_info( 25 | &self, 26 | ) -> zbus::Result>; 27 | } 28 | -------------------------------------------------------------------------------- /website/docs/intro.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # 🚀 Getting Started 6 | 7 | Ashell is a status bar for Hyprland and Niri, written in Rust using the `iced` library. 8 | 9 | ## Does it only work on Hyprland and Niri? 10 | 11 | This project originally supported only Hyprland, primarily because 12 | it is the compositor I use to test ashell. 13 | 14 | Thanks to community support, ashell now supports Niri as well. 15 | 16 | In the future, we plan to expand this functionality to other 17 | Wayland compositors. 18 | 19 | ## Features 20 | 21 | - App Launcher button 22 | - Clipboard button 23 | - OS Updates indicator 24 | - Hyprland/Niri Active Window 25 | - Hyprland/Niri Workspaces 26 | - System Information (CPU, RAM, Temperature) 27 | - Hyprland/Niri Keyboard Layout 28 | - Hyprland Keyboard Submap 29 | - Tray 30 | - Date and Time 31 | - Privacy indicators (microphone, camera, and screen sharing usage) 32 | - Media Player 33 | - Settings Panel 34 | - Power menu 35 | - Battery information 36 | - Audio sources and sinks 37 | - Screen brightness 38 | - Network controls 39 | - VPN 40 | - Bluetooth 41 | - Power profiles 42 | - Idle inhibitor 43 | - Airplane mode 44 | - Custom Modules 45 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.7.0/intro.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # 🚀 Getting Started 6 | 7 | Ashell is a status bar for Hyprland and Niri, written in Rust using the `iced` library. 8 | 9 | ## Does it only work on Hyprland and Niri? 10 | 11 | This project originally supported only Hyprland, primarily because 12 | it is the compositor I use to test ashell. 13 | 14 | Thanks to community support, ashell now supports Niri as well. 15 | 16 | In the future, we plan to expand this functionality to other 17 | Wayland compositors. 18 | 19 | ## Features 20 | 21 | - App Launcher button 22 | - Clipboard button 23 | - OS Updates indicator 24 | - Hyprland/Niri Active Window 25 | - Hyprland/Niri Workspaces 26 | - System Information (CPU, RAM, Temperature) 27 | - Hyprland/Niri Keyboard Layout 28 | - Hyprland Keyboard Submap 29 | - Tray 30 | - Date and Time 31 | - Privacy indicators (microphone, camera, and screen sharing usage) 32 | - Media Player 33 | - Settings Panel 34 | - Power menu 35 | - Battery information 36 | - Audio sources and sinks 37 | - Screen brightness 38 | - Network controls 39 | - VPN 40 | - Bluetooth 41 | - Power profiles 42 | - Idle inhibitor 43 | - Airplane mode 44 | - Custom Modules 45 | -------------------------------------------------------------------------------- /src/services/network/iwd_dbus/station_diagnostic.rs: -------------------------------------------------------------------------------- 1 | //! # D-Bus interface proxy for: `net.connman.iwd.StationDiagnostic` 2 | //! 3 | //! This code was generated by `zbus-xmlgen` `5.1.0` from D-Bus introspection data. 4 | //! 5 | //! You may prefer to adapt it, instead of using it verbatim. 6 | //! 7 | //! More information can be found in the [Writing a client proxy] section of the zbus 8 | //! documentation. 9 | //! 10 | //! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the 11 | //! following zbus API can be used: 12 | //! 13 | //! * [`zbus::fdo::IntrospectableProxy`] 14 | //! * [`zbus::fdo::PropertiesProxy`] 15 | //! 16 | //! Consequently `zbus-xmlgen` did not generate code for the above interfaces. 17 | //! 18 | //! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html 19 | //! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces, 20 | use zbus::proxy; 21 | #[proxy( 22 | interface = "net.connman.iwd.StationDiagnostic", 23 | assume_defaults = true 24 | )] 25 | pub trait StationDiagnostic { 26 | /// GetDiagnostics method 27 | fn get_diagnostics( 28 | &self, 29 | ) -> zbus::Result>; 30 | } 31 | -------------------------------------------------------------------------------- /website/docs/configuration/modules/keyboard.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 7 3 | --- 4 | 5 | # Keyboard 6 | 7 | There are two keyboard modules available in the status bar. 8 | 9 | ## Keyboard Layout 10 | 11 | The Keyboard Layout module displays the current keyboard layout and allows 12 | switching between layouts by clicking on the module. 13 | 14 | You can add an optional configuration to map a keyboard layout label 15 | to another label using the `labels` configuration. 16 | 17 | :::warning 18 | 19 | Ashell comes with a set of default icons that are used internally. 20 | 21 | If you decide to use a font icon in your keyboard layout configuration remember 22 | to install the font with that icon on your system. 23 | 24 | For example you can use [Nerd Fonts](https://www.nerdfonts.com/) 25 | 26 | ::: 27 | 28 | ### Example 29 | 30 | In this example we're mapping the "English (US)" layout to the 🇺🇸 flag and 31 | the "Italian" layout to the 🇮🇹 flag. 32 | 33 | ```toml 34 | [keyboard_layout.labels] 35 | "English (US)" = "🇺🇸" 36 | "Italian" = "🇮🇹" 37 | ``` 38 | 39 | ## Keyboard Submap 40 | 41 | This module displays the current keyboard submap in use. You can find more information 42 | about submap in the [Hyprland documentation](https://wiki.hypr.land/Configuring/Binds/#submaps). 43 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.7.0/configuration/modules/keyboard.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 7 3 | --- 4 | 5 | # Keyboard 6 | 7 | There are two keyboard modules available in the status bar. 8 | 9 | ## Keyboard Layout 10 | 11 | The Keyboard Layout module displays the current keyboard layout and allows 12 | switching between layouts by clicking on the module. 13 | 14 | You can add an optional configuration to map a keyboard layout label 15 | to another label using the `labels` configuration. 16 | 17 | :::warning 18 | 19 | Ashell comes with a set of default icons that are used internally. 20 | 21 | If you decide to use a font icon in your keyboard layout configuration remember 22 | to install the font with that icon on your system. 23 | 24 | For example you can use [Nerd Fonts](https://www.nerdfonts.com/) 25 | 26 | ::: 27 | 28 | ### Example 29 | 30 | In this example we're mapping the "English (US)" layout to the 🇺🇸 flag and 31 | the "Italian" layout to the 🇮🇹 flag. 32 | 33 | ```toml 34 | [keyboard_layout.labels] 35 | "English (US)" = "🇺🇸" 36 | "Italian" = "🇮🇹" 37 | ``` 38 | 39 | ## Keyboard Submap 40 | 41 | This module displays the current keyboard submap in use. You can find more information 42 | about submap in the [Hyprland documentation](https://wiki.hypr.land/Configuring/Binds/#submaps). 43 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.6.0/intro.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # 🚀 Getting Started 6 | 7 | Ashell is a status bar for Hyprland, written in Rust using the `iced` library. 8 | 9 | ## Does it only work on Hyprland? 10 | 11 | While it’s currently tailored for Hyprland, it could potentially 12 | work with other compositors. 13 | 14 | However, it currently relies on [hyprland-rs](https://github.com/hyprland-community/hyprland-rs) 15 | to gather information about the active window and workspaces. 16 | I haven’t implemented any feature flags to disable these functionalities or 17 | provide alternative methods to obtain this data. 18 | 19 | ## Features 20 | 21 | - App Launcher button 22 | - Clipboard button 23 | - OS Updates indicator 24 | - Hyprland Active Window 25 | - Hyprland Workspaces 26 | - System Information (CPU, RAM, Temperature) 27 | - Hyprland Keyboard Layout 28 | - Hyprland Keyboard Submap 29 | - Tray 30 | - Date and Time 31 | - Privacy indicators (microphone, camera, and screen sharing usage) 32 | - Media Player 33 | - Settings Panel 34 | - Power menu 35 | - Battery information 36 | - Audio sources and sinks 37 | - Screen brightness 38 | - Network controls 39 | - VPN 40 | - Bluetooth 41 | - Power profiles 42 | - Idle inhibitor 43 | - Airplane mode 44 | - Custom Modules 45 | -------------------------------------------------------------------------------- /.github/workflows/nix-ci.yml: -------------------------------------------------------------------------------- 1 | name: Nix CI 2 | 3 | on: 4 | push: 5 | branches: ["main"] 6 | pull_request: 7 | branches: ["main"] 8 | types: 9 | - opened 10 | - reopened 11 | - synchronize 12 | - ready_for_review 13 | 14 | jobs: 15 | checks-build: 16 | runs-on: ubuntu-24.04 17 | permissions: 18 | contents: write 19 | actions: write 20 | 21 | steps: 22 | - uses: actions/checkout@v5 23 | 24 | - uses: nixbuild/nix-quick-install-action@v34 25 | 26 | - name: Restore and save Nix store 27 | uses: nix-community/cache-nix-action@v6 28 | with: 29 | primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} 30 | # do purge caches 31 | purge: true 32 | # purge all versions of the cache 33 | purge-prefixes: build-${{ runner.os }}- 34 | # created more than 0 seconds ago relative to the start of the `Post Restore` phase 35 | purge-created: 0 36 | # except the version with the `primary-key`, if it exists 37 | purge-primary-key: never 38 | # collect garbage until Nix store size (in bytes) is at most this number 39 | # before trying to save a new cache 40 | # 1 GB = 1073741824 B 41 | gc-max-store-size-linux: 1073741824 42 | 43 | - name: Nix build- 44 | run: nix build 45 | -------------------------------------------------------------------------------- /src/services/network/iwd_dbus/service_manager.rs: -------------------------------------------------------------------------------- 1 | //! # D-Bus interface proxy for: `net.connman.iwd.p2p.ServiceManager` 2 | //! 3 | //! This code was generated by `zbus-xmlgen` `5.1.0` from D-Bus introspection data. 4 | //! 5 | //! You may prefer to adapt it, instead of using it verbatim. 6 | //! 7 | //! More information can be found in the [Writing a client proxy] section of the zbus 8 | //! documentation. 9 | //! 10 | //! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the 11 | //! following zbus API can be used: 12 | //! 13 | //! * [`zbus::fdo::IntrospectableProxy`] 14 | //! * [`zbus::fdo::PropertiesProxy`] 15 | //! 16 | //! Consequently `zbus-xmlgen` did not generate code for the above interfaces. 17 | //! 18 | //! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html 19 | //! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces, 20 | use zbus::proxy; 21 | #[proxy( 22 | interface = "net.connman.iwd.p2p.ServiceManager", 23 | assume_defaults = true 24 | )] 25 | pub trait ServiceManager { 26 | /// RegisterDisplayService method 27 | fn register_display_service( 28 | &self, 29 | properties: std::collections::HashMap<&str, &zbus::zvariant::Value<'_>>, 30 | ) -> zbus::Result<()>; 31 | 32 | /// UnregisterDisplayService method 33 | fn unregister_display_service(&self) -> zbus::Result<()>; 34 | } 35 | -------------------------------------------------------------------------------- /src/services/network/iwd_dbus/simple_configuration.rs: -------------------------------------------------------------------------------- 1 | //! # D-Bus interface proxy for: `net.connman.iwd.SimpleConfiguration` 2 | //! 3 | //! This code was generated by `zbus-xmlgen` `5.1.0` from D-Bus introspection data. 4 | //! 5 | //! You may prefer to adapt it, instead of using it verbatim. 6 | //! 7 | //! More information can be found in the [Writing a client proxy] section of the zbus 8 | //! documentation. 9 | //! 10 | //! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the 11 | //! following zbus API can be used: 12 | //! 13 | //! * [`zbus::fdo::IntrospectableProxy`] 14 | //! * [`zbus::fdo::PropertiesProxy`] 15 | //! 16 | //! Consequently `zbus-xmlgen` did not generate code for the above interfaces. 17 | //! 18 | //! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html 19 | //! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces, 20 | use zbus::proxy; 21 | #[proxy( 22 | interface = "net.connman.iwd.SimpleConfiguration", 23 | assume_defaults = true 24 | )] 25 | pub trait SimpleConfiguration { 26 | /// Cancel method 27 | fn cancel(&self) -> zbus::Result<()>; 28 | 29 | /// GeneratePin method 30 | fn generate_pin(&self) -> zbus::Result; 31 | 32 | /// PushButton method 33 | fn push_button(&self) -> zbus::Result<()>; 34 | 35 | /// StartPin method 36 | fn start_pin(&self, pin: &str) -> zbus::Result<()>; 37 | } 38 | -------------------------------------------------------------------------------- /src/modules/keyboard_submap.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | services::{ReadOnlyService, ServiceEvent, compositor::CompositorService}, 3 | theme::AshellTheme, 4 | }; 5 | use iced::{Element, Subscription, widget::text}; 6 | 7 | #[derive(Debug, Clone)] 8 | pub enum Message { 9 | ServiceEvent(ServiceEvent), 10 | } 11 | 12 | #[derive(Debug, Clone)] 13 | pub struct KeyboardSubmap { 14 | service: Option, 15 | } 16 | 17 | impl KeyboardSubmap { 18 | pub fn default() -> Self { 19 | Self { service: None } 20 | } 21 | 22 | pub fn update(&mut self, message: Message) { 23 | match message { 24 | Message::ServiceEvent(event) => match event { 25 | ServiceEvent::Init(s) => self.service = Some(s), 26 | ServiceEvent::Update(e) => { 27 | if let Some(service) = &mut self.service { 28 | service.update(e); 29 | } 30 | } 31 | _ => {} 32 | }, 33 | } 34 | } 35 | 36 | pub fn view(&self, _: &AshellTheme) -> Option> { 37 | let submap = self.service.as_ref()?.submap.as_ref()?; 38 | 39 | if !submap.is_empty() { 40 | Some(text(submap).into()) 41 | } else { 42 | None 43 | } 44 | } 45 | 46 | pub fn subscription(&self) -> Subscription { 47 | CompositorService::subscribe().map(Message::ServiceEvent) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /website/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "website", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "docusaurus": "docusaurus", 7 | "start": "docusaurus start", 8 | "build": "docusaurus build", 9 | "swizzle": "docusaurus swizzle", 10 | "deploy": "docusaurus deploy", 11 | "clear": "docusaurus clear", 12 | "serve": "docusaurus serve", 13 | "write-translations": "docusaurus write-translations", 14 | "write-heading-ids": "docusaurus write-heading-ids", 15 | "typecheck": "tsc" 16 | }, 17 | "dependencies": { 18 | "@docusaurus/core": "3.9.2", 19 | "@docusaurus/preset-classic": "3.9.2", 20 | "@easyops-cn/docusaurus-search-local": "^0.52.2", 21 | "@mdx-js/react": "^3.1.1", 22 | "clsx": "^2.1.1", 23 | "prism-react-renderer": "^2.4.1", 24 | "react": "^19.2.0", 25 | "react-dom": "19.2.0" 26 | }, 27 | "devDependencies": { 28 | "@docusaurus/module-type-aliases": "3.9.2", 29 | "@docusaurus/tsconfig": "3.9.2", 30 | "@docusaurus/types": "3.9.2", 31 | "typescript": "~5.9.3" 32 | }, 33 | "browserslist": { 34 | "production": [ 35 | ">0.5%", 36 | "not dead", 37 | "not op_mini all" 38 | ], 39 | "development": [ 40 | "last 3 chrome version", 41 | "last 3 firefox version", 42 | "last 5 safari version" 43 | ] 44 | }, 45 | "engines": { 46 | "node": ">=18.0" 47 | }, 48 | "packageManager": "pnpm@10.12.4+sha512.5ea8b0deed94ed68691c9bad4c955492705c5eeb8a87ef86bc62c74a26b037b08ff9570f108b2e4dbd1dd1a9186fea925e527f141c648e85af45631074680184" 49 | } 50 | -------------------------------------------------------------------------------- /website/docs/configuration/full_config.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 4 3 | --- 4 | 5 | # Full Configuration Example 6 | 7 | ```toml 8 | log_level = "warn" 9 | outputs = { Targets = ["eDP-1"] } 10 | position = "Top" 11 | app_launcher_cmd = "walker" 12 | 13 | [modules] 14 | left = [ [ "appLauncher", "Updates", "Workspaces" ] ] 15 | center = [ "WindowTitle" ] 16 | right = [ "SystemInfo", [ "Tray", "Clock", "Privacy", "Settings" ] ] 17 | 18 | [updates] 19 | check_cmd = "checkupdates; paru -Qua" 20 | update_cmd = 'alacritty -e bash -c "paru; echo Done - Press enter to exit; read" &' 21 | 22 | [workspaces] 23 | enable_workspace_filling = true 24 | 25 | [[CustomModule]] 26 | name = "appLauncher" 27 | icon = "󱗼" 28 | command = "walker" 29 | 30 | [window_title] 31 | truncate_title_after_length = 100 32 | 33 | [settings] 34 | lock_cmd = "playerctl --all-players pause; nixGL hyprlock &" 35 | audio_sinks_more_cmd = "pavucontrol -t 3" 36 | audio_sources_more_cmd = "pavucontrol -t 4" 37 | wifi_more_cmd = "nm-connection-editor" 38 | vpn_more_cmd = "nm-connection-editor" 39 | bluetooth_more_cmd = "blueberry" 40 | 41 | [appearance] 42 | style = "Islands" 43 | 44 | primary_color = "#7aa2f7" 45 | success_color = "#9ece6a" 46 | text_color = "#a9b1d6" 47 | workspace_colors = [ "#7aa2f7", "#9ece6a" ] 48 | special_workspace_colors = [ "#7aa2f7", "#9ece6a" ] 49 | 50 | [appearance.danger_color] 51 | base = "#f7768e" 52 | weak = "#e0af68" 53 | 54 | [appearance.background_color] 55 | base = "#1a1b26" 56 | weak = "#24273a" 57 | strong = "#414868" 58 | 59 | [appearance.secondary_color] 60 | base = "#0c0d14" 61 | 62 | ``` 63 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.6.0/configuration/full_config.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 4 3 | --- 4 | 5 | # Full Configuration Example 6 | 7 | ```toml 8 | log_level = "warn" 9 | outputs = { Targets = ["eDP-1"] } 10 | position = "Top" 11 | app_launcher_cmd = "walker" 12 | 13 | [modules] 14 | left = [ [ "appLauncher", "Updates", "Workspaces" ] ] 15 | center = [ "WindowTitle" ] 16 | right = [ "SystemInfo", [ "Tray", "Clock", "Privacy", "Settings" ] ] 17 | 18 | [updates] 19 | check_cmd = "checkupdates; paru -Qua" 20 | update_cmd = 'alacritty -e bash -c "paru; echo Done - Press enter to exit; read" &' 21 | 22 | [workspaces] 23 | enable_workspace_filling = true 24 | 25 | [[CustomModule]] 26 | name = "appLauncher" 27 | icon = "󱗼" 28 | command = "walker" 29 | 30 | [window_title] 31 | truncate_title_after_length = 100 32 | 33 | [settings] 34 | lock_cmd = "playerctl --all-players pause; nixGL hyprlock &" 35 | audio_sinks_more_cmd = "pavucontrol -t 3" 36 | audio_sources_more_cmd = "pavucontrol -t 4" 37 | wifi_more_cmd = "nm-connection-editor" 38 | vpn_more_cmd = "nm-connection-editor" 39 | bluetooth_more_cmd = "blueberry" 40 | 41 | [appearance] 42 | style = "Islands" 43 | 44 | primary_color = "#7aa2f7" 45 | success_color = "#9ece6a" 46 | text_color = "#a9b1d6" 47 | workspace_colors = [ "#7aa2f7", "#9ece6a" ] 48 | special_workspace_colors = [ "#7aa2f7", "#9ece6a" ] 49 | 50 | [appearance.danger_color] 51 | base = "#f7768e" 52 | weak = "#e0af68" 53 | 54 | [appearance.background_color] 55 | base = "#1a1b26" 56 | weak = "#24273a" 57 | strong = "#414868" 58 | 59 | [appearance.secondary_color] 60 | base = "#0c0d14" 61 | 62 | ``` 63 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.7.0/configuration/full_config.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 4 3 | --- 4 | 5 | # Full Configuration Example 6 | 7 | ```toml 8 | log_level = "warn" 9 | outputs = { Targets = ["eDP-1"] } 10 | position = "Top" 11 | app_launcher_cmd = "walker" 12 | 13 | [modules] 14 | left = [ [ "appLauncher", "Updates", "Workspaces" ] ] 15 | center = [ "WindowTitle" ] 16 | right = [ "SystemInfo", [ "Tray", "Clock", "Privacy", "Settings" ] ] 17 | 18 | [updates] 19 | check_cmd = "checkupdates; paru -Qua" 20 | update_cmd = 'alacritty -e bash -c "paru; echo Done - Press enter to exit; read" &' 21 | 22 | [workspaces] 23 | enable_workspace_filling = true 24 | 25 | [[CustomModule]] 26 | name = "appLauncher" 27 | icon = "󱗼" 28 | command = "walker" 29 | 30 | [window_title] 31 | truncate_title_after_length = 100 32 | 33 | [settings] 34 | lock_cmd = "playerctl --all-players pause; nixGL hyprlock &" 35 | audio_sinks_more_cmd = "pavucontrol -t 3" 36 | audio_sources_more_cmd = "pavucontrol -t 4" 37 | wifi_more_cmd = "nm-connection-editor" 38 | vpn_more_cmd = "nm-connection-editor" 39 | bluetooth_more_cmd = "blueberry" 40 | 41 | [appearance] 42 | style = "Islands" 43 | 44 | primary_color = "#7aa2f7" 45 | success_color = "#9ece6a" 46 | text_color = "#a9b1d6" 47 | workspace_colors = [ "#7aa2f7", "#9ece6a" ] 48 | special_workspace_colors = [ "#7aa2f7", "#9ece6a" ] 49 | 50 | [appearance.danger_color] 51 | base = "#f7768e" 52 | weak = "#e0af68" 53 | 54 | [appearance.background_color] 55 | base = "#1a1b26" 56 | weak = "#24273a" 57 | strong = "#414868" 58 | 59 | [appearance.secondary_color] 60 | base = "#0c0d14" 61 | 62 | ``` 63 | -------------------------------------------------------------------------------- /src/services/network/iwd_dbus/adapter.rs: -------------------------------------------------------------------------------- 1 | //! # D-Bus interface proxy for: `net.connman.iwd.Adapter` 2 | //! 3 | //! This code was generated by `zbus-xmlgen` `5.1.0` from D-Bus introspection data. 4 | //! 5 | //! You may prefer to adapt it, instead of using it verbatim. 6 | //! 7 | //! More information can be found in the [Writing a client proxy] section of the zbus 8 | //! documentation. 9 | //! 10 | //! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the 11 | //! following zbus API can be used: 12 | //! 13 | //! * [`zbus::fdo::IntrospectableProxy`] 14 | //! * [`zbus::fdo::PropertiesProxy`] 15 | //! 16 | //! Consequently `zbus-xmlgen` did not generate code for the above interfaces. 17 | //! 18 | //! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html 19 | //! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces, 20 | use zbus::proxy; 21 | #[proxy(interface = "net.connman.iwd.Adapter", assume_defaults = true)] 22 | pub trait Adapter { 23 | /// Model property 24 | #[zbus(property)] 25 | fn model(&self) -> zbus::Result; 26 | 27 | /// Name property 28 | #[zbus(property)] 29 | fn name(&self) -> zbus::Result; 30 | 31 | /// Powered property 32 | #[zbus(property)] 33 | fn powered(&self) -> zbus::Result; 34 | #[zbus(property)] 35 | fn set_powered(&self, value: bool) -> zbus::Result<()>; 36 | 37 | /// SupportedModes property 38 | #[zbus(property)] 39 | fn supported_modes(&self) -> zbus::Result>; 40 | 41 | /// Vendor property 42 | #[zbus(property)] 43 | fn vendor(&self) -> zbus::Result; 44 | } 45 | -------------------------------------------------------------------------------- /src/modules/clock.rs: -------------------------------------------------------------------------------- 1 | use crate::{config::ClockModuleConfig, theme::AshellTheme}; 2 | use chrono::{DateTime, Local}; 3 | use iced::{Element, Subscription, time::every, widget::text}; 4 | use std::time::Duration; 5 | 6 | #[derive(Debug, Clone)] 7 | pub enum Message { 8 | Update, 9 | } 10 | 11 | pub struct Clock { 12 | config: ClockModuleConfig, 13 | date: DateTime, 14 | } 15 | 16 | impl Clock { 17 | pub fn new(config: ClockModuleConfig) -> Self { 18 | Self { 19 | config, 20 | date: Local::now(), 21 | } 22 | } 23 | 24 | pub fn update(&mut self, message: Message) { 25 | match message { 26 | Message::Update => { 27 | self.date = Local::now(); 28 | } 29 | } 30 | } 31 | 32 | pub fn view(&'_ self, _: &AshellTheme) -> Element<'_, Message> { 33 | text(self.date.format(&self.config.format).to_string()).into() 34 | } 35 | 36 | pub fn subscription(&self) -> Subscription { 37 | let second_specifiers = [ 38 | "%S", // Seconds (00-60) 39 | "%T", // Hour:Minute:Second 40 | "%X", // Locale time representation with seconds 41 | "%r", // 12-hour clock time with seconds 42 | "%:z", // UTC offset with seconds 43 | "%s", // Unix timestamp (seconds since epoch) 44 | ]; 45 | let interval = if second_specifiers 46 | .iter() 47 | .any(|&spec| self.config.format.contains(spec)) 48 | { 49 | Duration::from_secs(1) 50 | } else { 51 | Duration::from_secs(5) 52 | }; 53 | 54 | every(interval).map(|_| Message::Update) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /website/src/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import type { ReactNode } from "react"; 2 | import clsx from "clsx"; 3 | import Link from "@docusaurus/Link"; 4 | import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; 5 | import Layout from "@theme/Layout"; 6 | import HomepageFeatures from "@site/src/components/HomepageFeatures"; 7 | 8 | import styles from "./index.module.css"; 9 | 10 | function HomepageHeader() { 11 | const { siteConfig } = useDocusaurusContext(); 12 | return ( 13 |
14 |
15 |
16 | Logo 17 | Ashell 22 |
23 |

24 | {siteConfig.tagline} 25 |

26 |
27 | 31 | Get Started 32 | 33 |
34 |
35 |
36 | ); 37 | } 38 | 39 | export default function Home(): ReactNode { 40 | const { siteConfig } = useDocusaurusContext(); 41 | return ( 42 | 46 | 47 |
48 | 49 |
50 |
51 | ); 52 | } 53 | -------------------------------------------------------------------------------- /src/services/network/iwd_dbus/agent_manager.rs: -------------------------------------------------------------------------------- 1 | //! # D-Bus interface proxy for: `net.connman.iwd.AgentManager` 2 | //! 3 | //! This code was generated by `zbus-xmlgen` `5.1.0` from D-Bus introspection data. 4 | //! 5 | //! You may prefer to adapt it, instead of using it verbatim. 6 | //! 7 | //! More information can be found in the [Writing a client proxy] section of the zbus 8 | //! documentation. 9 | //! 10 | //! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the 11 | //! following zbus API can be used: 12 | //! 13 | //! * [`zbus::fdo::IntrospectableProxy`] 14 | //! * [`zbus::fdo::PropertiesProxy`] 15 | //! 16 | //! Consequently `zbus-xmlgen` did not generate code for the above interfaces. 17 | //! 18 | //! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html 19 | //! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces, 20 | use zbus::proxy; 21 | #[proxy(interface = "net.connman.iwd.AgentManager", assume_defaults = true)] 22 | pub trait AgentManager { 23 | /// RegisterAgent method 24 | fn register_agent(&self, path: &zbus::zvariant::ObjectPath<'_>) -> zbus::Result<()>; 25 | 26 | /// RegisterNetworkConfigurationAgent method 27 | fn register_network_configuration_agent( 28 | &self, 29 | path: &zbus::zvariant::ObjectPath<'_>, 30 | ) -> zbus::Result<()>; 31 | 32 | /// UnregisterAgent method 33 | fn unregister_agent(&self, path: &zbus::zvariant::ObjectPath<'_>) -> zbus::Result<()>; 34 | 35 | /// UnregisterNetworkConfigurationAgent method 36 | fn unregister_network_configuration_agent( 37 | &self, 38 | path: &zbus::zvariant::ObjectPath<'_>, 39 | ) -> zbus::Result<()>; 40 | } 41 | -------------------------------------------------------------------------------- /src/services/network/iwd_dbus/device.rs: -------------------------------------------------------------------------------- 1 | //! # D-Bus interface proxy for: `net.connman.iwd.Device` 2 | //! 3 | //! This code was generated by `zbus-xmlgen` `5.1.0` from D-Bus introspection data. 4 | //! 5 | //! You may prefer to adapt it, instead of using it verbatim. 6 | //! 7 | //! More information can be found in the [Writing a client proxy] section of the zbus 8 | //! documentation. 9 | //! 10 | //! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the 11 | //! following zbus API can be used: 12 | //! 13 | //! * [`zbus::fdo::IntrospectableProxy`] 14 | //! * [`zbus::fdo::PropertiesProxy`] 15 | //! 16 | //! Consequently `zbus-xmlgen` did not generate code for the above interfaces. 17 | //! 18 | //! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html 19 | //! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces, 20 | use zbus::proxy; 21 | #[proxy(interface = "net.connman.iwd.Device", assume_defaults = true)] 22 | pub trait Device { 23 | /// Adapter property 24 | #[zbus(property)] 25 | fn adapter(&self) -> zbus::Result; 26 | 27 | /// Address property 28 | #[zbus(property)] 29 | fn address(&self) -> zbus::Result; 30 | 31 | /// Mode property 32 | #[zbus(property)] 33 | fn mode(&self) -> zbus::Result; 34 | #[zbus(property)] 35 | fn set_mode(&self, value: &str) -> zbus::Result<()>; 36 | 37 | /// Name property 38 | #[zbus(property)] 39 | fn name(&self) -> zbus::Result; 40 | 41 | /// Powered property 42 | #[zbus(property)] 43 | fn powered(&self) -> zbus::Result; 44 | #[zbus(property)] 45 | fn set_powered(&self, value: bool) -> zbus::Result<()>; 46 | } 47 | -------------------------------------------------------------------------------- /src/services/network/iwd_dbus/known_network.rs: -------------------------------------------------------------------------------- 1 | //! # D-Bus interface proxy for: `net.connman.iwd.KnownNetwork` 2 | //! 3 | //! This code was generated by `zbus-xmlgen` `5.1.0` from D-Bus introspection data. 4 | //! 5 | //! You may prefer to adapt it, instead of using it verbatim. 6 | //! 7 | //! More information can be found in the [Writing a client proxy] section of the zbus 8 | //! documentation. 9 | //! 10 | //! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the 11 | //! following zbus API can be used: 12 | //! 13 | //! * [`zbus::fdo::IntrospectableProxy`] 14 | //! * [`zbus::fdo::PropertiesProxy`] 15 | //! 16 | //! Consequently `zbus-xmlgen` did not generate code for the above interfaces. 17 | //! 18 | //! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html 19 | //! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces, 20 | use zbus::proxy; 21 | #[proxy(interface = "net.connman.iwd.KnownNetwork", assume_defaults = true)] 22 | pub trait KnownNetwork { 23 | /// Forget method 24 | fn forget(&self) -> zbus::Result<()>; 25 | 26 | /// AutoConnect property 27 | #[zbus(property)] 28 | fn auto_connect(&self) -> zbus::Result; 29 | #[zbus(property)] 30 | fn set_auto_connect(&self, value: bool) -> zbus::Result<()>; 31 | 32 | /// Hidden property 33 | #[zbus(property)] 34 | fn hidden(&self) -> zbus::Result; 35 | 36 | /// LastConnectedTime property 37 | #[zbus(property)] 38 | fn last_connected_time(&self) -> zbus::Result; 39 | 40 | /// Name property 41 | #[zbus(property)] 42 | fn name(&self) -> zbus::Result; 43 | 44 | /// Type property 45 | #[zbus(property)] 46 | fn type_(&self) -> zbus::Result; 47 | } 48 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "crane": { 4 | "locked": { 5 | "lastModified": 1763938834, 6 | "narHash": "sha256-j8iB0Yr4zAvQLueCZ5abxfk6fnG/SJ5JnGUziETjwfg=", 7 | "owner": "ipetkov", 8 | "repo": "crane", 9 | "rev": "d9e753122e51cee64eb8d2dddfe11148f339f5a2", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "owner": "ipetkov", 14 | "repo": "crane", 15 | "type": "github" 16 | } 17 | }, 18 | "nixpkgs": { 19 | "locked": { 20 | "lastModified": 1764517877, 21 | "narHash": "sha256-pp3uT4hHijIC8JUK5MEqeAWmParJrgBVzHLNfJDZxg4=", 22 | "owner": "NixOS", 23 | "repo": "nixpkgs", 24 | "rev": "2d293cbfa5a793b4c50d17c05ef9e385b90edf6c", 25 | "type": "github" 26 | }, 27 | "original": { 28 | "owner": "NixOS", 29 | "ref": "nixos-unstable", 30 | "repo": "nixpkgs", 31 | "type": "github" 32 | } 33 | }, 34 | "root": { 35 | "inputs": { 36 | "crane": "crane", 37 | "nixpkgs": "nixpkgs", 38 | "rust-overlay": "rust-overlay" 39 | } 40 | }, 41 | "rust-overlay": { 42 | "inputs": { 43 | "nixpkgs": [ 44 | "nixpkgs" 45 | ] 46 | }, 47 | "locked": { 48 | "lastModified": 1764557621, 49 | "narHash": "sha256-kX5PoY8hQZ80+amMQgOO9t8Tc1JZ70gYRnzaVD4AA+o=", 50 | "owner": "oxalica", 51 | "repo": "rust-overlay", 52 | "rev": "93316876c2229460a5d6f5f052766cc4cef538ce", 53 | "type": "github" 54 | }, 55 | "original": { 56 | "owner": "oxalica", 57 | "repo": "rust-overlay", 58 | "type": "github" 59 | } 60 | } 61 | }, 62 | "root": "root", 63 | "version": 7 64 | } 65 | -------------------------------------------------------------------------------- /src/services/network/iwd_dbus/device_provisioning.rs: -------------------------------------------------------------------------------- 1 | //! # D-Bus interface proxy for: `net.connman.iwd.DeviceProvisioning` 2 | //! 3 | //! This code was generated by `zbus-xmlgen` `5.1.0` from D-Bus introspection data. 4 | //! 5 | //! You may prefer to adapt it, instead of using it verbatim. 6 | //! 7 | //! More information can be found in the [Writing a client proxy] section of the zbus 8 | //! documentation. 9 | //! 10 | //! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the 11 | //! following zbus API can be used: 12 | //! 13 | //! * [`zbus::fdo::IntrospectableProxy`] 14 | //! * [`zbus::fdo::PropertiesProxy`] 15 | //! 16 | //! Consequently `zbus-xmlgen` did not generate code for the above interfaces. 17 | //! 18 | //! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html 19 | //! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces, 20 | use zbus::proxy; 21 | #[proxy( 22 | interface = "net.connman.iwd.DeviceProvisioning", 23 | assume_defaults = true 24 | )] 25 | pub trait DeviceProvisioning { 26 | /// ConfigureEnrollee method 27 | fn configure_enrollee(&self, uri: &str) -> zbus::Result<()>; 28 | 29 | /// StartConfigurator method 30 | fn start_configurator(&self) -> zbus::Result; 31 | 32 | /// StartEnrollee method 33 | fn start_enrollee(&self) -> zbus::Result; 34 | 35 | /// Stop method 36 | fn stop(&self) -> zbus::Result<()>; 37 | 38 | /// Role property 39 | #[zbus(property)] 40 | fn role(&self) -> zbus::Result; 41 | 42 | /// Started property 43 | #[zbus(property)] 44 | fn started(&self) -> zbus::Result; 45 | 46 | /// URI property 47 | #[zbus(property, name = "URI")] 48 | fn uri(&self) -> zbus::Result; 49 | } 50 | -------------------------------------------------------------------------------- /src/services/throttle.rs: -------------------------------------------------------------------------------- 1 | use iced::futures::{ 2 | Stream, 3 | task::{Context, Poll}, 4 | }; 5 | use pin_project_lite::pin_project; 6 | use std::{pin::Pin, time::Duration}; 7 | use tokio::time::{self, Sleep}; 8 | 9 | pin_project! { 10 | pub struct Throttle { 11 | #[pin] 12 | inner: S, 13 | duration: Duration, 14 | sleep: Option>>, 15 | } 16 | } 17 | 18 | impl Throttle { 19 | pub fn new(inner: S, duration: Duration) -> Self { 20 | Self { 21 | inner, 22 | duration, 23 | sleep: None, 24 | } 25 | } 26 | } 27 | 28 | impl Stream for Throttle 29 | where 30 | S: Stream, 31 | { 32 | type Item = S::Item; 33 | 34 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 35 | let mut this = self.project(); 36 | 37 | // If we're in the throttling period, poll the sleep 38 | if let Some(sleep) = &mut this.sleep { 39 | match sleep.as_mut().poll(cx) { 40 | Poll::Pending => return Poll::Pending, 41 | Poll::Ready(_) => *this.sleep = None, // Throttle period over 42 | } 43 | } 44 | 45 | match this.inner.as_mut().poll_next(cx) { 46 | Poll::Ready(Some(item)) => { 47 | *this.sleep = Some(Box::pin(time::sleep(*this.duration))); 48 | Poll::Ready(Some(item)) 49 | } 50 | Poll::Ready(None) => Poll::Ready(None), 51 | Poll::Pending => Poll::Pending, 52 | } 53 | } 54 | } 55 | 56 | pub trait ThrottleExt: Stream + Sized { 57 | fn throttle(self, duration: Duration) -> Throttle { 58 | Throttle::new(self, duration) 59 | } 60 | } 61 | 62 | impl ThrottleExt for T {} 63 | -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name-template: "$RESOLVED_VERSION" 2 | tag-template: "$RESOLVED_VERSION" 3 | categories: 4 | - title: "💥 Breaking changes" 5 | labels: 6 | - "breaking" 7 | - title: "🚀 Features" 8 | labels: 9 | - "feature" 10 | - "enhancement" 11 | - title: "🐞 Bug fixes" 12 | labels: 13 | - "fix" 14 | - "bugfix" 15 | - "bug" 16 | - title: "📚 Documentation" 17 | labels: 18 | - "documentation" 19 | - "docs" 20 | - title: "🧰 Maintenance" 21 | label: 22 | - "chore" 23 | - title: "🔧 Dependency updates" 24 | labels: 25 | - "dependencies" 26 | change-template: "- $TITLE @$AUTHOR (#$NUMBER)" 27 | change-title-escapes: '\<*_&' 28 | exclude-labels: 29 | - "skip-changelog" 30 | exclude-contributors: 31 | - "MalpenZibo" 32 | - "dependabot" 33 | - "dependabot[bot]" 34 | - "github-actions[bot]" 35 | no-contributors-template: "just me this time 😅" 36 | autolabeler: 37 | - label: "docs" 38 | branch: 39 | - '/^docs\/.+/' 40 | title: 41 | - "/^docs/i" 42 | - label: "bug" 43 | branch: 44 | - '/fix\/.+/' 45 | title: 46 | - "/fix/i" 47 | - label: "feature" 48 | branch: 49 | - '/feature\/.+/' 50 | - '/feat\/.+/' 51 | title: 52 | - "/feature/i" 53 | - '/feat\/.+/' 54 | - label: "chore" 55 | branch: 56 | - '/chore\/.+/' 57 | title: 58 | - "/chore/i" 59 | - label: "dependencies" 60 | branch: 61 | - '/dependabot\/.+/' 62 | version-resolver: 63 | major: 64 | labels: 65 | - "major" 66 | minor: 67 | labels: 68 | - "minor" 69 | patch: 70 | labels: 71 | - "patch" 72 | default: patch 73 | template: | 74 | ## Changes 75 | 76 | $CHANGES 77 | 78 | ## Contributors 79 | 80 | ❤️ A big thanks to $CONTRIBUTORS 81 | -------------------------------------------------------------------------------- /.github/workflows/copr-build.yml: -------------------------------------------------------------------------------- 1 | name: Copr Build 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | chroots: 7 | description: "Space-separated Copr chroots" 8 | required: false 9 | default: "fedora-42-x86_64" 10 | push: 11 | tags: 12 | - "v*" 13 | 14 | jobs: 15 | copr: 16 | runs-on: ubuntu-latest 17 | container: 18 | image: fedora:42 19 | env: 20 | COPR_CONFIG: ${{ secrets.COPR_CONFIG }} 21 | steps: 22 | - uses: actions/checkout@v4 23 | - name: Install deps 24 | run: | 25 | dnf -y install git cargo rust rpm-build copr-cli gcc make pkgconf-pkg-config 26 | dnf -y clean all 27 | - name: Configure copr-cli 28 | if: env.COPR_CONFIG != '' 29 | run: | 30 | mkdir -p ~/.config 31 | printf "%s" "$COPR_CONFIG" > ~/.config/copr 32 | chmod 600 ~/.config/copr 33 | - name: Ensure cargo-rpm 34 | run: cargo install cargo-rpm --locked 35 | - name: Prepare RPM packaging 36 | run: | 37 | if [ ! -d .rpm ]; then cargo rpm init; fi 38 | - name: Build SRPM 39 | run: cargo rpm build -v 40 | - name: Locate SRPM 41 | id: srpm 42 | run: echo "path=$(ls -1 target/release/rpmbuild/SRPMS/*.src.rpm | head -n1)" >> $GITHUB_OUTPUT 43 | - name: Trigger Copr build 44 | if: env.COPR_CONFIG != '' 45 | env: 46 | CHROOTS: ${{ github.event.inputs.chroots }} 47 | run: | 48 | CHROOTS="${CHROOTS:-fedora-42-x86_64}" 49 | args=() 50 | for c in $CHROOTS; do args+=( -r "$c" ); done 51 | copr-cli build "${args[@]}" killcrb/ashell "${{ steps.srpm.outputs.path }}" 52 | - name: List builds 53 | if: env.COPR_CONFIG != '' 54 | run: copr-cli list-builds killcrb/ashell 55 | -------------------------------------------------------------------------------- /src/utils/launcher.rs: -------------------------------------------------------------------------------- 1 | use std::process::Command; 2 | 3 | pub fn execute_command(command: String) { 4 | tokio::spawn(async move { 5 | let _ = Command::new("bash") 6 | .arg("-c") 7 | .arg(&command) 8 | .spawn() 9 | .unwrap_or_else(|_| panic!("Failed to execute command {}", &command)) 10 | .wait(); 11 | }); 12 | } 13 | 14 | pub fn suspend(cmd: String) { 15 | tokio::spawn(async move { 16 | let _ = Command::new("bash") 17 | .arg("-c") 18 | .arg(cmd) 19 | .spawn() 20 | .expect("Failed to execute command.") 21 | .wait(); 22 | }); 23 | } 24 | 25 | pub fn hibernate(cmd: String) { 26 | tokio::spawn(async move { 27 | let _ = Command::new("bash") 28 | .arg("-c") 29 | .arg(cmd) 30 | .spawn() 31 | .expect("Failed to execute command.") 32 | .wait(); 33 | }); 34 | } 35 | 36 | pub fn shutdown(cmd: String) { 37 | tokio::spawn(async move { 38 | let _ = Command::new("bash") 39 | .arg("-c") 40 | .arg(cmd) 41 | .spawn() 42 | .expect("Failed to execute command.") 43 | .wait(); 44 | }); 45 | } 46 | 47 | pub fn reboot(cmd: String) { 48 | tokio::spawn(async move { 49 | let _ = Command::new("bash") 50 | .arg("-c") 51 | .arg(cmd) 52 | .spawn() 53 | .expect("Failed to execute command.") 54 | .wait(); 55 | }); 56 | } 57 | 58 | pub fn logout(cmd: String) { 59 | tokio::spawn(async move { 60 | let _ = Command::new("bash") 61 | .arg("-c") 62 | .arg(cmd) 63 | .spawn() 64 | .expect("Failed to execute command.") 65 | .wait(); 66 | }); 67 | } 68 | -------------------------------------------------------------------------------- /src/services/network/iwd_dbus/network.rs: -------------------------------------------------------------------------------- 1 | //! # D-Bus interface proxy for: `net.connman.iwd.Network` 2 | //! 3 | //! This code was generated by `zbus-xmlgen` `5.1.0` from D-Bus introspection data. 4 | //! 5 | //! You may prefer to adapt it, instead of using it verbatim. 6 | //! 7 | //! More information can be found in the [Writing a client proxy] section of the zbus 8 | //! documentation. 9 | //! 10 | //! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the 11 | //! following zbus API can be used: 12 | //! 13 | //! * [`zbus::fdo::IntrospectableProxy`] 14 | //! * [`zbus::fdo::PropertiesProxy`] 15 | //! 16 | //! Consequently `zbus-xmlgen` did not generate code for the above interfaces. 17 | //! 18 | //! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html 19 | //! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces, 20 | use zbus::proxy; 21 | #[proxy(interface = "net.connman.iwd.Network", assume_defaults = true)] 22 | pub trait Network { 23 | /// Connect method 24 | fn connect(&self) -> zbus::Result<()>; 25 | 26 | /// Connected property 27 | #[zbus(property)] 28 | fn connected(&self) -> zbus::Result; 29 | 30 | /// Device property 31 | #[zbus(property)] 32 | fn device(&self) -> zbus::Result; 33 | 34 | /// ExtendedServiceSet property 35 | #[zbus(property)] 36 | fn extended_service_set(&self) -> zbus::Result>; 37 | 38 | /// KnownNetwork property 39 | #[zbus(property)] 40 | fn known_network(&self) -> zbus::Result; 41 | 42 | /// Name property 43 | #[zbus(property)] 44 | fn name(&self) -> zbus::Result; 45 | 46 | /// Type property 47 | #[zbus(property)] 48 | fn type_(&self) -> zbus::Result; 49 | } 50 | -------------------------------------------------------------------------------- /src/services/compositor/types.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, Clone, PartialEq)] 2 | pub struct CompositorWorkspace { 3 | pub id: i32, 4 | pub name: String, 5 | pub monitor: String, 6 | pub monitor_id: Option, 7 | pub windows: u16, 8 | pub is_special: bool, 9 | } 10 | 11 | #[derive(Debug, Clone, PartialEq)] 12 | pub struct CompositorMonitor { 13 | pub id: i128, 14 | pub name: String, 15 | pub active_workspace_id: i32, 16 | pub special_workspace_id: i32, 17 | } 18 | 19 | #[derive(Debug, Clone, PartialEq, Default)] 20 | pub struct ActiveWindow { 21 | pub title: String, 22 | pub class: String, 23 | pub address: String, 24 | } 25 | 26 | #[derive(Debug, Clone, Default)] 27 | pub struct CompositorState { 28 | pub workspaces: Vec, 29 | pub monitors: Vec, 30 | pub active_workspace_id: Option, 31 | pub active_window: Option, 32 | pub keyboard_layout: String, 33 | pub submap: Option, 34 | } 35 | 36 | #[derive(Debug, Copy, Clone)] 37 | pub enum CompositorChoice { 38 | Hyprland, 39 | Niri, 40 | } 41 | 42 | #[derive(Debug, Clone)] 43 | pub struct CompositorService { 44 | pub state: CompositorState, 45 | pub backend: CompositorChoice, 46 | } 47 | 48 | #[derive(Debug, Clone)] 49 | pub enum CompositorEvent { 50 | ActionPerformed, // for now a noop to respond to commands 51 | StateChanged(CompositorState), 52 | // We can add specific events if needed, but a full state sync is safer for workspaces 53 | } 54 | 55 | #[derive(Debug, Clone)] 56 | #[allow(dead_code)] 57 | pub enum CompositorCommand { 58 | FocusWorkspace(i32), 59 | FocusSpecialWorkspace(String), 60 | FocusMonitor(i128), 61 | ToggleSpecialWorkspace(String), 62 | ScrollWorkspace(i32), // +1 or -1 63 | CustomDispatch(String, String), // For "vdesk" 64 | NextLayout, 65 | } 66 | -------------------------------------------------------------------------------- /dist-workspace.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = ["cargo:."] 3 | 4 | # Config for 'dist' 5 | [dist] 6 | # The preferred dist version to use in CI (Cargo.toml SemVer syntax) 7 | cargo-dist-version = "0.30.0" 8 | # CI backends to support 9 | ci = "github" 10 | # The installers to generate for each app 11 | installers = ["shell"] 12 | # Whether CI should trigger releases with dispatches instead of tag pushes 13 | dispatch-releases = true 14 | # Checksums to generate for each App 15 | checksum = "false" 16 | # Generate and dist a source tarball 17 | source-tarball = false 18 | # Which actions to run on pull requests 19 | pr-run-mode = "skip" 20 | # Target platforms to build apps for (Rust target-triple syntax) 21 | targets = ["x86_64-unknown-linux-gnu"] 22 | # Whether dist should create a Github Release or use an existing draft 23 | create-release = false 24 | # Global artifacts jobs to run in CI 25 | global-artifacts-jobs = ["./generate-installers"] 26 | # Post-announce jobs to run in CI 27 | post-announce-jobs = ["./remove-manifest-assets", "./update-arch-package"] 28 | # Path that installers should place binaries in 29 | install-path = "CARGO_HOME" 30 | # Whether to install an updater program 31 | install-updater = false 32 | 33 | [dist.github-custom-runners] 34 | global = "ubuntu-24.04" 35 | x86_64-unknown-linux-gnu = "ubuntu-24.04" 36 | 37 | [dist.dependencies.apt] 38 | pkg-config = { stage = ["build"] } 39 | llvm-dev = { stage = ["build"] } 40 | libclang-dev = { stage = ["build"] } 41 | clang = { stage = ["build"] } 42 | libxkbcommon-dev = { stage = ["build"] } 43 | libwayland-dev = { stage = ["build"] } 44 | "libpipewire-0.3-dev" = { stage = ["build"] } 45 | libpulse-dev = { stage = ["build"] } 46 | libudev-dev = { stage = ["build"] } 47 | dbus = { stage = ["build", "run"] } 48 | 49 | libxkbcommon0 = { stage = ["run"] } 50 | wayland-protocols = { stage = ["run"] } 51 | pipewire = { stage = ["run"] } 52 | pulseaudio = { stage = ["run"] } 53 | 54 | -------------------------------------------------------------------------------- /src/services/network/iwd_dbus/access_point.rs: -------------------------------------------------------------------------------- 1 | //! # D-Bus interface proxy for: `net.connman.iwd.AccessPoint` 2 | //! 3 | //! This code was generated by `zbus-xmlgen` `5.1.0` from D-Bus introspection data. 4 | //! 5 | //! You may prefer to adapt it, instead of using it verbatim. 6 | //! 7 | //! More information can be found in the [Writing a client proxy] section of the zbus 8 | //! documentation. 9 | //! 10 | //! 11 | //! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html 12 | //! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces, 13 | use zbus::proxy; 14 | #[proxy(interface = "net.connman.iwd.AccessPoint", assume_defaults = true)] 15 | pub trait AccessPoint { 16 | /// GetOrderedNetworks method 17 | fn get_ordered_networks( 18 | &self, 19 | ) -> zbus::Result>; 20 | 21 | /// Scan method 22 | fn scan(&self) -> zbus::Result<()>; 23 | 24 | /// Start method 25 | fn start(&self, ssid: &str, psk: &str) -> zbus::Result<()>; 26 | 27 | /// StartProfile method 28 | fn start_profile(&self, ssid: &str) -> zbus::Result<()>; 29 | 30 | /// Stop method 31 | fn stop(&self) -> zbus::Result<()>; 32 | 33 | /// Frequency property 34 | #[zbus(property)] 35 | fn frequency(&self) -> zbus::Result; 36 | 37 | /// GroupCipher property 38 | #[zbus(property)] 39 | fn group_cipher(&self) -> zbus::Result; 40 | 41 | /// Name property 42 | #[zbus(property)] 43 | fn name(&self) -> zbus::Result; 44 | 45 | /// PairwiseCiphers property 46 | #[zbus(property)] 47 | fn pairwise_ciphers(&self) -> zbus::Result>; 48 | 49 | /// Scanning property 50 | #[zbus(property)] 51 | fn scanning(&self) -> zbus::Result; 52 | 53 | /// Started property 54 | #[zbus(property)] 55 | fn started(&self) -> zbus::Result; 56 | } 57 | -------------------------------------------------------------------------------- /src/services/network/iwd_dbus/shared_code_device_provisioning.rs: -------------------------------------------------------------------------------- 1 | //! # D-Bus interface proxy for: `net.connman.iwd.SharedCodeDeviceProvisioning` 2 | //! 3 | //! This code was generated by `zbus-xmlgen` `5.1.0` from D-Bus introspection data. 4 | //! 5 | //! You may prefer to adapt it, instead of using it verbatim. 6 | //! 7 | //! More information can be found in the [Writing a client proxy] section of the zbus 8 | //! documentation. 9 | //! 10 | //! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the 11 | //! following zbus API can be used: 12 | //! 13 | //! * [`zbus::fdo::IntrospectableProxy`] 14 | //! * [`zbus::fdo::PropertiesProxy`] 15 | //! 16 | //! Consequently `zbus-xmlgen` did not generate code for the above interfaces. 17 | //! 18 | //! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html 19 | //! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces, 20 | use zbus::proxy; 21 | #[proxy( 22 | interface = "net.connman.iwd.SharedCodeDeviceProvisioning", 23 | assume_defaults = true 24 | )] 25 | pub trait SharedCodeDeviceProvisioning { 26 | /// ConfigureEnrollee method 27 | fn configure_enrollee( 28 | &self, 29 | args: std::collections::HashMap<&str, &zbus::zvariant::Value<'_>>, 30 | ) -> zbus::Result<()>; 31 | 32 | /// StartConfigurator method 33 | fn start_configurator(&self, path: &zbus::zvariant::ObjectPath<'_>) -> zbus::Result<()>; 34 | 35 | /// StartEnrollee method 36 | fn start_enrollee( 37 | &self, 38 | args: std::collections::HashMap<&str, &zbus::zvariant::Value<'_>>, 39 | ) -> zbus::Result<()>; 40 | 41 | /// Stop method 42 | fn stop(&self) -> zbus::Result<()>; 43 | 44 | /// Role property 45 | #[zbus(property)] 46 | fn role(&self) -> zbus::Result; 47 | 48 | /// Started property 49 | #[zbus(property)] 50 | fn started(&self) -> zbus::Result; 51 | } 52 | -------------------------------------------------------------------------------- /website/src/css/custom.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Any CSS included here will be global. The classic template 3 | * bundles Infima by default. Infima is a CSS framework designed to 4 | * work well for content-centric websites. 5 | */ 6 | 7 | /* You can override the default Infima variables here. */ 8 | :root { 9 | --ifm-color-primary: #2e7de9; 10 | --ifm-color-primary-dark: #186ee3; 11 | --ifm-color-primary-darker: #1768d7; 12 | --ifm-color-primary-darkest: #1355b1; 13 | --ifm-color-primary-light: #478dec; 14 | --ifm-color-primary-lighter: #5495ed; 15 | --ifm-color-primary-lightest: #7aacf1; 16 | --ifm-code-font-size: 95%; 17 | --docusaurus-highlighted-code-line-bg: #2f334d; 18 | } 19 | 20 | /* For readability concerns, you should choose a lighter palette in dark mode. */ 21 | [data-theme="dark"] { 22 | --ifm-color-primary: #82aaff; 23 | --ifm-color-primary-dark: #5b90ff; 24 | --ifm-color-primary-darker: #4883ff; 25 | --ifm-color-primary-darkest: #0f5bff; 26 | --ifm-color-primary-light: #a8c4ff; 27 | --ifm-color-primary-lighter: #bcd1ff; 28 | --ifm-color-primary-lightest: #f5f9ff; 29 | --ifm-background-color: #222436; 30 | --ifm-background-color: #1e2030; 31 | --ifm-heading-color: #bcd1ff; 32 | --ifm-navbar-search-input-background-color: #2f334d; 33 | } 34 | 35 | html[data-theme="dark"] { 36 | --primary-bg: #222436; 37 | --ifm-background-color: #1e2030; 38 | --ifm-background-surface-color: #222436; 39 | } 40 | 41 | .social { 42 | display: flex; 43 | align-items: center; 44 | gap: 1rem; 45 | padding: 0; 46 | } 47 | 48 | .social path { 49 | fill: var(--ifm-navbar-link-color); 50 | } 51 | 52 | .social:hover path { 53 | fill: var(--ifm-color-primary); 54 | } 55 | 56 | .theme-doc-version-badge { 57 | margin-bottom: 16px; 58 | } 59 | 60 | @media screen and (max-width: 996px) { 61 | .theme-doc-version-badge { 62 | margin-bottom: revert; 63 | } 64 | 65 | .social { 66 | margin: 48px 16px; 67 | display: inline-block; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /website/static/img/iced.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /website/docs/configuration/appearance/palette.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | --- 4 | 5 | # Palette 6 | 7 | With these configuration options, you can customize 8 | the color palette of your status bar. 9 | 10 | Each color can be a simple hex color like `#228800` or an 11 | object that defines: 12 | 13 | - A base hex color 14 | - Two optional variants of that color (a strong one and a weak one) 15 | - An optional text color to use with that base color 16 | 17 | If the strong and weak variants are not provided, they will be auto-generated. 18 | If no text color is provided, the default text color will be used. 19 | 20 | ## Example 21 | 22 | ```toml 23 | [appearance.background_color] 24 | base = "#448877" 25 | strong = "#448888" 26 | weak = "#448855" 27 | text = "#ffffff" 28 | ``` 29 | 30 | ## Palette Colors 31 | 32 | The following are the colors that make up the palette: 33 | 34 | - `background_color`: Used as the background color for all status bar components 35 | - `primary_color`: Used for elements like buttons or slider handles 36 | - `secondary_color`: Used for borders and slider tracks 37 | - `success_color`: Used for success indicators 38 | - `danger_color`: Used for danger messages or danger states 39 | (the weak version is used for warning states) 40 | - `text_color`: Used as the default text color 41 | 42 | ## Workspace Colors 43 | 44 | The following colors are used for the workspaces module. 45 | 46 | You can specify which color to use for workspace indicators based on 47 | the monitor to which a workspace is attached. 48 | 49 | For example, if workspace 1 is attached to `monitorA`, the first 50 | color will be used; if workspace 2 is attached to `monitorB`, 51 | the second color will be used, and so on. 52 | 53 | Use the `workspace_colors` field for regular workspaces, and 54 | `special_workspace_colors` for special workspaces. 55 | 56 | If `special_workspace_colors` is not defined, `workspace_colors` will be used. 57 | If neither `workspace_colors` is defined nor a color exists 58 | for a given monitor, the `primary_color` will be used. 59 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.6.0/configuration/appearance/palette.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | --- 4 | 5 | # Palette 6 | 7 | With these configuration options, you can customize 8 | the color palette of your status bar. 9 | 10 | Each color can be a simple hex color like `#228800` or an 11 | object that defines: 12 | 13 | - A base hex color 14 | - Two optional variants of that color (a strong one and a weak one) 15 | - An optional text color to use with that base color 16 | 17 | If the strong and weak variants are not provided, they will be auto-generated. 18 | If no text color is provided, the default text color will be used. 19 | 20 | ## Example 21 | 22 | ```toml 23 | [appearance.background_color] 24 | base = "#448877" 25 | strong = "#448888" 26 | weak = "#448855" 27 | text = "#ffffff" 28 | ``` 29 | 30 | ## Palette Colors 31 | 32 | The following are the colors that make up the palette: 33 | 34 | - `background_color`: Used as the background color for all status bar components 35 | - `primary_color`: Used for elements like buttons or slider handles 36 | - `secondary_color`: Used for borders and slider tracks 37 | - `success_color`: Used for success indicators 38 | - `danger_color`: Used for danger messages or danger states 39 | (the weak version is used for warning states) 40 | - `text_color`: Used as the default text color 41 | 42 | ## Workspace Colors 43 | 44 | The following colors are used for the workspaces module. 45 | 46 | You can specify which color to use for workspace indicators based on 47 | the monitor to which a workspace is attached. 48 | 49 | For example, if workspace 1 is attached to `monitorA`, the first 50 | color will be used; if workspace 2 is attached to `monitorB`, 51 | the second color will be used, and so on. 52 | 53 | Use the `workspace_colors` field for regular workspaces, and 54 | `special_workspace_colors` for special workspaces. 55 | 56 | If `special_workspace_colors` is not defined, `workspace_colors` will be used. 57 | If neither `workspace_colors` is defined nor a color exists 58 | for a given monitor, the `primary_color` will be used. 59 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.7.0/configuration/appearance/palette.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | --- 4 | 5 | # Palette 6 | 7 | With these configuration options, you can customize 8 | the color palette of your status bar. 9 | 10 | Each color can be a simple hex color like `#228800` or an 11 | object that defines: 12 | 13 | - A base hex color 14 | - Two optional variants of that color (a strong one and a weak one) 15 | - An optional text color to use with that base color 16 | 17 | If the strong and weak variants are not provided, they will be auto-generated. 18 | If no text color is provided, the default text color will be used. 19 | 20 | ## Example 21 | 22 | ```toml 23 | [appearance.background_color] 24 | base = "#448877" 25 | strong = "#448888" 26 | weak = "#448855" 27 | text = "#ffffff" 28 | ``` 29 | 30 | ## Palette Colors 31 | 32 | The following are the colors that make up the palette: 33 | 34 | - `background_color`: Used as the background color for all status bar components 35 | - `primary_color`: Used for elements like buttons or slider handles 36 | - `secondary_color`: Used for borders and slider tracks 37 | - `success_color`: Used for success indicators 38 | - `danger_color`: Used for danger messages or danger states 39 | (the weak version is used for warning states) 40 | - `text_color`: Used as the default text color 41 | 42 | ## Workspace Colors 43 | 44 | The following colors are used for the workspaces module. 45 | 46 | You can specify which color to use for workspace indicators based on 47 | the monitor to which a workspace is attached. 48 | 49 | For example, if workspace 1 is attached to `monitorA`, the first 50 | color will be used; if workspace 2 is attached to `monitorB`, 51 | the second color will be used, and so on. 52 | 53 | Use the `workspace_colors` field for regular workspaces, and 54 | `special_workspace_colors` for special workspaces. 55 | 56 | If `special_workspace_colors` is not defined, `workspace_colors` will be used. 57 | If neither `workspace_colors` is defined nor a color exists 58 | for a given monitor, the `primary_color` will be used. 59 | -------------------------------------------------------------------------------- /website/docs/configuration/appearance/general.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # General 6 | 7 | These are all the appearance options not related to the color palette. 8 | 9 | ## Font 10 | 11 | You can change the font used by setting the `font_name` field. This configuration 12 | is optional—if not set, the `iced` library will use the default font. 13 | 14 | ```toml 15 | [appearance] 16 | font_name = "Comic Sans MS" 17 | ``` 18 | 19 | :::warning 20 | 21 | Changing the font requires to kill and restart ashell process. The font configuration does not support hot-reloading 22 | 23 | ::: 24 | 25 | ## Scaling Factor 26 | 27 | You can change the scaling factor of the status bar using the `scale_factor` field. 28 | 29 | The value should be a float greater than `0.0` and less than or equal to `2.0`. 30 | The default value is `1.0`. 31 | 32 | ```toml 33 | [appearance] 34 | scale_factor = 1.5 35 | ``` 36 | 37 | ## Status Bar Style 38 | 39 | You can change the style of the status bar using the `style` field. 40 | 41 | You can choose between: 42 | 43 | - `Island`: This is the default style. Each module or module group is displayed 44 | in a rounded rectangle using the background color. 45 | - `Solid`: The status bar has a solid background color. 46 | - `Gradient`: The status bar has a gradient background color. 47 | 48 | ### Example 49 | 50 | ```toml 51 | [appearance] 52 | style = "Gradient" 53 | ``` 54 | 55 | ## Opacity 56 | 57 | You can change the opacity of the status bar components using the `opacity` field. 58 | 59 | The value should be a float between `0.0` and `1.0`, where `0.0` is fully transparent. 60 | The default value is `1.0`. 61 | 62 | It's also possible to define the opacity of status bar menus and whether they should 63 | include a backdrop effect. 64 | 65 | ## Examples 66 | 67 | Setting the opacity of the status bar components: 68 | 69 | ```toml 70 | [appearance] 71 | opacity = 0.8 72 | ``` 73 | 74 | Also setting the opacity of the status bar menus and adding a backdrop effect: 75 | 76 | ```toml 77 | [appearance] 78 | opacity = 0.8 79 | 80 | [appearance.menu] 81 | opacity = 0.7 82 | backdrop = 0.3 83 | ``` 84 | -------------------------------------------------------------------------------- /src/password_dialog.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | components::icons::{StaticIcon, icon}, 3 | theme::AshellTheme, 4 | }; 5 | use iced::{ 6 | Alignment, Element, Length, 7 | alignment::Vertical, 8 | widget::{button, column, horizontal_space, row, text, text_input}, 9 | window::Id, 10 | }; 11 | 12 | #[derive(Debug, Clone)] 13 | pub enum Message { 14 | PasswordChanged(String), 15 | DialogConfirmed(Id), 16 | DialogCancelled(Id), 17 | } 18 | 19 | pub fn view<'a>( 20 | id: Id, 21 | theme: &'a AshellTheme, 22 | wifi_ssid: &str, 23 | current_password: &str, 24 | ) -> Element<'a, Message> { 25 | column!( 26 | row!( 27 | icon(StaticIcon::WifiLock4).size(theme.font_size.xxl), 28 | text("Authentication required").size(theme.font_size.xl), 29 | ) 30 | .spacing(theme.space.md) 31 | .align_y(Alignment::Center), 32 | text(format!("Insert password to connect to: {wifi_ssid}")), 33 | text_input("", current_password) 34 | .secure(true) 35 | .size(theme.font_size.md) 36 | .padding([theme.space.xs, theme.space.md]) 37 | .style(theme.text_input_style()) 38 | .on_input(Message::PasswordChanged) 39 | .on_submit(Message::DialogConfirmed(id)), 40 | row!( 41 | horizontal_space(), 42 | button(text("Cancel").align_y(Vertical::Center)) 43 | .padding([theme.space.xxs, theme.space.xl]) 44 | .style(theme.outline_button_style()) 45 | .height(Length::Fixed(50.)) 46 | .on_press(Message::DialogCancelled(id)), 47 | button(text("Confirm").align_y(Vertical::Center)) 48 | .padding([theme.space.xxs, theme.space.xl]) 49 | .height(Length::Fixed(50.)) 50 | .style(theme.confirm_button_style()) 51 | .on_press(Message::DialogConfirmed(id)) 52 | ) 53 | .spacing(theme.space.xs) 54 | .width(Length::Fill) 55 | ) 56 | .spacing(theme.space.md) 57 | .padding(theme.space.md) 58 | .max_width(350.) 59 | .into() 60 | } 61 | -------------------------------------------------------------------------------- /website/src/pages/gallery.module.css: -------------------------------------------------------------------------------- 1 | .gallery { 2 | display: flex; 3 | flex-direction: column; 4 | 5 | align-items: center; 6 | 7 | padding: 48px; 8 | 9 | margin: 0 auto; 10 | width: 100%; 11 | max-width: 1400px; 12 | 13 | gap: 32px; 14 | } 15 | 16 | .galleryContent { 17 | display: flex; 18 | flex-direction: row; 19 | 20 | align-items: center; 21 | 22 | flex: 1 0 auto; 23 | align-self: stretch; 24 | justify-self: stretch; 25 | 26 | min-height: 600px; 27 | 28 | gap: 32px; 29 | } 30 | 31 | .arrow { 32 | min-width: 96px; 33 | max-width: 96px; 34 | cursor: pointer; 35 | flex: 0 0 auto; 36 | color: var(--ifm-navbar-link-color); 37 | } 38 | 39 | .arrow:hover { 40 | color: var(--ifm-navbar-link-hover-color); 41 | } 42 | 43 | .arrow.left { 44 | left: 0; 45 | } 46 | 47 | .arrow.right { 48 | right: 0; 49 | } 50 | 51 | .selectedImage { 52 | display: flex; 53 | flex-direction: column; 54 | flex: 1 1 auto; 55 | 56 | align-items: center; 57 | justify-content: center; 58 | } 59 | 60 | .selectedImage img { 61 | max-height: 600px; 62 | object-fit: contain; 63 | } 64 | 65 | .thumbnailContainer { 66 | display: flex; 67 | gap: 4px; 68 | flex-direction: row; 69 | align-items: center; 70 | } 71 | 72 | .imageThumbnail { 73 | display: flex; 74 | padding: 16px; 75 | cursor: pointer; 76 | align-items: center; 77 | justify-content: center; 78 | 79 | padding: 0px 12px; 80 | } 81 | 82 | .imageThumbnail.selected { 83 | outline: 2px solid var(--ifm-color-primary); 84 | } 85 | 86 | .imageThumbnail img { 87 | width: 100px; 88 | height: fit-content; 89 | } 90 | 91 | .imageThumbnail.left img { 92 | mask-image: linear-gradient(to left, black 0%, transparent 70%); 93 | } 94 | 95 | .imageThumbnail.right img { 96 | mask-image: linear-gradient(to right, black 0%, transparent 70%); 97 | } 98 | 99 | @media screen and (max-width: 996px) { 100 | .gallery { 101 | padding: 24px 0px; 102 | } 103 | 104 | .arrow { 105 | min-width: 48px; 106 | max-width: 48px; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /website/src/components/HomepageFeatures/index.tsx: -------------------------------------------------------------------------------- 1 | import type { ReactNode } from "react"; 2 | import clsx from "clsx"; 3 | import Heading from "@theme/Heading"; 4 | import styles from "./styles.module.css"; 5 | 6 | type FeatureItem = { 7 | title: string; 8 | Svg: React.ComponentType>; 9 | description: ReactNode; 10 | }; 11 | 12 | const FeatureList: FeatureItem[] = [ 13 | { 14 | title: "Ready to Go", 15 | Svg: require("@site/static/img/rocket.svg").default, 16 | description: ( 17 | <> 18 | Ashell is ready to use out of the box. Just install it, start using it, 19 | and customize only what you need. 20 | 21 | ), 22 | }, 23 | { 24 | title: "Everything You Need, Built In", 25 | Svg: require("@site/static/img/settings.svg").default, 26 | description: ( 27 | <> 28 | Ashell comes with essential modules like workspaces, time, battery, 29 | network, and more. No need to hunt for plugins or write custom scripts. 30 | 31 | ), 32 | }, 33 | { 34 | title: "Powered by iced", 35 | Svg: require("@site/static/img/iced.svg").default, 36 | description: ( 37 | <> 38 | A cross-platform GUI library for Rust focused on simplicity and 39 | type-safety. 40 | 41 | ), 42 | }, 43 | ]; 44 | 45 | function Feature({ title, Svg, description }: FeatureItem) { 46 | return ( 47 |
48 |
49 | 50 |
51 |
52 | {title} 53 |

{description}

54 |
55 |
56 | ); 57 | } 58 | 59 | export default function HomepageFeatures(): ReactNode { 60 | return ( 61 |
62 |
63 |
64 | {FeatureList.map((props, idx) => ( 65 | 66 | ))} 67 |
68 |
69 |
70 | ); 71 | } 72 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.6.0/configuration/appearance/general.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # General 6 | 7 | These are all the appearance options not related to the color palette. 8 | 9 | ## Font 10 | 11 | You can change the font used by setting the `font_name` field. This configuration 12 | is optional—if not set, the `iced` library will use the default font. 13 | 14 | ```toml 15 | [appearance] 16 | font_name = "Comic Sans MS" 17 | ``` 18 | 19 | :::warning 20 | 21 | Changing the font requires to kill and restart ashell process. The font configuration does not support hot-reloading 22 | 23 | ::: 24 | 25 | ## Scaling Factor 26 | 27 | You can change the scaling factor of the status bar using the `scale_factor` field. 28 | 29 | The value should be a float greater than `0.0` and less than or equal to `2.0`. 30 | The default value is `1.0`. 31 | 32 | ```toml 33 | [appearance] 34 | scale_factor = 1.5 35 | ``` 36 | 37 | ## Status Bar Style 38 | 39 | You can change the style of the status bar using the `style` field. 40 | 41 | You can choose between: 42 | 43 | - `Island`: This is the default style. Each module or module group is displayed 44 | in a rounded rectangle using the background color. 45 | - `Solid`: The status bar has a solid background color. 46 | - `Gradient`: The status bar has a gradient background color. 47 | 48 | ### Example 49 | 50 | ```toml 51 | [appearance] 52 | style = "Gradient" 53 | ``` 54 | 55 | ## Opacity 56 | 57 | You can change the opacity of the status bar components using the `opacity` field. 58 | 59 | The value should be a float between `0.0` and `1.0`, where `0.0` is fully transparent. 60 | The default value is `1.0`. 61 | 62 | It's also possible to define the opacity of status bar menus and whether they should 63 | include a backdrop effect. 64 | 65 | ## Examples 66 | 67 | Setting the opacity of the status bar components: 68 | 69 | ```toml 70 | [appearance] 71 | opacity = 0.8 72 | ``` 73 | 74 | Also setting the opacity of the status bar menus and adding a backdrop effect: 75 | 76 | ```toml 77 | [appearance] 78 | opacity = 0.8 79 | 80 | [appearance.menu] 81 | opacity = 0.7 82 | backdrop = 0.3 83 | ``` 84 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.7.0/configuration/appearance/general.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # General 6 | 7 | These are all the appearance options not related to the color palette. 8 | 9 | ## Font 10 | 11 | You can change the font used by setting the `font_name` field. This configuration 12 | is optional—if not set, the `iced` library will use the default font. 13 | 14 | ```toml 15 | [appearance] 16 | font_name = "Comic Sans MS" 17 | ``` 18 | 19 | :::warning 20 | 21 | Changing the font requires to kill and restart ashell process. The font configuration does not support hot-reloading 22 | 23 | ::: 24 | 25 | ## Scaling Factor 26 | 27 | You can change the scaling factor of the status bar using the `scale_factor` field. 28 | 29 | The value should be a float greater than `0.0` and less than or equal to `2.0`. 30 | The default value is `1.0`. 31 | 32 | ```toml 33 | [appearance] 34 | scale_factor = 1.5 35 | ``` 36 | 37 | ## Status Bar Style 38 | 39 | You can change the style of the status bar using the `style` field. 40 | 41 | You can choose between: 42 | 43 | - `Island`: This is the default style. Each module or module group is displayed 44 | in a rounded rectangle using the background color. 45 | - `Solid`: The status bar has a solid background color. 46 | - `Gradient`: The status bar has a gradient background color. 47 | 48 | ### Example 49 | 50 | ```toml 51 | [appearance] 52 | style = "Gradient" 53 | ``` 54 | 55 | ## Opacity 56 | 57 | You can change the opacity of the status bar components using the `opacity` field. 58 | 59 | The value should be a float between `0.0` and `1.0`, where `0.0` is fully transparent. 60 | The default value is `1.0`. 61 | 62 | It's also possible to define the opacity of status bar menus and whether they should 63 | include a backdrop effect. 64 | 65 | ## Examples 66 | 67 | Setting the opacity of the status bar components: 68 | 69 | ```toml 70 | [appearance] 71 | opacity = 0.8 72 | ``` 73 | 74 | Also setting the opacity of the status bar menus and adding a backdrop effect: 75 | 76 | ```toml 77 | [appearance] 78 | opacity = 0.8 79 | 80 | [appearance.menu] 81 | opacity = 0.7 82 | backdrop = 0.3 83 | ``` 84 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.6.0/configuration/modules/workspaces.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 4 3 | --- 4 | 5 | # Workspaces 6 | 7 | This module provides information about the current workspaces 8 | and allows switching between them. 9 | 10 | You can switch between two main visibility modes: 11 | 12 | - `All`: All workspaces will be displayed. 13 | - `MonitorSpecific`: Only the workspaces of the related monitor will be displayed. 14 | 15 | You can also enable or disable filling the workspace 16 | list with empty workspaces using the `enable_workspace_filling` option. 17 | 18 | The default configuration is: 19 | 20 | ```toml 21 | [workspaces] 22 | visibility_mode = "All" 23 | enable_workspace_filling = true 24 | ``` 25 | 26 | If you want a specific number of empty workspaces always displayed, 27 | you can use the `max_workspaces` option. This setting only works 28 | if `enable_workspace_filling` is set to `true`. 29 | 30 | Usually, `enable_workspace_filling` will create empty workspaces 31 | up to the greatest workspace in use. 32 | For example, if you have a window open in workspace 1 and 33 | another one in workspace 5, ashell will create empty 34 | workspaces 2, 3, and 4 to fill the gap. 35 | 36 | With `max_workspaces` set to 10, ashell will also create 37 | workspaces 6, 7, 8, 9, and 10. 38 | 39 | By default, `max_workspaces` is None, which disables this feature. 40 | 41 | ## Examples 42 | 43 | If you want to disable workspace filling and set the visibility mode 44 | to "MonitorSpecific", you can do it like this: 45 | 46 | ```toml 47 | [workspaces] 48 | visibility_mode = "MonitorSpecific" 49 | enable_workspace_filling = false 50 | ``` 51 | 52 | If you want to set the maximum number of workspaces to 10, you can do it like this: 53 | 54 | ```toml 55 | [workspaces] 56 | enable_workspace_filling = true 57 | max_workspaces = 10 58 | ``` 59 | You can also assign **custom names** to your workspaces using the `workspace_names` option. 60 | This lets you display alternative numerals (e.g., roman numerals, chinese numerals) instead of typical arabic numerals. 61 | If a name is missing for a given workspace index, the numeric ID will be used as a fallback. 62 | 63 | ```toml 64 | [workspaces] 65 | workspace_names = ["一","二","三","四","五","六","七","八","九","十",] 66 | 67 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.6.0/installation.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | --- 4 | 5 | # 🛠️ Installation 6 | 7 | You can install Ashell using the following methods: 8 | 9 | ## Packages 10 | 11 | :::info 12 | 13 | I only maintain the Arch Linux package and the Nix configuration included 14 | in the repository. 15 | 16 | If a package is broken, try building from source first. 17 | 18 | ::: 19 | 20 | [![Packaging status](https://repology.org/badge/vertical-allrepos/ashell.svg)](https://repology.org/project/ashell/versions) 21 | 22 | ### Arch Linux 23 | 24 | Install a tagged release from the AUR repositories: 25 | 26 | ```bash 27 | yay -S ashell 28 | ``` 29 | 30 | Or install from the AUR, which compiles the latest source: 31 | 32 | ```bash 33 | yay -S ashell-git 34 | ``` 35 | 36 | ### Nix 37 | 38 | To install Ashell using the Nix package manager, make sure flakes are enabled, 39 | then run: 40 | 41 | #### Tagged Release 42 | 43 | ```bash 44 | nix profile install github:MalpenZibo/ashell?ref=0.5.0 45 | ``` 46 | 47 | #### Main Branch 48 | 49 | ```bash 50 | nix profile install github:MalpenZibo/ashell 51 | ``` 52 | 53 | ### NixOS / Home Manager 54 | 55 | To use this flake, add the input to your `flake.nix`: 56 | 57 | ```nix 58 | inputs = { 59 | # ... other inputs 60 | ashell.url = "github:MalpenZibo/ashell"; 61 | # ... other inputs 62 | }; 63 | outputs = {...} @ inputs: {}; # Make sure to pass inputs to your specialArgs! 64 | ``` 65 | 66 | And in your `configuration.nix`: 67 | 68 | ```nix 69 | { pkgs, inputs, ... }: 70 | 71 | { 72 | environment.systemPackages = [inputs.ashell.defaultPackage.${pkgs.system}]; 73 | # or home.packages = ... 74 | } 75 | ``` 76 | 77 | This will build Ashell from source. 78 | Alternatively, you can use `pkgs.ashell` from `nixpkgs`, which is cached. 79 | 80 | ## Building from Source 81 | 82 | To build Ashell from source, ensure the following dependencies are installed: 83 | 84 | - Rust (with `cargo`) 85 | - wayland-protocols 86 | - clang 87 | - libxkbcommon 88 | - wayland 89 | - dbus 90 | - libpipewire 91 | - libpulse 92 | 93 | Then, from the root of the repository, run: 94 | 95 | ```bash 96 | cargo build --release 97 | 98 | # To install it system-wide 99 | sudo cp target/release/ashell /usr/bin 100 | ``` 101 | -------------------------------------------------------------------------------- /src/modules/privacy.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | components::icons::{StaticIcon, icon}, 3 | services::{ReadOnlyService, ServiceEvent, privacy::PrivacyService}, 4 | theme::AshellTheme, 5 | }; 6 | use iced::{ 7 | Alignment, Element, Subscription, 8 | widget::{Row, container}, 9 | }; 10 | 11 | #[derive(Debug, Clone)] 12 | pub enum Message { 13 | Event(ServiceEvent), 14 | } 15 | 16 | #[derive(Debug, Default, Clone)] 17 | pub struct Privacy { 18 | pub service: Option, 19 | } 20 | 21 | impl Privacy { 22 | pub fn update(&mut self, message: Message) { 23 | match message { 24 | Message::Event(event) => match event { 25 | ServiceEvent::Init(service) => { 26 | self.service = Some(service); 27 | } 28 | ServiceEvent::Update(data) => { 29 | if let Some(privacy) = self.service.as_mut() { 30 | privacy.update(data); 31 | } 32 | } 33 | ServiceEvent::Error(_) => {} 34 | }, 35 | } 36 | } 37 | 38 | pub fn view(&'_ self, theme: &AshellTheme) -> Option> { 39 | if let Some(service) = self.service.as_ref() 40 | && !service.no_access() 41 | { 42 | Some( 43 | container( 44 | Row::new() 45 | .push_maybe( 46 | service 47 | .screenshare_access() 48 | .then(|| icon(StaticIcon::ScreenShare)), 49 | ) 50 | .push_maybe(service.webcam_access().then(|| icon(StaticIcon::Webcam))) 51 | .push_maybe(service.microphone_access().then(|| icon(StaticIcon::Mic1))) 52 | .align_y(Alignment::Center) 53 | .spacing(theme.space.xs), 54 | ) 55 | .style(|theme| container::Style { 56 | text_color: Some(theme.extended_palette().danger.weak.color), 57 | ..Default::default() 58 | }) 59 | .into(), 60 | ) 61 | } else { 62 | None 63 | } 64 | } 65 | 66 | pub fn subscription(&self) -> Subscription { 67 | PrivacyService::subscribe().map(Message::Event) 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.6.0/configuration/modules/custom_module.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 13 3 | --- 4 | 5 | # Custom Modules 6 | 7 | This special module type lets you extend the functionality of Ashell 8 | by creating your own simple components. 9 | 10 | A **custom module** allows you to: 11 | 12 | - Display the output of a command (live). 13 | - Run a command when the module is clicked. 14 | - Change icons dynamically based on output. 15 | - Show an alert indicator based on specific conditions. 16 | 17 | ## Configuration 18 | 19 | To define a custom module, use the following fields: 20 | 21 | - `name`: Name of the module. Use this to refer to it in the [modules definitions](./index.md). 22 | - `icon`: Icon displayed in the status bar. 23 | - `command`: Command to execute when the module is clicked. 24 | - `listen_cmd` _(optional)_: Command to run in the background to update the 25 | module’s display. 26 | - `icons` _(optional)_: Regex-to-icon mapping to change the icon based on 27 | the `listen_cmd` output. 28 | - `alert` _(optional)_: Regex to trigger a red alert dot on the icon when 29 | matched in the `listen_cmd` output. 30 | 31 | --- 32 | 33 | ## `listen_cmd` 34 | 35 | The `listen_cmd` should output JSON in 36 | the [Waybar format](https://github.com/Alexays/Waybar/wiki/Module:-Custom#script-output), 37 | using `text` and `alt` fields. 38 | 39 | ### Example Output 40 | 41 | ```json 42 | { 43 | "text": "3", 44 | "alt": "notification" 45 | } 46 | ``` 47 | 48 | --- 49 | 50 | ## Dynamic Icons 51 | 52 | You can change the icon depending on the value of `alt` in the `listen_cmd` output. 53 | 54 | ### Icons Example 55 | 56 | ```toml 57 | icons.'dnd.*' = "" 58 | ``` 59 | 60 | This will change the icon to `` when `alt` matches `dnd.*`. 61 | 62 | --- 63 | 64 | ## Alerts 65 | 66 | Use the `alert` field to show a red dot on the module icon if the output 67 | matches a given regex. 68 | 69 | ### Alerts Example 70 | 71 | ```toml 72 | alert = ".*notification" 73 | ``` 74 | 75 | --- 76 | 77 | ## Examples 78 | 79 | ### Notifications (with swaync-client) 80 | 81 | ```toml 82 | [[CustomModule]] 83 | name = "CustomNotifications" 84 | icon = "" 85 | command = "swaync-client -t -sw" 86 | listen_cmd = "swaync-client -swb" 87 | icons.'dnd.*' = "" 88 | alert = ".*notification" 89 | ``` 90 | 91 | ### App Launcher (with walker) 92 | 93 | ```toml 94 | [[CustomModule]] 95 | name = "AppLauncher" 96 | icon = "󱗼" 97 | command = "walker" 98 | ``` 99 | -------------------------------------------------------------------------------- /website/docs/installation.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | --- 4 | 5 | # 🛠️ Installation 6 | 7 | You can install Ashell using the following methods: 8 | 9 | ## Packages 10 | 11 | :::info 12 | 13 | Officially maintained: Arch Linux package and the Nix configuration 14 | included in the repository. 15 | 16 | Community packaging: Fedora via Copr (see below). If a package is broken, 17 | try building from source first. 18 | 19 | ::: 20 | 21 | [![Packaging status](https://repology.org/badge/vertical-allrepos/ashell.svg)](https://repology.org/project/ashell/versions) 22 | 23 | ### Arch Linux 24 | 25 | Install a tagged release from the AUR repositories: 26 | 27 | ```bash 28 | yay -S ashell 29 | ``` 30 | 31 | Or install from the AUR, which compiles the latest source: 32 | 33 | ```bash 34 | yay -S ashell-git 35 | ``` 36 | 37 | ### Nix 38 | 39 | To install Ashell using the Nix package manager, make sure flakes are enabled, 40 | then run: 41 | 42 | #### Tagged Release 43 | 44 | ```bash 45 | nix profile install github:MalpenZibo/ashell?ref=0.5.0 46 | ``` 47 | 48 | #### Main Branch 49 | 50 | ```bash 51 | nix profile install github:MalpenZibo/ashell 52 | ``` 53 | 54 | ### NixOS / Home Manager 55 | 56 | To use this flake, add the input to your `flake.nix`: 57 | 58 | ```nix 59 | inputs = { 60 | # ... other inputs 61 | ashell.url = "github:MalpenZibo/ashell"; 62 | # ... other inputs 63 | }; 64 | outputs = {...} @ inputs: {}; # Make sure to pass inputs to your specialArgs! 65 | ``` 66 | 67 | And in your `configuration.nix`: 68 | 69 | ```nix 70 | { pkgs, inputs, ... }: 71 | 72 | { 73 | environment.systemPackages = [inputs.ashell.packages.${pkgs.system}.default]; 74 | # or home.packages = ... 75 | } 76 | ``` 77 | 78 | This will build Ashell from source. 79 | Alternatively, you can use `pkgs.ashell` from `nixpkgs`, which is cached. 80 | 81 | ### Fedora (Copr) 82 | 83 | Unofficial Copr repository (maintained by @killcrb): 84 | 85 | ```bash 86 | sudo dnf -y copr enable killcrb/ashell 87 | sudo dnf -y install ashell 88 | ``` 89 | 90 | ## Building from Source 91 | 92 | To build Ashell from source, ensure the following dependencies are installed: 93 | 94 | - Rust (with `cargo`) 95 | - wayland-protocols 96 | - clang 97 | - libxkbcommon 98 | - wayland 99 | - dbus 100 | - libpipewire 101 | - libpulse 102 | 103 | Then, from the root of the repository, run: 104 | 105 | ```bash 106 | cargo build --release 107 | 108 | # To install it system-wide 109 | sudo cp target/release/ashell /usr/local/bin/ashell 110 | ``` 111 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.7.0/installation.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | --- 4 | 5 | # 🛠️ Installation 6 | 7 | You can install Ashell using the following methods: 8 | 9 | ## Packages 10 | 11 | :::info 12 | 13 | Officially maintained: Arch Linux package and the Nix configuration 14 | included in the repository. 15 | 16 | Community packaging: Fedora via Copr (see below). If a package is broken, 17 | try building from source first. 18 | 19 | ::: 20 | 21 | [![Packaging status](https://repology.org/badge/vertical-allrepos/ashell.svg)](https://repology.org/project/ashell/versions) 22 | 23 | ### Arch Linux 24 | 25 | Install a tagged release from the AUR repositories: 26 | 27 | ```bash 28 | yay -S ashell 29 | ``` 30 | 31 | Or install from the AUR, which compiles the latest source: 32 | 33 | ```bash 34 | yay -S ashell-git 35 | ``` 36 | 37 | ### Nix 38 | 39 | To install Ashell using the Nix package manager, make sure flakes are enabled, 40 | then run: 41 | 42 | #### Tagged Release 43 | 44 | ```bash 45 | nix profile install github:MalpenZibo/ashell?ref=0.5.0 46 | ``` 47 | 48 | #### Main Branch 49 | 50 | ```bash 51 | nix profile install github:MalpenZibo/ashell 52 | ``` 53 | 54 | ### NixOS / Home Manager 55 | 56 | To use this flake, add the input to your `flake.nix`: 57 | 58 | ```nix 59 | inputs = { 60 | # ... other inputs 61 | ashell.url = "github:MalpenZibo/ashell"; 62 | # ... other inputs 63 | }; 64 | outputs = {...} @ inputs: {}; # Make sure to pass inputs to your specialArgs! 65 | ``` 66 | 67 | And in your `configuration.nix`: 68 | 69 | ```nix 70 | { pkgs, inputs, ... }: 71 | 72 | { 73 | environment.systemPackages = [inputs.ashell.packages.${pkgs.system}.default]; 74 | # or home.packages = ... 75 | } 76 | ``` 77 | 78 | This will build Ashell from source. 79 | Alternatively, you can use `pkgs.ashell` from `nixpkgs`, which is cached. 80 | 81 | ### Fedora (Copr) 82 | 83 | Unofficial Copr repository (maintained by @killcrb): 84 | 85 | ```bash 86 | sudo dnf -y copr enable killcrb/ashell 87 | sudo dnf -y install ashell 88 | ``` 89 | 90 | ## Building from Source 91 | 92 | To build Ashell from source, ensure the following dependencies are installed: 93 | 94 | - Rust (with `cargo`) 95 | - wayland-protocols 96 | - clang 97 | - libxkbcommon 98 | - wayland 99 | - dbus 100 | - libpipewire 101 | - libpulse 102 | 103 | Then, from the root of the repository, run: 104 | 105 | ```bash 106 | cargo build --release 107 | 108 | # To install it system-wide 109 | sudo cp target/release/ashell /usr/local/bin/ashell 110 | ``` 111 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ashell" 3 | description = "A ready to go Wayland status bar for Hyprland and Niri" 4 | homepage = "https://malpenzibo.github.io/ashell/" 5 | repository = "https://github.com/MalpenZibo/ashell" 6 | license = "MIT" 7 | version = "0.7.0" 8 | edition = "2024" 9 | rust-version = "1.88" 10 | 11 | [profile.release] 12 | lto = "thin" 13 | strip = true 14 | opt-level = 3 15 | panic = "abort" 16 | 17 | # The profile that 'dist' will build with 18 | [profile.dist] 19 | inherits = "release" 20 | 21 | [package.metadata.nfpm] 22 | provides = ["ashell"] 23 | depends = [ 24 | "libxkbcommon", 25 | "dbus", 26 | ] 27 | 28 | [package.metadata.nfpm.deb] 29 | depends = [ 30 | "libwayland-client0", 31 | "libpipewire-0.3-0t64", 32 | "libpulse0", 33 | ] 34 | [package.metadata.nfpm.rpm] 35 | depends = [ 36 | "libwayland-client", 37 | "pipewire-libs", 38 | "pulseaudio-libs", 39 | ] 40 | 41 | [dependencies] 42 | iced = { git = "https://github.com/MalpenZibo/iced", rev = "237116726a405b326bf6f61f2b9105b38a938490", features = [ 43 | "tokio", 44 | "multi-window", 45 | "advanced", 46 | "wgpu", 47 | "winit", 48 | "wayland", 49 | "image", 50 | "svg", 51 | "canvas" 52 | ] } 53 | chrono = { version = "0.4", default-features = false, features = ["clock"] } 54 | hyprland = "0.4.0-beta.2" 55 | serde = { version = "1.0", default-features = false, features = [] } 56 | sysinfo = "0.37" 57 | tokio = { version = "1", default-features = false, features = [] } 58 | zbus = { version = "5", default-features = false, features = ["tokio"] } 59 | libpulse-binding = { version = "2.28", features = ["pa_v15"] } 60 | log = { version = "0.4", features = [] } 61 | flexi_logger = "0.31" 62 | pipewire = "0.9" 63 | wayland-client = "0.31.5" 64 | wayland-protocols = { version = "0.32.3", features = ["client", "unstable"] } 65 | itertools = "0.14" 66 | hex_color = { version = "3", features = ["serde"] } 67 | anyhow = "1" 68 | udev = { version = "0.9", features = ["send", "sync"] } 69 | toml = "0.9" 70 | freedesktop-icons = "0.4" 71 | linicon-theme = "1.2.0" 72 | serde_json = "1" 73 | regex = "1.12.2" 74 | serde_with = "3.12.0" 75 | tokio-stream = "0.1.17" 76 | uuid = { version = "1.16.0", features = ["v4"] } 77 | clap = { version = "4.5", features = ["derive"] } 78 | shellexpand = { version = "3", features = ["path"] } 79 | inotify = "0.11.0" 80 | pin-project-lite = "0.2.16" 81 | niri-ipc = "25.11.0" 82 | parking_lot = "0.12.5" 83 | 84 | [build-dependencies] 85 | allsorts = "0.15" 86 | 87 | [package.metadata.rpm] 88 | package = "ashell" 89 | 90 | [package.metadata.rpm.cargo] 91 | buildflags = ["--release"] 92 | 93 | [package.metadata.rpm.targets] 94 | ashell = { path = "/usr/bin/ashell" } 95 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.6.0/configuration/modules/settings.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 12 3 | --- 4 | 5 | # Settings 6 | 7 | This module provides access to system settings like audio, network, bluetooth, 8 | battery, power profile and idle inhibitor. 9 | 10 | It displays in the status bar indicator about: 11 | 12 | - Audio volume 13 | - Network status 14 | - Battery status 15 | - Power profile 16 | - Idle inhibitor status 17 | 18 | And let you interact with these settings: 19 | 20 | - Change audio and microphone volume 21 | - Change audio output and input devices 22 | - Toggle network connection 23 | - Toggle VPN connection 24 | - Toggle airplane mode 25 | - Change brightness 26 | - Toggle bluetooth 27 | - Change power profile 28 | - Toggle idle inhibitor 29 | - Lock the screen 30 | - Suspend, logout, reboot, or shutdown the system 31 | 32 | You can configure some function of this module. 33 | 34 | With the `lock_cmd` option you can set a command to lock 35 | the system, if not set the related button will not appear. 36 | 37 | With the `shutdown_cmd`, `suspend_cmd`, `reboot_cmd`, and `logout_cmd`, 38 | you can change the related commands to shut down, suspend, reboot, 39 | or log out of the system. 40 | These parameters are optional and have the following default values: 41 | 42 | ```toml 43 | shutdown_cmd = "shutdown now" 44 | suspend_cmd = "systemctl suspend" 45 | reboot_cmd = "systemctl reboot" 46 | logout_cmd = "loginctl kill-user $(whoami)" 47 | ``` 48 | 49 | With the `audio_sinks_more_cmd` and `audio_sources_more_cmd` 50 | options you can set commands to open the audio settings 51 | for sinks and sources, if not set the related buttons will not appear. 52 | 53 | With the `wifi_more_cmd`, `vpn_more_cmd` and `bluetooth_more_cmd` options 54 | you can set commands to open the network, VPN and bluetooth settings. 55 | 56 | With the `remove_airplane_btn` option you can remove the airplane mode button. 57 | 58 | With the `remove_idle_btn` option you can remove the idle inhibitor button. 59 | 60 | ## Example 61 | 62 | In the following example we use: 63 | 64 | - `hyprlock` to lock the screen 65 | - `pavucontrol` to open the audio settings for sinks and sources 66 | directly in the correct tab. 67 | - `nm-connection-editor` to open the wifi and VPN settings 68 | - `blueman-manager` to open the bluetooth settings 69 | 70 | We also disable the airplane mode button and the idle inhibitor button. 71 | 72 | ```toml 73 | [settings] 74 | lock_cmd = "hyprlock &" 75 | audio_sinks_more_cmd = "pavucontrol -t 3" 76 | audio_sources_more_cmd = "pavucontrol -t 4" 77 | wifi_more_cmd = "nm-connection-editor" 78 | vpn_more_cmd = "nm-connection-editor" 79 | bluetooth_more_cmd = "blueman-manager" 80 | remove_airplane_btn = true 81 | remove_idle_btn = true 82 | ``` 83 | -------------------------------------------------------------------------------- /src/modules/keyboard_layout.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | config::KeyboardLayoutModuleConfig, 3 | services::{ 4 | ReadOnlyService, Service, ServiceEvent, 5 | compositor::{CompositorCommand, CompositorService}, 6 | }, 7 | theme::AshellTheme, 8 | }; 9 | use iced::{Element, Subscription, Task, widget::text}; 10 | 11 | #[derive(Debug, Clone)] 12 | pub enum Message { 13 | ServiceEvent(ServiceEvent), 14 | ChangeLayout, 15 | ConfigReloaded(KeyboardLayoutModuleConfig), 16 | } 17 | 18 | pub struct KeyboardLayout { 19 | config: KeyboardLayoutModuleConfig, 20 | service: Option, 21 | } 22 | 23 | impl KeyboardLayout { 24 | pub fn new(config: KeyboardLayoutModuleConfig) -> Self { 25 | Self { 26 | config, 27 | service: None, 28 | } 29 | } 30 | 31 | pub fn update(&mut self, message: Message) -> Task { 32 | match message { 33 | Message::ServiceEvent(event) => { 34 | match event { 35 | ServiceEvent::Init(s) => self.service = Some(s), 36 | ServiceEvent::Update(e) => { 37 | if let Some(service) = &mut self.service { 38 | service.update(e); 39 | } 40 | } 41 | _ => {} 42 | } 43 | Task::none() 44 | } 45 | Message::ChangeLayout => { 46 | if let Some(service) = &mut self.service { 47 | return service 48 | .command(CompositorCommand::NextLayout) 49 | .map(Message::ServiceEvent); 50 | } 51 | Task::none() 52 | } 53 | Message::ConfigReloaded(new_config) => { 54 | self.config = new_config; 55 | Task::none() 56 | } 57 | } 58 | } 59 | 60 | pub fn view(&self, _: &AshellTheme) -> Option> { 61 | let service = self.service.as_ref()?; 62 | let active_layout = &service.keyboard_layout; 63 | 64 | // Fallback to displaying the layout ID/Name if no label config exists 65 | let label = match self.config.labels.get(active_layout) { 66 | Some(value) => value.to_string(), 67 | None => active_layout.clone(), 68 | }; 69 | 70 | // Returns plain text matching original implementation style. 71 | // (Assuming parent container or mouse area handles interactions if any) 72 | Some(text(label).into()) 73 | } 74 | 75 | pub fn subscription(&self) -> Subscription { 76 | CompositorService::subscribe().map(Message::ServiceEvent) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/services/network/iwd_dbus/station.rs: -------------------------------------------------------------------------------- 1 | //! # D-Bus interface proxy for: `net.connman.iwd.Station` 2 | //! 3 | //! This code was generated by `zbus-xmlgen` `5.1.0` from D-Bus introspection data. 4 | //! 5 | //! You may prefer to adapt it, instead of using it verbatim. 6 | //! 7 | //! More information can be found in the [Writing a client proxy] section of the zbus 8 | //! documentation. 9 | //! 10 | //! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the 11 | //! following zbus API can be used: 12 | //! 13 | //! * [`zbus::fdo::IntrospectableProxy`] 14 | //! * [`zbus::fdo::PropertiesProxy`] 15 | //! 16 | //! Consequently `zbus-xmlgen` did not generate code for the above interfaces. 17 | //! 18 | //! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html 19 | //! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces, 20 | use zbus::proxy; 21 | #[proxy(interface = "net.connman.iwd.Station", assume_defaults = true)] 22 | pub trait Station { 23 | /// ConnectHiddenNetwork method 24 | fn connect_hidden_network(&self, name: &str) -> zbus::Result<()>; 25 | 26 | /// Disconnect method 27 | fn disconnect(&self) -> zbus::Result<()>; 28 | 29 | /// GetHiddenAccessPoints method 30 | fn get_hidden_access_points(&self) -> zbus::Result>; 31 | 32 | /// GetOrderedNetworks method 33 | fn get_ordered_networks(&self) -> zbus::Result>; 34 | 35 | /// RegisterSignalLevelAgent method 36 | fn register_signal_level_agent( 37 | &self, 38 | path: &zbus::zvariant::ObjectPath<'_>, 39 | levels: &[i16], 40 | ) -> zbus::Result<()>; 41 | 42 | /// Scan method 43 | fn scan(&self) -> zbus::Result<()>; 44 | 45 | /// UnregisterSignalLevelAgent method 46 | fn unregister_signal_level_agent( 47 | &self, 48 | path: &zbus::zvariant::ObjectPath<'_>, 49 | ) -> zbus::Result<()>; 50 | 51 | /// Affinities property 52 | #[zbus(property)] 53 | fn affinities(&self) -> zbus::Result>; 54 | #[zbus(property)] 55 | fn set_affinities(&self, value: &[&zbus::zvariant::ObjectPath<'_>]) -> zbus::Result<()>; 56 | 57 | /// ConnectedAccessPoint property 58 | #[zbus(property)] 59 | fn connected_access_point(&self) -> zbus::Result; 60 | 61 | /// ConnectedNetwork property 62 | #[zbus(property)] 63 | fn connected_network(&self) -> zbus::Result; 64 | 65 | /// Scanning property 66 | #[zbus(property)] 67 | fn scanning(&self) -> zbus::Result; 68 | 69 | /// State property 70 | #[zbus(property)] 71 | fn state(&self) -> zbus::Result; 72 | } 73 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "A ready to go Wayland status bar for Hyprland and Niri"; 3 | 4 | inputs = { 5 | crane.url = "github:ipetkov/crane"; 6 | nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; 7 | rust-overlay = { 8 | url = "github:oxalica/rust-overlay"; 9 | inputs = { 10 | nixpkgs.follows = "nixpkgs"; 11 | }; 12 | }; 13 | }; 14 | 15 | outputs = 16 | { 17 | crane, 18 | nixpkgs, 19 | rust-overlay, 20 | ... 21 | }: 22 | let 23 | forAllSystems = with nixpkgs; (lib.genAttrs lib.systems.flakeExposed); 24 | perSystem = forAllSystems (system: rec { 25 | overlays = [ (import rust-overlay) ]; 26 | pkgs = import nixpkgs { 27 | inherit system overlays; 28 | }; 29 | craneLib = crane.mkLib pkgs; 30 | rustToolchain = pkgs.rust-bin.stable.latest; 31 | buildInputs = with pkgs; [ 32 | rustToolchain.default 33 | rustPlatform.bindgenHook 34 | pkg-config 35 | libxkbcommon 36 | libGL 37 | pipewire 38 | libpulseaudio 39 | wayland 40 | vulkan-loader 41 | udev 42 | ]; 43 | runtimeDependencies = with pkgs; [ 44 | libpulseaudio 45 | wayland 46 | mesa 47 | vulkan-loader 48 | libGL 49 | libglvnd 50 | ]; 51 | ldLibraryPath = pkgs.lib.makeLibraryPath runtimeDependencies; 52 | defaultPackage = craneLib.buildPackage { 53 | src = ./.; 54 | 55 | nativeBuildInputs = with pkgs; [ 56 | makeWrapper 57 | pkg-config 58 | autoPatchelfHook # Add runtimeDependencies to rpath 59 | ]; 60 | 61 | inherit buildInputs runtimeDependencies ldLibraryPath; 62 | 63 | postInstall = '' 64 | wrapProgram "$out/bin/ashell" --prefix LD_LIBRARY_PATH : "${ldLibraryPath}" 65 | ''; 66 | meta.mainProgram = "ashell"; 67 | }; 68 | 69 | devShell = pkgs.mkShell { 70 | inherit ldLibraryPath; 71 | buildInputs = buildInputs ++ [ 72 | pkgs.rust-analyzer-unwrapped 73 | pkgs.nixfmt-rfc-style 74 | ]; 75 | 76 | RUST_SRC_PATH = "${rustToolchain.rust-src}/lib/rustlib/src/rust/library"; 77 | LD_LIBRARY_PATH = ldLibraryPath; 78 | }; 79 | 80 | formatter = pkgs.nixfmt-rfc-style; 81 | }); 82 | in 83 | { 84 | packages = forAllSystems (system: { 85 | default = perSystem.${system}.defaultPackage; 86 | }); 87 | devShells = forAllSystems (system: { 88 | default = perSystem.${system}.devShell; 89 | }); 90 | formatter = forAllSystems (system: perSystem.${system}.formatter); 91 | }; 92 | } 93 | -------------------------------------------------------------------------------- /website/docs/configuration/modules/custom_module.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 13 3 | --- 4 | 5 | # Custom Modules 6 | 7 | This special module type lets you extend the functionality of Ashell 8 | by creating your own simple components. 9 | 10 | A **custom module** allows you to: 11 | 12 | - Display the output of a command (live). 13 | - Run a command when the module is clicked. 14 | - Change icons dynamically based on output. 15 | - Show an alert indicator based on specific conditions. 16 | 17 | :::warning 18 | 19 | Ashell comes with a set of default icons that are used internally. 20 | 21 | If you specify a font icon in the custom module configuration remember 22 | to install the font with that icon on your system. 23 | 24 | For example you can use [Nerd Fonts](https://www.nerdfonts.com/) 25 | 26 | ::: 27 | 28 | ## Configuration 29 | 30 | To define a custom module, use the following fields: 31 | 32 | - `name`: Name of the module. Use this to refer to it in the [modules definitions](./index.md). 33 | - `icon`: Icon displayed in the status bar. 34 | - `command`: Command to execute when the module is clicked. 35 | - `listen_cmd` _(optional)_: Command to run in the background to update the 36 | module’s display. 37 | - `icons` _(optional)_: Regex-to-icon mapping to change the icon based on 38 | the `listen_cmd` output. 39 | - `alert` _(optional)_: Regex to trigger a red alert dot on the icon when 40 | matched in the `listen_cmd` output. 41 | 42 | --- 43 | 44 | ## `listen_cmd` 45 | 46 | The `listen_cmd` should output JSON in 47 | the [Waybar format](https://github.com/Alexays/Waybar/wiki/Module:-Custom#script-output), 48 | using `text` and `alt` fields. 49 | 50 | ### Example Output 51 | 52 | ```json 53 | { 54 | "text": "3", 55 | "alt": "notification" 56 | } 57 | ``` 58 | 59 | --- 60 | 61 | ## Dynamic Icons 62 | 63 | You can change the icon depending on the value of `alt` in the `listen_cmd` output. 64 | 65 | ### Icons Example 66 | 67 | ```toml 68 | icons.'dnd.*' = "" 69 | ``` 70 | 71 | This will change the icon to `` when `alt` matches `dnd.*`. 72 | 73 | --- 74 | 75 | ## Alerts 76 | 77 | Use the `alert` field to show a red dot on the module icon if the output 78 | matches a given regex. 79 | 80 | ### Alerts Example 81 | 82 | ```toml 83 | alert = ".*notification" 84 | ``` 85 | 86 | --- 87 | 88 | ## Examples 89 | 90 | ### Notifications (with swaync-client) 91 | 92 | ```toml 93 | [[CustomModule]] 94 | name = "CustomNotifications" 95 | icon = "" 96 | command = "swaync-client -t -sw" 97 | listen_cmd = "swaync-client -swb" 98 | icons.'dnd.*' = "" 99 | alert = ".*notification" 100 | ``` 101 | 102 | ### App Launcher (with walker) 103 | 104 | ```toml 105 | [[CustomModule]] 106 | name = "AppLauncher" 107 | icon = "󱗼" 108 | command = "walker" 109 | ``` 110 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.7.0/configuration/modules/custom_module.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 13 3 | --- 4 | 5 | # Custom Modules 6 | 7 | This special module type lets you extend the functionality of Ashell 8 | by creating your own simple components. 9 | 10 | A **custom module** allows you to: 11 | 12 | - Display the output of a command (live). 13 | - Run a command when the module is clicked. 14 | - Change icons dynamically based on output. 15 | - Show an alert indicator based on specific conditions. 16 | 17 | :::warning 18 | 19 | Ashell comes with a set of default icons that are used internally. 20 | 21 | If you specify a font icon in the custom module configuration remember 22 | to install the font with that icon on your system. 23 | 24 | For example you can use [Nerd Fonts](https://www.nerdfonts.com/) 25 | 26 | ::: 27 | 28 | ## Configuration 29 | 30 | To define a custom module, use the following fields: 31 | 32 | - `name`: Name of the module. Use this to refer to it in the [modules definitions](./index.md). 33 | - `icon`: Icon displayed in the status bar. 34 | - `command`: Command to execute when the module is clicked. 35 | - `listen_cmd` _(optional)_: Command to run in the background to update the 36 | module’s display. 37 | - `icons` _(optional)_: Regex-to-icon mapping to change the icon based on 38 | the `listen_cmd` output. 39 | - `alert` _(optional)_: Regex to trigger a red alert dot on the icon when 40 | matched in the `listen_cmd` output. 41 | 42 | --- 43 | 44 | ## `listen_cmd` 45 | 46 | The `listen_cmd` should output JSON in 47 | the [Waybar format](https://github.com/Alexays/Waybar/wiki/Module:-Custom#script-output), 48 | using `text` and `alt` fields. 49 | 50 | ### Example Output 51 | 52 | ```json 53 | { 54 | "text": "3", 55 | "alt": "notification" 56 | } 57 | ``` 58 | 59 | --- 60 | 61 | ## Dynamic Icons 62 | 63 | You can change the icon depending on the value of `alt` in the `listen_cmd` output. 64 | 65 | ### Icons Example 66 | 67 | ```toml 68 | icons.'dnd.*' = "" 69 | ``` 70 | 71 | This will change the icon to `` when `alt` matches `dnd.*`. 72 | 73 | --- 74 | 75 | ## Alerts 76 | 77 | Use the `alert` field to show a red dot on the module icon if the output 78 | matches a given regex. 79 | 80 | ### Alerts Example 81 | 82 | ```toml 83 | alert = ".*notification" 84 | ``` 85 | 86 | --- 87 | 88 | ## Examples 89 | 90 | ### Notifications (with swaync-client) 91 | 92 | ```toml 93 | [[CustomModule]] 94 | name = "CustomNotifications" 95 | icon = "" 96 | command = "swaync-client -t -sw" 97 | listen_cmd = "swaync-client -swb" 98 | icons.'dnd.*' = "" 99 | alert = ".*notification" 100 | ``` 101 | 102 | ### App Launcher (with walker) 103 | 104 | ```toml 105 | [[CustomModule]] 106 | name = "AppLauncher" 107 | icon = "󱗼" 108 | command = "walker" 109 | ``` 110 | -------------------------------------------------------------------------------- /src/modules/window_title.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | config::{WindowTitleConfig, WindowTitleMode}, 3 | services::{ReadOnlyService, ServiceEvent, compositor::CompositorService}, 4 | theme::AshellTheme, 5 | utils::truncate_text, 6 | }; 7 | use iced::{ 8 | Element, Subscription, 9 | widget::{container, text}, 10 | }; 11 | 12 | #[derive(Debug, Clone)] 13 | pub enum Message { 14 | ServiceEvent(ServiceEvent), 15 | ConfigReloaded(WindowTitleConfig), 16 | } 17 | 18 | pub struct WindowTitle { 19 | config: WindowTitleConfig, 20 | service: Option, 21 | value: Option, 22 | } 23 | 24 | impl WindowTitle { 25 | pub fn new(config: WindowTitleConfig) -> Self { 26 | Self { 27 | config, 28 | service: None, 29 | value: None, 30 | } 31 | } 32 | 33 | pub fn update(&mut self, message: Message) { 34 | match message { 35 | Message::ServiceEvent(event) => match event { 36 | ServiceEvent::Init(service) => { 37 | self.service = Some(service); 38 | self.recalculate_value(); 39 | } 40 | ServiceEvent::Update(event) => { 41 | if let Some(service) = &mut self.service { 42 | service.update(event); 43 | self.recalculate_value(); 44 | } 45 | } 46 | _ => {} 47 | }, 48 | Message::ConfigReloaded(cfg) => { 49 | self.config = cfg; 50 | self.recalculate_value(); 51 | } 52 | } 53 | } 54 | 55 | fn recalculate_value(&mut self) { 56 | if let Some(service) = &self.service { 57 | self.value = service.active_window.as_ref().map(|w| { 58 | let raw_title = match self.config.mode { 59 | WindowTitleMode::Title => &w.title, 60 | WindowTitleMode::Class => &w.class, 61 | }; 62 | 63 | if self.config.truncate_title_after_length > 0 { 64 | truncate_text(raw_title, self.config.truncate_title_after_length) 65 | } else { 66 | raw_title.clone() 67 | } 68 | }); 69 | } 70 | } 71 | 72 | pub fn get_value(&self) -> Option { 73 | self.value.clone() 74 | } 75 | 76 | pub fn view(&'_ self, theme: &AshellTheme, title: String) -> Element<'_, Message> { 77 | container( 78 | text(title) 79 | .size(theme.font_size.sm) 80 | .wrapping(text::Wrapping::None), 81 | ) 82 | .clip(true) 83 | .into() 84 | } 85 | 86 | pub fn subscription(&self) -> Subscription { 87 | CompositorService::subscribe().map(Message::ServiceEvent) 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /website/docs/configuration/modules/index.md: -------------------------------------------------------------------------------- 1 | # 🧩 Modules 2 | 3 | Ashell modules identify the various features of the status bar. 4 | 5 | Each module provides a set of functionalities that can be enabled 6 | or disabled in the configuration file. 7 | 8 | ## Organize modules 9 | 10 | The status bar is divided into three main sections: left, center, and right. 11 | 12 | Each section holds a list of modules or module groups, 13 | allowing flexible layout configuration. 14 | 15 | Modules can be used on their own or organized into groups. 16 | 17 | ### Default configuration 18 | 19 | ```toml 20 | [modules] 21 | left = [ "Workspaces" ] 22 | center = [ "WindowTitle" ] 23 | right = [ [ "Clock", "Privacy", "Settings" ] ] 24 | ``` 25 | 26 | ### Example 27 | 28 | If we want to add the `SystemInfo` module to the right side of 29 | the status bar but not in the same group as the `Clock`, `Privacy`, 30 | and `Settings` modules, we can do it like this: 31 | 32 | ```toml 33 | right = [ "SystemInfo", [ "Clock", "Privacy", "Settings" ] ] 34 | ``` 35 | 36 | ## Available modules 37 | 38 | The following modules are available: 39 | 40 | ### AppLauncher 41 | 42 | Provides a way to launch applications from the status bar. 43 | 44 | :::info 45 | This module requires additional configuration to work properly. 46 | See the dedicated section in the [documentation](./app_launcher.md). 47 | ::: 48 | 49 | :::warning 50 | This module will be deprecated in future releases. 51 | ::: 52 | 53 | ### Updates 54 | 55 | Provides information about available updates for the system. 56 | 57 | :::info 58 | This module requires additional configuration to work properly. 59 | See the dedicated section in the [documentation](./updates.md). 60 | ::: 61 | 62 | ### Clipboard 63 | 64 | Launches a clipboard manager. 65 | 66 | :::info 67 | This module requires additional configuration to work properly. 68 | See the dedicated section in the [documentation](./clipboard.md). 69 | ::: 70 | 71 | :::warning 72 | This module will be deprecated in future releases. 73 | ::: 74 | 75 | ### Workspaces 76 | 77 | Provides information about the current workspaces and allows switching between them. 78 | 79 | ### WindowTitle 80 | 81 | Displays the title of the currently focused window. 82 | 83 | ### SystemInfo 84 | 85 | Displays system information such as CPU usage, memory usage, and disk space. 86 | 87 | ### KeyboardLayout 88 | 89 | Displays the current keyboard layout and allows switching between layouts. 90 | 91 | ### KeyboardSubmap 92 | 93 | Displays the current keyboard submap. 94 | 95 | ### Tray 96 | 97 | Displays system tray icons and menus for applications. 98 | 99 | ### Clock 100 | 101 | Displays the current time and date. 102 | 103 | ### Privacy 104 | 105 | Provides privacy-related features, such as toggling microphone and camera access. 106 | 107 | ### MediaPlayer 108 | 109 | Displays media player controls and information about the currently playing media. 110 | 111 | ### Settings 112 | 113 | Provides access to system settings like audio, network, Bluetooth, battery, 114 | power profile, and idle inhibitor. 115 | -------------------------------------------------------------------------------- /src/modules/settings/brightness.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | components::icons::{StaticIcon, icon_mono}, 3 | services::{ 4 | ReadOnlyService, Service, ServiceEvent, 5 | brightness::{BrightnessCommand, BrightnessService}, 6 | }, 7 | theme::AshellTheme, 8 | }; 9 | use iced::{ 10 | Alignment, Element, Length, Subscription, Task, 11 | widget::{container, row, slider}, 12 | }; 13 | 14 | #[derive(Debug, Clone)] 15 | pub enum Message { 16 | Event(ServiceEvent), 17 | Change(u32), 18 | MenuOpened, 19 | } 20 | 21 | pub enum Action { 22 | None, 23 | Command(Task), 24 | } 25 | 26 | pub struct BrightnessSettings { 27 | service: Option, 28 | } 29 | 30 | impl BrightnessSettings { 31 | pub fn new() -> Self { 32 | Self { service: None } 33 | } 34 | 35 | pub fn update(&mut self, message: Message) -> Action { 36 | match message { 37 | Message::Event(event) => match event { 38 | ServiceEvent::Init(service) => { 39 | self.service = Some(service); 40 | Action::None 41 | } 42 | ServiceEvent::Update(data) => { 43 | if let Some(service) = self.service.as_mut() { 44 | service.update(data); 45 | } 46 | Action::None 47 | } 48 | _ => Action::None, 49 | }, 50 | Message::Change(value) => match self.service.as_mut() { 51 | Some(service) => Action::Command( 52 | service 53 | .command(BrightnessCommand::Set(value)) 54 | .map(Message::Event), 55 | ), 56 | _ => Action::None, 57 | }, 58 | Message::MenuOpened => { 59 | if let Some(service) = self.service.as_mut() { 60 | Action::Command( 61 | service 62 | .command(BrightnessCommand::Refresh) 63 | .map(Message::Event), 64 | ) 65 | } else { 66 | Action::None 67 | } 68 | } 69 | } 70 | } 71 | 72 | pub fn slider(&'_ self, theme: &AshellTheme) -> Option> { 73 | self.service.as_ref().map(|service| { 74 | row!( 75 | container(icon_mono(StaticIcon::Brightness)) 76 | .center_x(32.) 77 | .center_y(32.) 78 | .clip(true), 79 | slider(0..=100, service.current * 100 / service.max, |v| { 80 | Message::Change(v * service.max / 100) 81 | }) 82 | .step(1_u32) 83 | .width(Length::Fill), 84 | ) 85 | .align_y(Alignment::Center) 86 | .spacing(theme.space.xs) 87 | .into() 88 | }) 89 | } 90 | 91 | pub fn subscription(&self) -> Subscription { 92 | BrightnessService::subscribe().map(Message::Event) 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.6.0/configuration/modules/index.md: -------------------------------------------------------------------------------- 1 | # 🧩 Modules 2 | 3 | Ashell modules identify the various features of the status bar. 4 | 5 | Each module provides a set of functionalities that can be enabled 6 | or disabled in the configuration file. 7 | 8 | ## Organize modules 9 | 10 | The status bar is divided into three main sections: left, center, and right. 11 | 12 | Each section holds a list of modules or module groups, 13 | allowing flexible layout configuration. 14 | 15 | Modules can be used on their own or organized into groups. 16 | 17 | ### Default configuration 18 | 19 | ```toml 20 | [modules] 21 | left = [ "Workspaces" ] 22 | center = [ "WindowTitle" ] 23 | right = [ [ "Clock", "Privacy", "Settings" ] ] 24 | ``` 25 | 26 | ### Example 27 | 28 | If we want to add the `SystemInfo` module to the right side of 29 | the status bar but not in the same group as the `Clock`, `Privacy`, 30 | and `Settings` modules, we can do it like this: 31 | 32 | ```toml 33 | right = [ "SystemInfo", [ "Clock", "Privacy", "Settings" ] ] 34 | ``` 35 | 36 | ## Available modules 37 | 38 | The following modules are available: 39 | 40 | ### AppLauncher 41 | 42 | Provides a way to launch applications from the status bar. 43 | 44 | :::info 45 | This module requires additional configuration to work properly. 46 | See the dedicated section in the [documentation](./app_launcher.md). 47 | ::: 48 | 49 | :::warning 50 | This module will be deprecated in future releases. 51 | ::: 52 | 53 | ### Updates 54 | 55 | Provides information about available updates for the system. 56 | 57 | :::info 58 | This module requires additional configuration to work properly. 59 | See the dedicated section in the [documentation](./updates.md). 60 | ::: 61 | 62 | ### Clipboard 63 | 64 | Launches a clipboard manager. 65 | 66 | :::info 67 | This module requires additional configuration to work properly. 68 | See the dedicated section in the [documentation](./clipboard.md). 69 | ::: 70 | 71 | :::warning 72 | This module will be deprecated in future releases. 73 | ::: 74 | 75 | ### Workspaces 76 | 77 | Provides information about the current workspaces and allows switching between them. 78 | 79 | ### WindowTitle 80 | 81 | Displays the title of the currently focused window. 82 | 83 | ### SystemInfo 84 | 85 | Displays system information such as CPU usage, memory usage, and disk space. 86 | 87 | ### KeyboardLayout 88 | 89 | Displays the current keyboard layout and allows switching between layouts. 90 | 91 | ### KeyboardSubmap 92 | 93 | Displays the current keyboard submap. 94 | 95 | ### Tray 96 | 97 | Displays system tray icons and menus for applications. 98 | 99 | ### Clock 100 | 101 | Displays the current time and date. 102 | 103 | ### Privacy 104 | 105 | Provides privacy-related features, such as toggling microphone and camera access. 106 | 107 | ### MediaPlayer 108 | 109 | Displays media player controls and information about the currently playing media. 110 | 111 | ### Settings 112 | 113 | Provides access to system settings like audio, network, Bluetooth, battery, 114 | power profile, and idle inhibitor. 115 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.7.0/configuration/modules/index.md: -------------------------------------------------------------------------------- 1 | # 🧩 Modules 2 | 3 | Ashell modules identify the various features of the status bar. 4 | 5 | Each module provides a set of functionalities that can be enabled 6 | or disabled in the configuration file. 7 | 8 | ## Organize modules 9 | 10 | The status bar is divided into three main sections: left, center, and right. 11 | 12 | Each section holds a list of modules or module groups, 13 | allowing flexible layout configuration. 14 | 15 | Modules can be used on their own or organized into groups. 16 | 17 | ### Default configuration 18 | 19 | ```toml 20 | [modules] 21 | left = [ "Workspaces" ] 22 | center = [ "WindowTitle" ] 23 | right = [ [ "Clock", "Privacy", "Settings" ] ] 24 | ``` 25 | 26 | ### Example 27 | 28 | If we want to add the `SystemInfo` module to the right side of 29 | the status bar but not in the same group as the `Clock`, `Privacy`, 30 | and `Settings` modules, we can do it like this: 31 | 32 | ```toml 33 | right = [ "SystemInfo", [ "Clock", "Privacy", "Settings" ] ] 34 | ``` 35 | 36 | ## Available modules 37 | 38 | The following modules are available: 39 | 40 | ### AppLauncher 41 | 42 | Provides a way to launch applications from the status bar. 43 | 44 | :::info 45 | This module requires additional configuration to work properly. 46 | See the dedicated section in the [documentation](./app_launcher.md). 47 | ::: 48 | 49 | :::warning 50 | This module will be deprecated in future releases. 51 | ::: 52 | 53 | ### Updates 54 | 55 | Provides information about available updates for the system. 56 | 57 | :::info 58 | This module requires additional configuration to work properly. 59 | See the dedicated section in the [documentation](./updates.md). 60 | ::: 61 | 62 | ### Clipboard 63 | 64 | Launches a clipboard manager. 65 | 66 | :::info 67 | This module requires additional configuration to work properly. 68 | See the dedicated section in the [documentation](./clipboard.md). 69 | ::: 70 | 71 | :::warning 72 | This module will be deprecated in future releases. 73 | ::: 74 | 75 | ### Workspaces 76 | 77 | Provides information about the current workspaces and allows switching between them. 78 | 79 | ### WindowTitle 80 | 81 | Displays the title of the currently focused window. 82 | 83 | ### SystemInfo 84 | 85 | Displays system information such as CPU usage, memory usage, and disk space. 86 | 87 | ### KeyboardLayout 88 | 89 | Displays the current keyboard layout and allows switching between layouts. 90 | 91 | ### KeyboardSubmap 92 | 93 | Displays the current keyboard submap. 94 | 95 | ### Tray 96 | 97 | Displays system tray icons and menus for applications. 98 | 99 | ### Clock 100 | 101 | Displays the current time and date. 102 | 103 | ### Privacy 104 | 105 | Provides privacy-related features, such as toggling microphone and camera access. 106 | 107 | ### MediaPlayer 108 | 109 | Displays media player controls and information about the currently playing media. 110 | 111 | ### Settings 112 | 113 | Provides access to system settings like audio, network, Bluetooth, battery, 114 | power profile, and idle inhibitor. 115 | -------------------------------------------------------------------------------- /website/docs/configuration/main.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # 🚪 Main 6 | 7 | This page contains the base configuration options for Ashell. 8 | 9 | It allows you to configure things like the log level, the monitor(s) used to 10 | render the status bar, and the bar’s position. 11 | 12 | All these configurations are defined in the root of the `toml` file. 13 | 14 | ## Log Level 15 | 16 | The log level controls the verbosity of logs. 17 | 18 | You can set it to a general level like `debug`, `info`, `warn`, or `error`, 19 | or specify fine-grained control to enable logs from specific modules 20 | in the codebase, e.g., `ashell::services::network=debug`. 21 | 22 | See more about [log levels](https://docs.rs/env_logger/latest/env_logger/#enabling-logging). 23 | 24 | :::warning 25 | 26 | This configuration **requires** restarting Ashell to take effect. 27 | 28 | ::: 29 | 30 | ### Log Examples 31 | 32 | Set the global log level to `debug` for all modules: 33 | 34 | ```toml 35 | log_level = "debug" 36 | ``` 37 | 38 | Set the log level for the `ashell` module only: 39 | 40 | ```toml 41 | log_level = "ashell=debug" 42 | ``` 43 | 44 | Set the log level to `warn` for all modules, `info` for Ashell modules, 45 | and `debug` only for the network service: 46 | 47 | ```toml 48 | log_level = "warn,ashell=info,ashell::services::network=debug" 49 | ``` 50 | 51 | To understand all possible module names you can use, check 52 | the [source code](https://github.com/MalpenZibo/ashell). 53 | The `src` folder is the root of the `ashell` module, and every directory 54 | or file under it declares a module or submodule. 55 | 56 | For example, the file `src/modules/media_player.rs` maps to the module `ashell::modules::media_player`. 57 | 58 | :::warning 59 | 60 | Don’t confuse Ashell features (called “modules”) with Rust modules 61 | (defined with `mod.rs` or in files). 62 | In this configuration, we're referring to Rust modules. 63 | 64 | ::: 65 | 66 | ## Outputs 67 | 68 | You can configure which monitor(s) should display the status bar. 69 | 70 | It can render on all monitors, only on the active one 71 | (the focused monitor when Ashell starts), or on a list of specified monitors. 72 | 73 | ### Output Examples 74 | 75 | Render the status bar on all monitors: 76 | 77 | ```toml 78 | outputs = "All" 79 | ``` 80 | 81 | Render the status bar on the active monitor: 82 | 83 | ```toml 84 | outputs = "Active" 85 | ``` 86 | 87 | Render the status bar on a specific list of monitors: 88 | 89 | ```toml 90 | outputs = { Targets = ["DP-1", "eDP-1"] } 91 | ``` 92 | 93 | ## Position 94 | 95 | You can set the position of the status bar to either `Top` or `Bottom`. 96 | 97 | ### Position Examples 98 | 99 | Set the bar position to the top: 100 | 101 | ```toml 102 | position = "Top" 103 | ``` 104 | 105 | Set the bar position to the bottom: 106 | 107 | ```toml 108 | position = "Bottom" 109 | ``` 110 | 111 | ## Close menu with esc 112 | 113 | You can enable the use of the `Esc` key to close the menu. 114 | 115 | :::warning 116 | 117 | With these features enabled ashell will use the keyboard 118 | in an exclusive way when a menu is open. 119 | 120 | That means other applications will not be able to use 121 | the keyboard when the menu is open. 122 | 123 | ::: 124 | 125 | ```toml 126 | enable_esc_key = true 127 | ``` 128 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.6.0/configuration/main.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # 🚪 Main 6 | 7 | This page contains the base configuration options for Ashell. 8 | 9 | It allows you to configure things like the log level, the monitor(s) used to 10 | render the status bar, and the bar’s position. 11 | 12 | All these configurations are defined in the root of the `toml` file. 13 | 14 | ## Log Level 15 | 16 | The log level controls the verbosity of logs. 17 | 18 | You can set it to a general level like `debug`, `info`, `warn`, or `error`, 19 | or specify fine-grained control to enable logs from specific modules 20 | in the codebase, e.g., `ashell::services::network=debug`. 21 | 22 | See more about [log levels](https://docs.rs/env_logger/latest/env_logger/#enabling-logging). 23 | 24 | :::warning 25 | 26 | This configuration **requires** restarting Ashell to take effect. 27 | 28 | ::: 29 | 30 | ### Log Examples 31 | 32 | Set the global log level to `debug` for all modules: 33 | 34 | ```toml 35 | log_level = "debug" 36 | ``` 37 | 38 | Set the log level for the `ashell` module only: 39 | 40 | ```toml 41 | log_level = "ashell=debug" 42 | ``` 43 | 44 | Set the log level to `warn` for all modules, `info` for Ashell modules, 45 | and `debug` only for the network service: 46 | 47 | ```toml 48 | log_level = "warn,ashell=info,ashell::services::network=debug" 49 | ``` 50 | 51 | To understand all possible module names you can use, check 52 | the [source code](https://github.com/MalpenZibo/ashell). 53 | The `src` folder is the root of the `ashell` module, and every directory 54 | or file under it declares a module or submodule. 55 | 56 | For example, the file `src/modules/media_player.rs` maps to the module `ashell::modules::media_player`. 57 | 58 | :::warning 59 | 60 | Don’t confuse Ashell features (called “modules”) with Rust modules 61 | (defined with `mod.rs` or in files). 62 | In this configuration, we're referring to Rust modules. 63 | 64 | ::: 65 | 66 | ## Outputs 67 | 68 | You can configure which monitor(s) should display the status bar. 69 | 70 | It can render on all monitors, only on the active one 71 | (the focused monitor when Ashell starts), or on a list of specified monitors. 72 | 73 | ### Output Examples 74 | 75 | Render the status bar on all monitors: 76 | 77 | ```toml 78 | outputs = "All" 79 | ``` 80 | 81 | Render the status bar on the active monitor: 82 | 83 | ```toml 84 | outputs = "Active" 85 | ``` 86 | 87 | Render the status bar on a specific list of monitors: 88 | 89 | ```toml 90 | outputs = { Targets = ["DP-1", "eDP-1"] } 91 | ``` 92 | 93 | ## Position 94 | 95 | You can set the position of the status bar to either `Top` or `Bottom`. 96 | 97 | ### Position Examples 98 | 99 | Set the bar position to the top: 100 | 101 | ```toml 102 | position = "Top" 103 | ``` 104 | 105 | Set the bar position to the bottom: 106 | 107 | ```toml 108 | position = "Bottom" 109 | ``` 110 | 111 | ## Close menu with esc 112 | 113 | You can enable the use of the `Esc` key to close the menu. 114 | 115 | :::warning 116 | 117 | With these features enabled ashell will use the keyboard 118 | in an exclusive way when a menu is open. 119 | 120 | That means other applications will not be able to use 121 | the keyboard when the menu is open. 122 | 123 | ::: 124 | 125 | ```toml 126 | enable_esc_key = true 127 | ``` 128 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.7.0/configuration/main.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # 🚪 Main 6 | 7 | This page contains the base configuration options for Ashell. 8 | 9 | It allows you to configure things like the log level, the monitor(s) used to 10 | render the status bar, and the bar’s position. 11 | 12 | All these configurations are defined in the root of the `toml` file. 13 | 14 | ## Log Level 15 | 16 | The log level controls the verbosity of logs. 17 | 18 | You can set it to a general level like `debug`, `info`, `warn`, or `error`, 19 | or specify fine-grained control to enable logs from specific modules 20 | in the codebase, e.g., `ashell::services::network=debug`. 21 | 22 | See more about [log levels](https://docs.rs/env_logger/latest/env_logger/#enabling-logging). 23 | 24 | :::warning 25 | 26 | This configuration **requires** restarting Ashell to take effect. 27 | 28 | ::: 29 | 30 | ### Log Examples 31 | 32 | Set the global log level to `debug` for all modules: 33 | 34 | ```toml 35 | log_level = "debug" 36 | ``` 37 | 38 | Set the log level for the `ashell` module only: 39 | 40 | ```toml 41 | log_level = "ashell=debug" 42 | ``` 43 | 44 | Set the log level to `warn` for all modules, `info` for Ashell modules, 45 | and `debug` only for the network service: 46 | 47 | ```toml 48 | log_level = "warn,ashell=info,ashell::services::network=debug" 49 | ``` 50 | 51 | To understand all possible module names you can use, check 52 | the [source code](https://github.com/MalpenZibo/ashell). 53 | The `src` folder is the root of the `ashell` module, and every directory 54 | or file under it declares a module or submodule. 55 | 56 | For example, the file `src/modules/media_player.rs` maps to the module `ashell::modules::media_player`. 57 | 58 | :::warning 59 | 60 | Don’t confuse Ashell features (called “modules”) with Rust modules 61 | (defined with `mod.rs` or in files). 62 | In this configuration, we're referring to Rust modules. 63 | 64 | ::: 65 | 66 | ## Outputs 67 | 68 | You can configure which monitor(s) should display the status bar. 69 | 70 | It can render on all monitors, only on the active one 71 | (the focused monitor when Ashell starts), or on a list of specified monitors. 72 | 73 | ### Output Examples 74 | 75 | Render the status bar on all monitors: 76 | 77 | ```toml 78 | outputs = "All" 79 | ``` 80 | 81 | Render the status bar on the active monitor: 82 | 83 | ```toml 84 | outputs = "Active" 85 | ``` 86 | 87 | Render the status bar on a specific list of monitors: 88 | 89 | ```toml 90 | outputs = { Targets = ["DP-1", "eDP-1"] } 91 | ``` 92 | 93 | ## Position 94 | 95 | You can set the position of the status bar to either `Top` or `Bottom`. 96 | 97 | ### Position Examples 98 | 99 | Set the bar position to the top: 100 | 101 | ```toml 102 | position = "Top" 103 | ``` 104 | 105 | Set the bar position to the bottom: 106 | 107 | ```toml 108 | position = "Bottom" 109 | ``` 110 | 111 | ## Close menu with esc 112 | 113 | You can enable the use of the `Esc` key to close the menu. 114 | 115 | :::warning 116 | 117 | With these features enabled ashell will use the keyboard 118 | in an exclusive way when a menu is open. 119 | 120 | That means other applications will not be able to use 121 | the keyboard when the menu is open. 122 | 123 | ::: 124 | 125 | ```toml 126 | enable_esc_key = true 127 | ``` 128 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use crate::config::get_config; 2 | use app::App; 3 | use clap::Parser; 4 | use flexi_logger::{ 5 | Age, Cleanup, Criterion, FileSpec, LogSpecBuilder, LogSpecification, Logger, Naming, 6 | }; 7 | use iced::Font; 8 | use log::{debug, error, warn}; 9 | use std::panic; 10 | use std::path::PathBuf; 11 | use std::{backtrace::Backtrace, borrow::Cow}; 12 | 13 | mod app; 14 | mod centerbox; 15 | mod components; 16 | mod config; 17 | mod menu; 18 | mod modules; 19 | mod outputs; 20 | mod password_dialog; 21 | mod position_button; 22 | mod services; 23 | mod theme; 24 | mod utils; 25 | 26 | const NERD_FONT: &[u8] = include_bytes!("../target/generated/SymbolsNerdFont-Regular-Subset.ttf"); 27 | const NERD_FONT_MONO: &[u8] = 28 | include_bytes!("../target/generated/SymbolsNerdFontMono-Regular-Subset.ttf"); 29 | const CUSTOM_FONT: &[u8] = include_bytes!("../assets/AshellCustomIcon-Regular.otf"); 30 | const HEIGHT: f64 = 34.; 31 | 32 | #[derive(Parser, Debug)] 33 | #[command(version, about, long_about = None)] 34 | struct Args { 35 | #[arg(short, long, value_parser = clap::value_parser!(PathBuf))] 36 | config_path: Option, 37 | } 38 | 39 | fn get_log_spec(log_level: &str) -> LogSpecification { 40 | let new_spec = LogSpecification::env_or_parse(log_level); 41 | 42 | match new_spec { 43 | Ok(spec) => spec, 44 | Err(err) => { 45 | warn!("Failed to parse log level: {err}, use the default"); 46 | 47 | LogSpecification::default() 48 | } 49 | } 50 | } 51 | 52 | #[tokio::main] 53 | async fn main() -> iced::Result { 54 | let args = Args::parse(); 55 | debug!("args: {args:?}"); 56 | 57 | let logger = Logger::with( 58 | LogSpecBuilder::new() 59 | .default(log::LevelFilter::Info) 60 | .build(), 61 | ) 62 | .log_to_file(FileSpec::default().directory("/tmp/ashell")) 63 | .duplicate_to_stdout(flexi_logger::Duplicate::All) 64 | .rotate( 65 | Criterion::Age(Age::Day), 66 | Naming::Timestamps, 67 | Cleanup::KeepLogFiles(7), 68 | ); 69 | let logger = if cfg!(debug_assertions) { 70 | logger.duplicate_to_stdout(flexi_logger::Duplicate::All) 71 | } else { 72 | logger 73 | }; 74 | let logger = logger.start().unwrap(); 75 | panic::set_hook(Box::new(|info| { 76 | let b = Backtrace::capture(); 77 | error!("Panic: {info} \n {b}"); 78 | })); 79 | 80 | let (config, config_path) = get_config(args.config_path).unwrap_or_else(|err| { 81 | error!("Failed to read config: {err}"); 82 | 83 | std::process::exit(1); 84 | }); 85 | 86 | logger.set_new_spec(get_log_spec(&config.log_level)); 87 | 88 | let font = match config.appearance.font_name { 89 | Some(ref font_name) => Font::with_name(Box::leak(font_name.clone().into_boxed_str())), 90 | None => Font::DEFAULT, 91 | }; 92 | 93 | iced::daemon(App::title, App::update, App::view) 94 | .subscription(App::subscription) 95 | .theme(App::theme) 96 | .style(App::style) 97 | .scale_factor(App::scale_factor) 98 | .font(Cow::from(NERD_FONT)) 99 | .font(Cow::from(NERD_FONT_MONO)) 100 | .font(Cow::from(CUSTOM_FONT)) 101 | .default_font(font) 102 | .run_with(App::new((logger, config, config_path))) 103 | } 104 | -------------------------------------------------------------------------------- /.github/workflows/generate-installers.yml: -------------------------------------------------------------------------------- 1 | name: "Generate Installers" 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | # These are passed automatically by cargo-dist 7 | plan: 8 | required: true 9 | type: string 10 | 11 | permissions: 12 | contents: write 13 | 14 | jobs: 15 | generate-installers: 16 | name: "Generate packages" 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | - uses: actions/checkout@v4 21 | 22 | - name: Parse plan manifest 23 | id: manifest 24 | env: 25 | PLAN: ${{ inputs.plan }} 26 | run: | 27 | echo "$PLAN" > plan.json 28 | 29 | # Extract artifact filenames and unique target triples 30 | targets=$(jq -r '[.releases[].artifacts[] as $a | .artifacts[$a].target_triples[]] | unique | join(",")' plan.json) 31 | echo "targets=$targets" >> "$GITHUB_OUTPUT" 32 | 33 | - name: Download built tarballs 34 | uses: actions/download-artifact@v4 35 | with: 36 | pattern: artifacts-build-local-* # matches all uploaded tarballs 37 | path: target/distrib 38 | 39 | - name: Install Rust 40 | uses: dtolnay/rust-toolchain@stable 41 | with: 42 | targets: ${{ steps.manifest.outputs.targets }} 43 | 44 | - name: Install cargo-nfpm 45 | run: cargo install cargo-nfpm --locked 46 | 47 | - name: Build .deb and .rpm packages 48 | run: | 49 | mkdir artifacts 50 | 51 | # For each artifact filename listed in the plan 52 | for archive in $(jq -r '.releases[].artifacts[] | select(endswith(".tar.xz"))' plan.json); do 53 | # get the target triple for that artifact (first element) 54 | target_triple=$(jq -r --arg a "$archive" '.artifacts[$a].target_triples[0]' plan.json) 55 | 56 | # get the app_name for the release that contains this artifact 57 | # (select the release whose artifacts array contains the archive) 58 | app_name=$(jq -r --arg a "$archive" '.releases[] | select(.artifacts[] == $a) | .app_name' plan.json) 59 | 60 | echo "Processing archive=$archive target=$target_triple app=$app_name" 61 | 62 | # dest directory like target/x86_64-unknown-linux-gnu/release 63 | dest_dir="target/${target_triple}/release" 64 | mkdir -p "$dest_dir" 65 | 66 | # extract into dest (strip top-level folder if present) 67 | tar -xf "target/distrib/artifacts-build-local-$target_triple/$archive" -C "$dest_dir" --strip-components=1 68 | 69 | # Confirm the binary is where expected (optional debug) 70 | echo "Contents of $dest_dir:" 71 | ls -la "$dest_dir" || true 72 | 73 | # Run cargo-nfpm for this target triple (no-build because we have binaries) 74 | cargo nfpm package --format deb --no-build --target "$target_triple" --output "artifacts/$app_name-$target_triple.deb" || { 75 | echo "cargo-nfpm deb failed for $target_triple" 76 | exit 1 77 | } 78 | cargo nfpm package --format rpm --no-build --target "$target_triple" --output "artifacts/$app_name-$target_triple.rpm"|| { 79 | echo "cargo-nfpm rpm failed for $target_triple" 80 | exit 1 81 | } 82 | 83 | done 84 | 85 | - name: Upload generated installers 86 | uses: actions/upload-artifact@v4 87 | with: 88 | name: artifacts-installers 89 | path: artifacts 90 | -------------------------------------------------------------------------------- /website/versioned_docs/version-0.6.0/configuration/modules/system_info.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 6 3 | --- 4 | 5 | # System Info 6 | 7 | This module provides information about the system such as: 8 | 9 | - CPU usage 10 | - Memory usage 11 | - Disk space 12 | - Network IP 13 | - Network speed 14 | - Temperature 15 | 16 | It changes the indicator color based on the related value. 17 | For example, if the CPU usage is above 80%, the indicator will be red. 18 | 19 | By default, the module will display the CPU usage, memory usage, and temperature. 20 | 21 | ## Indicators 22 | 23 | Using the `indicators` configuration, you can select which indicators 24 | to display in the status bar. 25 | 26 | These are the available indicators: 27 | 28 | ### CPU 29 | 30 | The CPU indicator displays the current CPU usage as a percentage. 31 | 32 | To enable this indicator, add `Cpu` to the `indicators` configuration. 33 | 34 | ### Memory 35 | 36 | The Memory indicator displays the current memory usage as a percentage. 37 | 38 | To enable this indicator, add `Memory` to the `indicators` configuration. 39 | 40 | ### Memory Swap 41 | 42 | The Memory Swap indicator displays the current memory swap usage as a percentage. 43 | 44 | To enable this indicator, add `MemorySwap` to the `indicators` configuration. 45 | 46 | ### Disk 47 | 48 | The Disk indicator displays the disk space usage for a specific path. 49 | 50 | To enable this indicator, add `{ Disk = "path" }` to the `indicators` configuration, 51 | where `path` is the path to the disk you want to monitor. 52 | 53 | #### Example 54 | 55 | To monitor the home directory disk space, you can add the following to your configuration: 56 | 57 | ```toml 58 | [system_info] 59 | indicators = [ { Disk = "/home" } ] 60 | ``` 61 | 62 | ### IpAddress 63 | 64 | The IpAddress indicator displays the current IP address of the system. 65 | 66 | To enable this indicator, add `IpAddress` to the `indicators` configuration. 67 | 68 | ### DownloadSpeed 69 | 70 | The DownloadSpeed indicator displays the current download speed 71 | of the system's network connection. 72 | 73 | To enable this indicator, add `DownloadSpeed` to the `indicators` configuration. 74 | 75 | ### UploadSpeed 76 | 77 | The UploadSpeed indicator displays the current upload speed 78 | of the system's network connection. 79 | 80 | To enable this indicator, add `UploadSpeed` to the `indicators` configuration. 81 | 82 | ### Temperature 83 | 84 | The Temperature indicator displays the current temperature of the system's CPU. 85 | 86 | To enable this indicator, add `Temperature` to the `indicators` configuration. 87 | 88 | ## Warning and Alert Thresholds 89 | 90 | You can also configure the warning and alert thresholds for the following indicators: 91 | 92 | - CPU 93 | - Memory (RAM and Swap use the same thresholds) 94 | - Disk 95 | - Temperature 96 | 97 | To configure a threshold, you can add the following to your configuration: 98 | 99 | ```toml 100 | [system_info.threshold_type] 101 | warn_threshold = 60 102 | alert_threshold = 80 103 | ``` 104 | 105 | Where **threshold_type** is the type of indicator you want to 106 | configure and can be one of: 107 | 108 | - `cpu` 109 | - `memory` 110 | - `disk` 111 | - `temperature` 112 | 113 | ## Default Configuration 114 | 115 | ```toml 116 | [system_info] 117 | indicators = [ "Cpu", "Memory", "Temperature" ] 118 | 119 | [system_info.cpu] 120 | warn_threshold = 60 121 | alert_threshold = 80 122 | 123 | [system_info.memory] 124 | warn_threshold = 70 125 | alert_threshold = 85 126 | 127 | [system_info.disk] 128 | warn_threshold = 80 129 | alert_threshold = 90 130 | 131 | [system_info.temperature] 132 | warn_threshold = 60 133 | alert_threshold = 80 134 | ``` 135 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | ashell 4 | 5 |
6 | 7 | ## What is ashell? 8 | 9 | ashell is a ready to go Wayland status bar for Hyprland and Niri. 10 | 11 | Feel free to fork this project and customize it for your needs or just open an 12 | issue to request a particular feature. 13 | 14 | ## 🚀 Getting Started 15 | 16 | Refer to the [Getting Started](https://malpenzibo.github.io/ashell/docs/intro) 17 | page on website 18 | 19 | ## ✨ Features 20 | 21 | - App Launcher button 22 | - Сlipboard button 23 | - OS Updates indicator 24 | - Hyprland/Niri Active Window 25 | - Hyprland/Niri Workspaces 26 | - System Information (CPU, RAM, Temperature) 27 | - Hyprland/Niri Keyboard Layout 28 | - Hyprland Keyboard Submap 29 | - Tray 30 | - Date time 31 | - Privacy (check microphone, camera and screenshare usage) 32 | - Media Player 33 | - Settings panel 34 | - Power menu 35 | - Battery information 36 | - Audio sources and sinks 37 | - Screen brightness 38 | - Network stuff 39 | - VPN 40 | - Bluetooth 41 | - Power profiles 42 | - Idle inhibitor 43 | - Airplane mode 44 | - Custom Modules 45 | - Simple (execute command on click) 46 | - Advanced (update UI with command output) 47 | 48 | ## 🛠️ Install 49 | 50 | [![Packaging status](https://repology.org/badge/vertical-allrepos/ashell.svg)](https://repology.org/project/ashell/versions) 51 | 52 | Refer to the [Installation](https://malpenzibo.github.io/ashell/docs/installation) 53 | page for more details. 54 | 55 | ## ⚙️ Configuration 56 | 57 | ashell comes with a default configuration that should work out of the box. 58 | 59 | If you want to customize it you can refer to 60 | the [Configuration](https://malpenzibo.github.io/ashell/docs/configuration) 61 | page for more details. 62 | 63 | ## 📷 Screenshots 64 | 65 | I will try my best to keep these screenshots as updated as possible but some details 66 | could be different 67 | 68 | #### default style 69 | 70 | 71 | 72 | #### solid style 73 | 74 | 75 | 76 | #### gradient style 77 | 78 | 79 | 80 | #### opacity settings 81 | 82 | 83 | 84 | | ![](https://raw.githubusercontent.com/MalpenZibo/ashell/main/website/static/img/gallery/updates-panel.png) | ![](https://raw.githubusercontent.com/MalpenZibo/ashell/main/website/static/img/gallery/system-menu.png) | 85 | | ------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------- | 86 | | ![](https://raw.githubusercontent.com/MalpenZibo/ashell/main/website/static/img/gallery/tray-menu.png) | ![](https://raw.githubusercontent.com/MalpenZibo/ashell/main/website/static/img/gallery/power-menu.png) | 87 | | ![](https://raw.githubusercontent.com/MalpenZibo/ashell/main/website/static/img/gallery/sinks-selection.png) | ![](https://raw.githubusercontent.com/MalpenZibo/ashell/main/website/static/img/gallery/network-menu.png) | 88 | | ![](https://raw.githubusercontent.com/MalpenZibo/ashell/main/website/static/img/gallery/bluetooth-menu.png) | ![](https://raw.githubusercontent.com/MalpenZibo/ashell/main/website/static/img/gallery/vpn-menu.png) | 89 | -------------------------------------------------------------------------------- /website/static/img/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 60 | -------------------------------------------------------------------------------- /website/static/img/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 60 | -------------------------------------------------------------------------------- /website/static/img/rocket.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | --------------------------------------------------------------------------------