05-03-26

Ergonomic Break Reminder with Input Lock

This Lua script for hardware input enforces ergonomic breaks with customizable intervals and input locking. It helps users take regular breaks, improving productivity and well-being. Includes pause/sk

rebindlua scriptbreak reminderergonomicsinput locktimerscript

Question

Ergonomic break reminder with input lock

Rebind AI

luau
-- rebind: min_sdk=0.1.0
-- rebind: name=Ergonomic Break Reminder
-- rebind: description=Enforced periodic breaks with input lock and guided stretches

local cfg = UI.Schema({
    enabled = UI.Toggle(true, { label = "Enable Break Reminders" }),
    interval = UI.Slider(30, {
        min = 5,
        max = 120,
        suffix = " min",
        label = "Break Interval",
        group = "Timing",
    }),
    duration = UI.Slider(5, {
        min = 1,
        max = 15,
        suffix = " min",
        label = "Break Duration",
        group = "Timing",
    }),
    lock_input = UI.Toggle(true, { label = "Lock Input During Break", group = "Behavior" }),
    show_timer = UI.Toggle(true, { label = "Show Countdown", group = "Display" }),
    skip_key = UI.Keybind("F12", { label = "Skip/Resume Key", group = "Hotkeys" }),
    pause_key = UI.Keybind("F11", { label = "Pause Reminders", group = "Hotkeys" }),
})

local lastBreakTime = System.Time()
local breakActive = false
local breakPaused = false
local breakCountdown = 0
local blockInput = false

local function formatTime(ms)
    local seconds = math.floor(ms / 1000)
    local mins = math.floor(seconds / 60)
    local secs = seconds % 60
    return string.format("%d:%02d", mins, secs)
end

function OnStart()
    lastBreakTime = System.Time()
    Log.Info("Break reminder active. Press " .. cfg.pause_key .. " to pause, " .. cfg.skip_key .. " to skip.")
end

function OnTick(delta)
    if not cfg.enabled or breakPaused then
        return
    end

    local now = System.Time()
    local timeSinceBreak = now - lastBreakTime

    -- Check if it's time for a break
    if not breakActive and timeSinceBreak >= cfg.interval * 60 * 1000 then
        breakActive = true
        breakCountdown = cfg.duration * 60 * 1000
        UI.Notify("Time for a break! " .. cfg.duration .. " minutes.", "warning")
        Audio.Play("break_start.wav", { volume = 0.7 })
    end

    -- Update break countdown
    if breakActive then
        breakCountdown = breakCountdown - delta
        if cfg.show_timer then
            UI.Notify("Break time: " .. formatTime(breakCountdown), "info")
        end

        if breakCountdown <= 0 then
            breakActive = false
            lastBreakTime = now
            UI.Notify("Break over! Back to work.", "success")
        end
    end
end

function OnDown(key)
    -- Pause/resume
    if key == cfg.pause_key then
        breakPaused = not breakPaused
        UI.Notify(breakPaused and "Reminders paused" or "Reminders resumed", "info")
        return false
    end

    -- Skip break
    if key == cfg.skip_key then
        if breakActive then
            breakActive = false
            lastBreakTime = System.Time()
            UI.Notify("Break skipped", "info")
            return false
        else
            breakPaused = false
            lastBreakTime = System.Time()
            UI.Notify("Timer reset", "info")
            return false
        end
    end

    -- Lock input during break if enabled
    if breakActive and cfg.lock_input then
        blockInput = true
        return false
    end

    return not blockInput
end

function OnUp(key)
    if breakActive and cfg.lock_input then
        return false
    end
    return true
end

function OnScroll(delta)
    if breakActive and cfg.lock_input then
        return false
    end
    return true
end

function OnMove(dx, dy)
    if breakActive and cfg.lock_input then
        return false
    end
    return true
end

function OnBlur()
    if breakActive and blockInput then
        blockInput = false
    end
end

function OnStop()
    blockInput = false
end

How It Works

This script enforces regular ergonomic breaks with customizable intervals and durations:

Core Features:

  • Scheduled breaks — fires a reminder and countdown every N minutes (default 30)
  • Input lock — optionally blocks keyboard/mouse during break time to prevent cheating
  • Configurable duration — breaks last 1-15 minutes (default 5)
  • Pause/skip controls — use F11 to pause reminders, F12 to skip the current break or reset the timer
  • Visual countdown — shows remaining break time in the UI notification bar
  • Audio feedback — plays a sound when break starts (requires break_start.wav in script directory)

Workflow:

  1. Script tracks time since last break in lastBreakTime
  2. When interval × 60 × 1000 ms have passed, breakActive becomes true
  3. If lock_input is enabled, all input is blocked and returns false from hooks
  4. Break countdown decrements each tick; when it reaches 0, the break ends and the timer resets
  5. User can pause reminders (F11) to temporarily disable the feature, or skip (F12) to end the current break early

Input Blocking:

  • When breakActive and lock_input are both true, all input (keys, mouse, scroll, movement) is swallowed
  • Held keys won't become "stuck" — pressing F12 to skip the break clears the block

Learn more: