feat: Add h/l nav controls (#53)

This commit is contained in:
Valyn Tyler
2025-07-11 15:42:30 +03:00
committed by GitHub
parent 688165c2bc
commit a4b5419b02
7 changed files with 197 additions and 80 deletions

1
.envrc Normal file
View File

@@ -0,0 +1 @@
use flake

1
.gitignore vendored
View File

@@ -1 +1,2 @@
/target /target
.direnv/

71
Cargo.lock generated
View File

@@ -90,9 +90,9 @@ checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
[[package]] [[package]]
name = "async-channel" name = "async-channel"
version = "2.3.1" version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2"
dependencies = [ dependencies = [
"concurrent-queue", "concurrent-queue",
"event-listener-strategy", "event-listener-strategy",
@@ -266,9 +266,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.5.40" version = "4.5.41"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
"clap_derive", "clap_derive",
@@ -276,9 +276,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_builder" name = "clap_builder"
version = "4.5.40" version = "4.5.41"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e" checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d"
dependencies = [ dependencies = [
"anstream", "anstream",
"anstyle", "anstyle",
@@ -288,9 +288,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_derive" name = "clap_derive"
version = "4.5.40" version = "4.5.41"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce" checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491"
dependencies = [ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
@@ -874,9 +874,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.9.0" version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661"
dependencies = [ dependencies = [
"equivalent", "equivalent",
"hashbrown", "hashbrown",
@@ -901,6 +901,17 @@ dependencies = [
"syn 2.0.104", "syn 2.0.104",
] ]
[[package]]
name = "io-uring"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013"
dependencies = [
"bitflags 2.9.1",
"cfg-if",
"libc",
]
[[package]] [[package]]
name = "is_terminal_polyfill" name = "is_terminal_polyfill"
version = "1.70.1" version = "1.70.1"
@@ -943,9 +954,9 @@ dependencies = [
[[package]] [[package]]
name = "kasuari" name = "kasuari"
version = "0.4.6" version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "def1b67294a9fdc95eeeeafd1209c7a1b8a82aa0bf80ac2ab2a7d0318e9c7622" checksum = "96d9e0d6a8bf886abccc1cbcac7d74f9000ae5882aedc4a9042188bbc9cd4487"
dependencies = [ dependencies = [
"hashbrown", "hashbrown",
"thiserror 2.0.12", "thiserror 2.0.12",
@@ -980,9 +991,9 @@ dependencies = [
[[package]] [[package]]
name = "libredox" name = "libredox"
version = "0.1.3" version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638"
dependencies = [ dependencies = [
"bitflags 2.9.1", "bitflags 2.9.1",
"libc", "libc",
@@ -1444,9 +1455,9 @@ dependencies = [
[[package]] [[package]]
name = "ratatui" name = "ratatui"
version = "0.30.0-alpha.4" version = "0.30.0-alpha.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63bfff7501cc6892821f54f1133661e0534413342c8e8efbb41af0ffccdcea45" checksum = "71365e96fb8f1350c02908e788815c5a57c0c1f557673b274a94edee7a4fe001"
dependencies = [ dependencies = [
"instability", "instability",
"ratatui-core", "ratatui-core",
@@ -1458,9 +1469,9 @@ dependencies = [
[[package]] [[package]]
name = "ratatui-core" name = "ratatui-core"
version = "0.1.0-alpha.5" version = "0.1.0-alpha.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "353047185fbfb81ee05a3f8c573956adb2aa9a505da47fb150c18388806f5e22" checksum = "f836b2eac888da74162b680a8facdbe784ae73df3b0f711eef74bb90a7477f78"
dependencies = [ dependencies = [
"bitflags 2.9.1", "bitflags 2.9.1",
"compact_str 0.9.0", "compact_str 0.9.0",
@@ -1478,9 +1489,9 @@ dependencies = [
[[package]] [[package]]
name = "ratatui-crossterm" name = "ratatui-crossterm"
version = "0.1.0-alpha.4" version = "0.1.0-alpha.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c729303ad253dd928b75f5866feb41c73d0e72b62ec91b13a5d91141ff5bfd1" checksum = "22f4a90548bf8ed759d226d621d73561110db23aee7b7dc4e12c39ac7132062f"
dependencies = [ dependencies = [
"crossterm 0.29.0", "crossterm 0.29.0",
"instability", "instability",
@@ -1489,9 +1500,9 @@ dependencies = [
[[package]] [[package]]
name = "ratatui-macros" name = "ratatui-macros"
version = "0.7.0-alpha.3" version = "0.7.0-alpha.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "058564a94bc18220b5c37caf05ec334e362bc87711522703fbed1ec9c43a0eae" checksum = "1f4c660248a5a9edf95698cf33dc36a82ae48a918594480cdada340d81584e0b"
dependencies = [ dependencies = [
"ratatui-core", "ratatui-core",
"ratatui-widgets", "ratatui-widgets",
@@ -1499,9 +1510,9 @@ dependencies = [
[[package]] [[package]]
name = "ratatui-termwiz" name = "ratatui-termwiz"
version = "0.1.0-alpha.4" version = "0.1.0-alpha.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca620dea5f1b7e949fc60a7d78626946dc0273707d28eed4ce3ee458ae0218ca" checksum = "4cbb5d7645e56f06ead2a49a72b9cc05022f0b215ec7cdf39d37ed94e9a73d69"
dependencies = [ dependencies = [
"ratatui-core", "ratatui-core",
"termwiz", "termwiz",
@@ -1509,9 +1520,9 @@ dependencies = [
[[package]] [[package]]
name = "ratatui-widgets" name = "ratatui-widgets"
version = "0.3.0-alpha.4" version = "0.3.0-alpha.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fab55e77e0421bb88944cc0262317688e039d0e58518195f13a6e689f3e22f42" checksum = "388428527811be6da3e23157d951308d9eae4ce1b4d1d545a55673bbcdfb7326"
dependencies = [ dependencies = [
"bitflags 2.9.1", "bitflags 2.9.1",
"hashbrown", "hashbrown",
@@ -1962,17 +1973,19 @@ checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c"
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.45.1" version = "1.46.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17"
dependencies = [ dependencies = [
"backtrace", "backtrace",
"bytes", "bytes",
"io-uring",
"libc", "libc",
"mio", "mio",
"parking_lot", "parking_lot",
"pin-project-lite", "pin-project-lite",
"signal-hook-registry", "signal-hook-registry",
"slab",
"socket2", "socket2",
"tokio-macros", "tokio-macros",
"windows-sys 0.52.0", "windows-sys 0.52.0",
@@ -2047,7 +2060,7 @@ version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dce25d24adf2c5350c57426f25cf12bc767455a6d9202be155458fc768ea1268" checksum = "dce25d24adf2c5350c57426f25cf12bc767455a6d9202be155458fc768ea1268"
dependencies = [ dependencies = [
"ratatui 0.30.0-alpha.4", "ratatui 0.30.0-alpha.5",
"unicode-width 0.2.0", "unicode-width 0.2.0",
] ]

65
flake.lock generated
View File

@@ -1,24 +1,79 @@
{ {
"nodes": { "nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1742268799, "lastModified": 1751984180,
"narHash": "sha256-IhnK4LhkBlf14/F8THvUy3xi/TxSQkp9hikfDZRD4Ic=", "narHash": "sha256-LwWRsENAZJKUdD3SpLluwDmdXY9F45ZEgCb0X+xgOL0=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "da044451c6a70518db5b730fe277b70f494188f1", "rev": "9807714d6944a957c2e036f84b0ff8caf9930bc0",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nixos", "owner": "nixos",
"ref": "nixos-24.11", "ref": "nixos-unstable",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }
}, },
"root": { "root": {
"inputs": { "inputs": {
"nixpkgs": "nixpkgs" "flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"rust-overlay": "rust-overlay"
}
},
"rust-overlay": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1752115281,
"narHash": "sha256-3i0sUli3sWCglfpj+yS1gtA+4m2ao2UMIxa4IfifUUU=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "e5b68250e585c60d1679803045575fb71801d822",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
} }
} }
}, },

View File

@@ -1,18 +1,55 @@
{ {
inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11"; inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
outputs = flake-utils.url = "github:numtide/flake-utils";
{ self, nixpkgs }: rust-overlay = {
{ url = "github:oxalica/rust-overlay";
packages = inputs.nixpkgs.follows = "nixpkgs";
nixpkgs.lib.genAttrs
[
"x86_64-linux"
"aarch64-linux"
]
(system: rec {
bluetui = nixpkgs.legacyPackages.${system}.callPackage ./package.nix { };
default = bluetui;
});
}; };
};
outputs = {
self,
nixpkgs,
flake-utils,
rust-overlay,
...
}:
flake-utils.lib.eachDefaultSystem (
system: let
overlays = [(import rust-overlay)];
pkgs = import nixpkgs {inherit system overlays;};
in {
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [
dbus
pkg-config
rust-bin.stable.latest.default
self.packages.${system}.default
];
};
packages = rec {
default = bluetui;
bluetui = let
cargo = (pkgs.lib.importTOML ./Cargo.toml).package;
in
pkgs.rustPlatform.buildRustPackage {
pname = cargo.name;
version = cargo.version;
src = ./.;
cargoLock.lockFile = ./Cargo.lock;
buildInputs = with pkgs; [dbus];
nativeBuildInputs = with pkgs; [pkg-config];
meta = {
description = cargo.description;
homepage = cargo.homepage;
license = pkgs.lib.licenses.gpl3Only;
maintainers = with pkgs.lib.maintainers; [samuel-martineau];
};
};
};
}
);
} }

View File

@@ -1,31 +0,0 @@
{
lib,
rustPlatform,
pkg-config,
dbus,
}:
let
cargo = (lib.importTOML ./Cargo.toml).package;
in
rustPlatform.buildRustPackage {
pname = cargo.name;
version = cargo.version;
src = ./.;
cargoLock = {
lockFile = ./Cargo.lock;
};
nativeBuildInputs = [ pkg-config ];
buildInputs = [ dbus ];
meta = {
description = cargo.description;
homepage = cargo.homepage;
license = lib.licenses.gpl3Only;
maintainers = with lib.maintainers; [ samuel-martineau ];
};
}

View File

@@ -120,6 +120,47 @@ pub async fn handle_key_events(
_ => {} _ => {}
}, },
KeyCode::Char('h') => match app.focused_block {
FocusedBlock::Adapter => {
if let Some(selected_controller) = app.controller_state.selected() {
let controller = &app.controllers[selected_controller];
if controller.new_devices.is_empty() {
app.focused_block = FocusedBlock::PairedDevices;
} else {
app.focused_block = FocusedBlock::NewDevices;
}
}
}
FocusedBlock::PairedDevices => {
app.focused_block = FocusedBlock::Adapter;
}
FocusedBlock::NewDevices => {
app.focused_block = FocusedBlock::PairedDevices;
app.reset_devices_state();
}
_ => {}
},
KeyCode::Char('l') => match app.focused_block {
FocusedBlock::Adapter => {
app.focused_block = FocusedBlock::PairedDevices;
app.reset_devices_state();
}
FocusedBlock::PairedDevices => {
if let Some(selected_controller) = app.controller_state.selected() {
let controller = &app.controllers[selected_controller];
if controller.new_devices.is_empty() {
app.focused_block = FocusedBlock::Adapter;
} else {
app.focused_block = FocusedBlock::NewDevices;
}
}
}
FocusedBlock::NewDevices => app.focused_block = FocusedBlock::Adapter,
_ => {}
},
// scroll down // scroll down
KeyCode::Char('j') | KeyCode::Down => match app.focused_block { KeyCode::Char('j') | KeyCode::Down => match app.focused_block {
FocusedBlock::Adapter => { FocusedBlock::Adapter => {