local M = {} local focusCanvas = nil local activeProfile = nil local configPath = hs.configdir .. "/focus_profiles.json" local function loadProfiles() local file = io.open(configPath, "r") if not file then print("Error: Could not open focus_profiles.json") return nil end local content = file:read("*a") file:close() return hs.json.decode(content) end local function manageApps(profileConfig) for _, appName in ipairs(profileConfig.close) do local app = hs.application.get(appName) if app then app:kill() end end for _, appName in ipairs(profileConfig.keepOpen) do hs.application.launchOrFocus(appName) end end local function setFocusOverlay(alpha) if focusCanvas then focusCanvas:delete() focusCanvas = nil end if not alpha or alpha == 0 then return end local mainScreen = hs.screen.mainScreen() local rect = mainScreen:frame() focusCanvas = hs.canvas.new(rect) focusCanvas:insertElement({ action = "fill", type = "rectangle", fillColor = { red = 0, green = 0, blue = 0, alpha = alpha } }) focusCanvas:level(50) focusCanvas:show() local frontApp = hs.application.frontmostApplication() if frontApp then local win = frontApp:mainWindow() if win then win:focus() end end end function M.activate(profileName) local profiles = loadProfiles() if not profiles or not profiles[profileName] then print("Error: Profile '" .. tostring(profileName) .. "' not found.") return "Profile not found" end activeProfile = profileName local currentProfileConfig = profiles[profileName] manageApps(currentProfileConfig) setFocusOverlay(currentProfileConfig.dimAlpha) return "Activated " .. profileName .. " mode" end function M.clear() setFocusOverlay(nil) activeProfile = nil return "Focus mode cleared" end hs.screen.watcher.new(function() if activeProfile then local profiles = loadProfiles() if profiles and profiles[activeProfile] then setFocusOverlay(profiles[activeProfile].dimAlpha) end end end):start() return M