Compare commits
2 Commits
9bd023ce2c
...
67085827b5
| Author | SHA1 | Date | |
|---|---|---|---|
| 67085827b5 | |||
| 1c32b40669 |
@ -1 +1,4 @@
|
||||
vim.opt_local.shiftwidth = 2
|
||||
vim.opt_local.expandtab = true
|
||||
vim.opt_local.softtabstop = 2
|
||||
vim.opt_local.tabstop = 2
|
||||
|
||||
@ -20,23 +20,23 @@
|
||||
"mason-lspconfig.nvim": { "branch": "main", "commit": "21c5b3ebeaa0412e28096bb0701434c51c1fbf76" },
|
||||
"mason-tool-installer.nvim": { "branch": "main", "commit": "443f1ef8b5e6bf47045cb2217b6f748a223cf7dc" },
|
||||
"mason.nvim": { "branch": "main", "commit": "2a6940af80375532e5e9e7c1f2fc6319a1b7a69d" },
|
||||
"mini.nvim": { "branch": "main", "commit": "a59a9b7fb0a42cbcf022938ee5f0724320b66f63" },
|
||||
"mini.nvim": { "branch": "main", "commit": "1345d191bb3da9c7b0e977f4387c5761f9bff68d" },
|
||||
"monokai-nightasty.nvim": { "branch": "main", "commit": "1e9b92006782a1217d0a7a871b871768f1cbf5ed" },
|
||||
"none-ls-extras.nvim": { "branch": "main", "commit": "27681d797a26f1b4d6119296df42f5204c88a2dc" },
|
||||
"none-ls.nvim": { "branch": "main", "commit": "01f8e62ea11603e59ad9ff7afcfa94fd183f76d6" },
|
||||
"nvim-autopairs": { "branch": "master", "commit": "7b9923abad60b903ece7c52940e1321d39eccc79" },
|
||||
"nvim-cmp": { "branch": "main", "commit": "a1d504892f2bc56c2e79b65c6faded2fd21f3eca" },
|
||||
"nvim-lsp-file-operations": { "branch": "master", "commit": "b9c795d3973e8eec22706af14959bc60c579e771" },
|
||||
"nvim-lspconfig": { "branch": "master", "commit": "a683e0ddf0cf64c6cd689e18ffb480ade3c162b7" },
|
||||
"nvim-lspconfig": { "branch": "master", "commit": "bfcc0171a43f22afa61d927ffe9fcb6cb85dc99e" },
|
||||
"nvim-surround": { "branch": "main", "commit": "2e93e154de9ff326def6480a4358bfc149d5da2c" },
|
||||
"nvim-tree.lua": { "branch": "master", "commit": "fb343438d49fba8c35ecc4829d66fca7a1f0ed3d" },
|
||||
"nvim-tree.lua": { "branch": "master", "commit": "8e8be709c9a93e1ebefde7964884a8b564bfd3e0" },
|
||||
"nvim-treesitter": { "branch": "main", "commit": "4916d6592ede8c07973490d9322f187e07dfefac" },
|
||||
"nvim-ts-autotag": { "branch": "main", "commit": "88c1453db4ba7dd24131086fe51fdf74e587d275" },
|
||||
"nvim-web-devicons": { "branch": "master", "commit": "dfbfaa967a6f7ec50789bead7ef87e336c1fa63c" },
|
||||
"plenary.nvim": { "branch": "master", "commit": "74b06c6c75e4eeb3108ec01852001636d85a932b" },
|
||||
"render-markdown.nvim": { "branch": "main", "commit": "5adf0895310c1904e5abfaad40a2baad7fe44a07" },
|
||||
"render-markdown.nvim": { "branch": "main", "commit": "f422cb5c6855f150e2ddcfaf44e7157b98b34f6a" },
|
||||
"telescope-fzf-native.nvim": { "branch": "main", "commit": "b25b749b9db64d375d782094e2b9dce53ad53a40" },
|
||||
"telescope.nvim": { "branch": "master", "commit": "7d324792b7943e4aa16ad007212e6acc6f9fe335" },
|
||||
"telescope.nvim": { "branch": "master", "commit": "9377230aa5305d9e9aca4ed8dadf1070fb4aa9fc" },
|
||||
"vim-floaterm": { "branch": "master", "commit": "bb4ba7952e906408e1f83b215f55ffe57efcade6" },
|
||||
"which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" }
|
||||
}
|
||||
|
||||
@ -28,6 +28,11 @@ return {
|
||||
return { desc = desc, buffer = ev.buf, silent = true }
|
||||
end
|
||||
|
||||
-- Render inlay hints (type/param/return) for servers that send them
|
||||
if vim.lsp.inlay_hint then
|
||||
vim.lsp.inlay_hint.enable(true, { bufnr = ev.buf })
|
||||
end
|
||||
|
||||
keymap.set('n', 'gd', '<cmd>Telescope lsp_definitions<cr>', opts('Go to definition'))
|
||||
keymap.set('n', 'gr', '<cmd>Telescope lsp_references<cr>', opts('Show LSP references'))
|
||||
keymap.set('n', 'gD', vim.lsp.buf.declaration, opts('Go to declaration'))
|
||||
@ -73,6 +78,15 @@ return {
|
||||
init_options = {
|
||||
hostInfo = 'neovim',
|
||||
},
|
||||
settings = {
|
||||
typescript = {
|
||||
inlayHints = {
|
||||
includeInlayVariableTypeHints = true,
|
||||
includeInlayParameterNameHints = 'all',
|
||||
includeInlayFunctionLikeReturnTypeHints = true,
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
-- eslint: linting for JS/TS/React projects
|
||||
|
||||
@ -65,6 +65,10 @@ PanelWindow {
|
||||
NetworkStatus {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
BluetoothControl {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
onClickedLeft: root.activePopup = root.activePopup === "bluetooth" ? "" : "bluetooth"
|
||||
}
|
||||
VolumeControl {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
onClickedLeft: root.activePopup = root.activePopup === "mixer" ? "" : "mixer"
|
||||
@ -118,6 +122,28 @@ PanelWindow {
|
||||
}
|
||||
}
|
||||
|
||||
// ── Bluetooth popup ───────────────────────────────────────────────
|
||||
PopoutWindow {
|
||||
id: btPopup
|
||||
popupName: "bluetooth"
|
||||
activePopup: root.activePopup
|
||||
|
||||
anchor.window: root
|
||||
anchor.rect.y: root.implicitHeight - root.bw - Theme.radius
|
||||
readonly property real pw: Math.max(rightRow.width + 2 * root.pad,
|
||||
btContent.implicitWidth + 2 * root.bw)
|
||||
anchor.rect.x: root.width - pw
|
||||
|
||||
implicitWidth: pw
|
||||
implicitHeight: btContent.implicitHeight + root.bw + Theme.radius
|
||||
|
||||
BluetoothContent {
|
||||
id: btContent
|
||||
anchors { left: parent.left; right: parent.right }
|
||||
scanning: btPopup._open
|
||||
}
|
||||
}
|
||||
|
||||
// ── Volume mixer popup ────────────────────────────────────────────
|
||||
PopoutWindow {
|
||||
popupName: "mixer"
|
||||
|
||||
187
roles/quickshell/files/bar/BluetoothContent.qml
Normal file
187
roles/quickshell/files/bar/BluetoothContent.qml
Normal file
@ -0,0 +1,187 @@
|
||||
import Quickshell.Bluetooth
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import "../components"
|
||||
|
||||
// Bluetooth panel – a plain Item so it can live inside an expanding section border.
|
||||
Item {
|
||||
id: root
|
||||
|
||||
implicitWidth: 300
|
||||
implicitHeight: btCol.implicitHeight + 24
|
||||
|
||||
// Driven by the popup's open state — only scan for nearby devices while visible.
|
||||
property bool scanning: false
|
||||
|
||||
readonly property var adapter: Bluetooth.defaultAdapter
|
||||
readonly property bool powered: adapter?.enabled ?? false
|
||||
|
||||
// Run device discovery only while the popup is open and the adapter is on.
|
||||
Binding {
|
||||
target: root.adapter
|
||||
property: "discovering"
|
||||
value: root.scanning && root.powered
|
||||
when: root.adapter !== null
|
||||
}
|
||||
|
||||
// \uf293 = FA bluetooth-b, \uf294 = FA bluetooth
|
||||
function devIcon(dev) {
|
||||
return dev.connected ? "\uf293" : "\uf294"
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: btCol
|
||||
anchors { fill: parent; margins: 12 }
|
||||
spacing: 4
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.bottomMargin: 2
|
||||
|
||||
Text {
|
||||
text: "Bluetooth"
|
||||
color: Theme.textDim
|
||||
font.pixelSize: 10
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
Text {
|
||||
text: root.powered ? "On" : "Off"
|
||||
font.pixelSize: 10
|
||||
color: root.powered ? Theme.accent : Theme.textDim
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: if (root.adapter) root.adapter.enabled = !root.adapter.enabled
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
visible: !root.powered
|
||||
text: "Adapter disabled"
|
||||
color: Theme.textDim
|
||||
font.pixelSize: 11
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
// ── Paired devices ────────────────────────────────────────────
|
||||
Text {
|
||||
visible: root.powered
|
||||
text: "Paired"
|
||||
color: Theme.textDim
|
||||
font.pixelSize: 10
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 6
|
||||
Layout.bottomMargin: 2
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: Bluetooth.devices
|
||||
delegate: DeviceRow {
|
||||
required property var modelData
|
||||
Layout.fillWidth: true
|
||||
device: modelData
|
||||
visible: root.powered && modelData.bonded
|
||||
}
|
||||
}
|
||||
|
||||
// ── Available (discoverable) devices ──────────────────────────
|
||||
RowLayout {
|
||||
visible: root.powered
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 6
|
||||
Layout.bottomMargin: 2
|
||||
|
||||
Text {
|
||||
text: "Available"
|
||||
color: Theme.textDim
|
||||
font.pixelSize: 10
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
Text {
|
||||
visible: root.adapter?.discovering ?? false
|
||||
text: "scanning…"
|
||||
color: Theme.textDim
|
||||
font.pixelSize: 10
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: Bluetooth.devices
|
||||
delegate: DeviceRow {
|
||||
required property var modelData
|
||||
Layout.fillWidth: true
|
||||
device: modelData
|
||||
// Only named devices — hides the swarm of random-address BLE beacons.
|
||||
visible: root.powered && !modelData.bonded
|
||||
&& (modelData.deviceName ?? "").length > 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component DeviceRow: RowLayout {
|
||||
id: drow
|
||||
required property var device
|
||||
spacing: 8
|
||||
implicitHeight: 28
|
||||
|
||||
// Once a freshly-paired device bonds, trust it (so it can reconnect
|
||||
// without an agent) and bring up the connection automatically.
|
||||
Connections {
|
||||
target: drow.device
|
||||
function onBondedChanged() {
|
||||
if (!drow.device.bonded) return
|
||||
if (!drow.device.trusted) drow.device.trusted = true
|
||||
if (!drow.device.connected) drow.device.connect()
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: root.devIcon(drow.device)
|
||||
font.family: "JetBrainsMono Nerd Font Mono"
|
||||
font.pixelSize: 13
|
||||
color: drow.device.connected ? Theme.accent : Theme.textDim
|
||||
}
|
||||
|
||||
Text {
|
||||
text: drow.device.name || drow.device.address || "?"
|
||||
font.pixelSize: 11
|
||||
color: drow.device.connected ? Theme.text : Theme.textDim
|
||||
Layout.fillWidth: true
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
Text {
|
||||
visible: drow.device.batteryAvailable
|
||||
text: Math.round(drow.device.battery * 100) + "%"
|
||||
font.pixelSize: 10
|
||||
color: Theme.textDim
|
||||
Layout.preferredWidth: 30
|
||||
horizontalAlignment: Text.AlignRight
|
||||
}
|
||||
|
||||
Text {
|
||||
text: drow.device.pairing ? "pairing…"
|
||||
: drow.device.state === BluetoothDeviceState.Connecting ? "…"
|
||||
: drow.device.state === BluetoothDeviceState.Disconnecting ? "…"
|
||||
: !drow.device.bonded ? "Pair"
|
||||
: drow.device.connected ? "Disconnect"
|
||||
: "Connect"
|
||||
font.pixelSize: 10
|
||||
color: drow.device.connected ? Theme.text : Theme.textDim
|
||||
Layout.preferredWidth: 70
|
||||
horizontalAlignment: Text.AlignRight
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
const d = drow.device
|
||||
if (d.pairing) d.cancelPair()
|
||||
else if (!d.bonded) d.pair()
|
||||
else if (d.connected) d.disconnect()
|
||||
else d.connect()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
63
roles/quickshell/files/bar/BluetoothControl.qml
Normal file
63
roles/quickshell/files/bar/BluetoothControl.qml
Normal file
@ -0,0 +1,63 @@
|
||||
import Quickshell.Bluetooth
|
||||
import QtQuick
|
||||
import "../components"
|
||||
|
||||
Item {
|
||||
id: root
|
||||
implicitWidth: chip.implicitWidth + 10
|
||||
implicitHeight: 24
|
||||
|
||||
signal clickedLeft
|
||||
|
||||
readonly property var adapter: Bluetooth.defaultAdapter
|
||||
readonly property bool powered: adapter?.enabled ?? false
|
||||
readonly property var connectedDevices:
|
||||
Bluetooth.devices.values.filter(d => d.connected)
|
||||
|
||||
// \uf293 = FA bluetooth-b (on), \uf294 = FA bluetooth (off / no connection)
|
||||
readonly property string btIcon: root.powered ? "\uf293" : "\uf294"
|
||||
|
||||
function label() {
|
||||
const n = root.connectedDevices.length
|
||||
if (n === 0) return ""
|
||||
if (n === 1) {
|
||||
const name = root.connectedDevices[0].name || ""
|
||||
return name.length > 16 ? name.substring(0, 15) + "…" : name
|
||||
}
|
||||
return n + " devices"
|
||||
}
|
||||
|
||||
Row {
|
||||
id: chip
|
||||
anchors.centerIn: parent
|
||||
spacing: 5
|
||||
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: root.btIcon
|
||||
font.family: "JetBrainsMono Nerd Font Mono"
|
||||
font.pixelSize: 14
|
||||
color: (root.powered && root.connectedDevices.length > 0) ? Theme.text : Theme.textDim
|
||||
}
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: root.label()
|
||||
font.pixelSize: 11
|
||||
color: Theme.textDim
|
||||
visible: text !== ""
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: mouse => {
|
||||
if (mouse.button === Qt.RightButton) {
|
||||
if (root.adapter) root.adapter.enabled = !root.adapter.enabled
|
||||
} else {
|
||||
root.clickedLeft()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -68,8 +68,8 @@ Item {
|
||||
required property var modelData
|
||||
Layout.fillWidth: true
|
||||
node: modelData
|
||||
visible: modelData.isStream && !modelData.isSink && modelData.ready
|
||||
&& !(modelData.description ?? "").toLowerCase().includes("monitor")
|
||||
// Application playback streams (sink inputs) report isStream && isSink.
|
||||
visible: modelData.isStream && modelData.isSink && modelData.ready
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
Bar 1.0 Bar.qml
|
||||
Battery 1.0 Battery.qml
|
||||
BluetoothControl 1.0 BluetoothControl.qml
|
||||
BluetoothContent 1.0 BluetoothContent.qml
|
||||
PopoutWindow 1.0 PopoutWindow.qml
|
||||
CalendarContent 1.0 CalendarContent.qml
|
||||
Clock 1.0 Clock.qml
|
||||
|
||||
@ -48,4 +48,6 @@
|
||||
- { src: bar/VolumeMixerContent.qml, dest: bar/VolumeMixerContent.qml }
|
||||
- { src: bar/Workspaces.qml, dest: bar/Workspaces.qml }
|
||||
- { src: bar/WorkspaceButton.qml, dest: bar/WorkspaceButton.qml }
|
||||
- { src: bar/BluetoothContent.qml, dest: bar/BluetoothContent.qml }
|
||||
- { src: bar/BluetoothControl.qml, dest: bar/BluetoothControl.qml }
|
||||
- { src: bar/qmldir, dest: bar/qmldir }
|
||||
|
||||
Reference in New Issue
Block a user