Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 44 additions & 12 deletions cli.sh
Original file line number Diff line number Diff line change
Expand Up @@ -283,14 +283,30 @@ brightness)
bash "${SCRIPT_DIR}/scripts/brightness_list.sh" >"${BRIGHTNESS_SAVE_FILE}.tmp" 2>/dev/null || {
echo "Warning: Could not query current brightness"
}
# Skip saving if brightness is 0 (screen off state) and we already have a save
if [ -f "${BRIGHTNESS_SAVE_FILE}.tmp" ]; then
while IFS=: read -r name bright method; do
if [ -n "$name" ] && [ -n "$bright" ]; then
echo "${name}:${bright}"
# Check if all values are 0 or very low (screen off state)
ALL_ZERO=true
while IFS=: read -r name bright; do
if [ -n "$bright" ] && [ "$bright" -gt 5 ]; then
ALL_ZERO=false
break
fi
done <"${BRIGHTNESS_SAVE_FILE}.tmp" >"$BRIGHTNESS_SAVE_FILE"
rm -f "${BRIGHTNESS_SAVE_FILE}.tmp"
echo "Saved current brightness for all monitors"
done <"${BRIGHTNESS_SAVE_FILE}.tmp"

# Only save if not all zero, OR if no previous save exists
if [ "$ALL_ZERO" = true ] && [ -f "$BRIGHTNESS_SAVE_FILE" ]; then
echo "Skipped saving - brightness at 0 (keeping previous save)"
rm -f "${BRIGHTNESS_SAVE_FILE}.tmp"
else
while IFS=: read -r name bright; do
if [ -n "$name" ] && [ -n "$bright" ]; then
echo "${name}:${bright}"
fi
done <"${BRIGHTNESS_SAVE_FILE}.tmp" >"$BRIGHTNESS_SAVE_FILE"
rm -f "${BRIGHTNESS_SAVE_FILE}.tmp"
echo "Saved current brightness for all monitors"
fi
fi
else
# Save specific monitor
Expand Down Expand Up @@ -352,14 +368,30 @@ brightness)
echo "Warning: Could not query current brightness"
}
# Convert format from name:brightness:method to name:brightness
# Skip saving if brightness is 0 (screen off state) and we already have a save
if [ -f "${BRIGHTNESS_SAVE_FILE}.tmp" ]; then
while IFS=: read -r name bright method; do
if [ -n "$name" ] && [ -n "$bright" ]; then
echo "${name}:${bright}"
# Check if all values are 0 or very low (screen off state)
ALL_ZERO=true
while IFS=: read -r name bright; do
if [ -n "$bright" ] && [ "$bright" -gt 5 ]; then
ALL_ZERO=false
break
fi
done <"${BRIGHTNESS_SAVE_FILE}.tmp" >"$BRIGHTNESS_SAVE_FILE"
rm -f "${BRIGHTNESS_SAVE_FILE}.tmp"
echo "Saved current brightness for all monitors"
done <"${BRIGHTNESS_SAVE_FILE}.tmp"

# Only save if not all zero, OR if no previous save exists
if [ "$ALL_ZERO" = true ] && [ -f "$BRIGHTNESS_SAVE_FILE" ]; then
echo "Skipped saving - brightness at 0 (keeping previous save)"
rm -f "${BRIGHTNESS_SAVE_FILE}.tmp"
else
while IFS=: read -r name bright; do
if [ -n "$name" ] && [ -n "$bright" ]; then
echo "${name}:${bright}"
fi
done <"${BRIGHTNESS_SAVE_FILE}.tmp" >"$BRIGHTNESS_SAVE_FILE"
rm -f "${BRIGHTNESS_SAVE_FILE}.tmp"
echo "Saved current brightness for all monitors"
fi
fi
else
# Save specific monitor
Expand Down
45 changes: 45 additions & 0 deletions modules/services/BluetoothDevice.qml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,53 @@ QtObject {
property int battery: -1
property bool batteryAvailable: battery >= 0
property bool connecting: false

// Battery notification tracking
property int previousBattery: -1
property bool notified15: false
property bool notified5: false

signal infoUpdated()

// Battery low notification - only send once per threshold crossing
onBatteryChanged: {
// Skip if battery value hasn't actually changed
if (battery === previousBattery) {
return;
}

if (battery >= 0 && connected) {
// Only notify at 15% if crossing threshold from above
if (previousBattery > 15 && battery <= 15 && battery > 5 && !notified15) {
notified15 = true;
sendLowBatteryNotification(15);
}
// Only notify at 5% if crossing threshold from above
if (previousBattery > 5 && battery <= 5 && !notified5) {
notified5 = true;
sendLowBatteryNotification(5);
}
// Reset flags when battery goes back up
if (battery > 15) {
notified15 = false;
notified5 = false;
} else if (battery > 5) {
notified5 = false;
}
}
previousBattery = battery;
}

function sendLowBatteryNotification(percent) {
const urgency = percent <= 5 ? "critical" : "normal";
Quickshell.execDetached([
"notify-send",
"-u", urgency,
"-i", "battery-low",
"Bluetooth Battery Low",
`${name} battery is at ${battery}%`
]);
}

// Connect with auto-trust for new devices
function connect() {
Expand Down
26 changes: 26 additions & 0 deletions modules/services/IdleService.qml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ Singleton {
// Master Idle Logic
property int elapsedIdleTime: 0
property var triggeredListeners: [] // Keeps track of indices that have fired
property bool resumeCooldown: false // Prevent immediate resume after listener triggers
property bool pendingReset: false // Track if reset was requested during cooldown

// Master Monitor: Detects "absence of activity" almost immediately
IdleMonitor {
Expand All @@ -72,6 +74,26 @@ Singleton {
idleTimer.start();
} else {
idleTimer.stop();
// If in cooldown, defer the reset
if (root.resumeCooldown) {
root.pendingReset = true;
} else {
root.resetIdleState();
}
}
}
}

// Cooldown timer - prevents resume for a short period after listener triggers
Timer {
id: cooldownTimer
interval: 1500 // 1.5 seconds - enough for lockscreen to fully load
repeat: false
onTriggered: {
root.resumeCooldown = false;
// Execute pending reset if activity happened during cooldown and user is still active
if (root.pendingReset && !masterMonitor.isIdle) {
root.pendingReset = false;
root.resetIdleState();
}
}
Expand Down Expand Up @@ -99,6 +121,10 @@ Singleton {
console.log("Idle timer " + tVal + "s reached: " + listener.onTimeout);
executionProc.command = ["sh", "-c", listener.onTimeout];
executionProc.running = true;

// Activate cooldown to prevent immediate resume from listener-caused activity
root.resumeCooldown = true;
cooldownTimer.restart();
}
root.triggeredListeners.push(i);
}
Expand Down