From acdcb6883d69b612b7eac58a8b19c93f49602ab4 Mon Sep 17 00:00:00 2001 From: proitheus Date: Tue, 23 Jun 2026 07:18:19 +0800 Subject: [PATCH] breaktimer: init at 2.1.0 Cross-platform Electron desktop app for managing periodic breaks. Runs as a system tray application with notifications and fullscreen break overlays. Homepage: https://github.com/tom-james-watson/breaktimer-app Assisted-by: opencode (z-ai GLM-5.2) --- .../br/breaktimer/disable-auto-update.patch | 89 +++++++++++ pkgs/by-name/br/breaktimer/package.nix | 140 ++++++++++++++++++ 2 files changed, 229 insertions(+) create mode 100644 pkgs/by-name/br/breaktimer/disable-auto-update.patch create mode 100644 pkgs/by-name/br/breaktimer/package.nix diff --git a/pkgs/by-name/br/breaktimer/disable-auto-update.patch b/pkgs/by-name/br/breaktimer/disable-auto-update.patch new file mode 100644 index 000000000000..2af3ab9a14e3 --- /dev/null +++ b/pkgs/by-name/br/breaktimer/disable-auto-update.patch @@ -0,0 +1,89 @@ +diff --git a/app/main/index.ts b/app/main/index.ts +index 96921cb..f6ce034 100644 +--- a/app/main/index.ts ++++ b/app/main/index.ts +@@ -1,11 +1,9 @@ +-import { app, shell } from "electron"; ++import { app } from "electron"; + import electronDebug from "electron-debug"; + import log from "electron-log"; +-import { autoUpdater } from "electron-updater"; + import { setAutoLauch } from "./lib/auto-launch"; + import { initBreaks } from "./lib/breaks"; + import "./lib/ipc"; +-import { showNotification } from "./lib/notifications"; + import { getAppInitialized } from "./lib/store"; + import { initTray } from "./lib/tray"; + import { createSettingsWindow, createSoundsWindow } from "./lib/windows"; +@@ -29,62 +27,6 @@ if (!gotTheLock) { + app.exit(); + } + +-function getDownloadUrl(): string { +- switch (process.platform) { +- case "win32": +- return "https://github.com/tom-james-watson/breaktimer-app/releases/latest/download/BreakTimer.exe"; +- case "linux": +- return "https://github.com/tom-james-watson/breaktimer-app/releases/latest"; +- default: +- throw new Error("Download URL should not be called for macOS"); +- } +-} +- +-function shouldAutoInstall(): boolean { +- const isMac = process.platform === "darwin"; +- const isLinux = process.platform === "linux"; +- +- return isMac || isLinux; +-} +- +-function checkForUpdates(): void { +- log.info("Checking for updates..."); +- autoUpdater.logger = log; +- +- autoUpdater.on("error", (error) => { +- log.error(`Auto updater error: ${error}`); +- }); +- +- if (shouldAutoInstall()) { +- autoUpdater.checkForUpdatesAndNotify().catch((error) => { +- log.error(`Unable to run auto updater: ${error}`); +- }); +- } else { +- autoUpdater.autoDownload = false; +- +- autoUpdater.on("update-available", (info) => { +- log.info("Update available:", info); +- +- const downloadUrl = getDownloadUrl(); +- +- showNotification( +- "Update Available", +- "A new version of BreakTimer is available. Click to download.", +- () => { +- shell.openExternal(downloadUrl).catch((error) => { +- log.error(`Failed to open download URL: ${error}`); +- }); +- }, +- false, +- ); +- }); +- +- autoUpdater.checkForUpdates().catch((error) => { +- log.error(`Unable to check for updates: ${error}`); +- }); +- } +-} +- + if (process.env.NODE_ENV === "production") { + const sourceMapSupport = require("source-map-support"); + sourceMapSupport.install(); +@@ -146,8 +88,4 @@ app.on("ready", async () => { + initBreaks(); + initTray(); + createSoundsWindow(); +- +- if (process.env.NODE_ENV !== "development") { +- checkForUpdates(); +- } + }); diff --git a/pkgs/by-name/br/breaktimer/package.nix b/pkgs/by-name/br/breaktimer/package.nix new file mode 100644 index 000000000000..9fd129c237fc --- /dev/null +++ b/pkgs/by-name/br/breaktimer/package.nix @@ -0,0 +1,140 @@ +{ + lib, + stdenv, + buildNpmPackage, + copyDesktopItems, + electron_40, + fetchFromGitHub, + jq, + makeDesktopItem, + makeWrapper, + nix-update-script, + nodejs_24, +}: + +let + electron = electron_40; + nodejs = nodejs_24; + description = "Cross-platform desktop app for managing periodic breaks"; +in +buildNpmPackage rec { + pname = "breaktimer"; + version = "2.1.0"; + + src = fetchFromGitHub { + owner = "tom-james-watson"; + repo = "breaktimer-app"; + tag = "v${version}"; + hash = "sha256-STDb6+brlVk/ZPUbw3cQOpe2r03WlFKEBgVLqJrsrHI="; + }; + + strictDeps = true; + __structuredAttrs = true; + + # electron-updater's auto-install path tries to download a new release + # from GitHub and overwrite the nix-store binary, which is read-only. + # Updates come via nix instead. + patches = [ ./disable-auto-update.patch ]; + + # The package ships a lockfile (package-lock.json) but the default + # `npm run build` is run via `concurrently`; we drive the build manually. + dontNpmBuild = true; + + env.ELECTRON_SKIP_BINARY_DOWNLOAD = "1"; + + npmDepsHash = "sha256-UL8e0UKZKhHHC+JvRpmcdBvFHlCdn3YknceVJ+knMgg="; + + nativeBuildInputs = [ + jq + nodejs + makeWrapper + copyDesktopItems + ]; + + preBuild = '' + if [[ $(jq --raw-output '.devDependencies.electron' < package.json | grep -E --only-matching '\^[0-9]+' | sed -e 's/\^//') != ${lib.escapeShellArg (lib.versions.major electron.version)} ]]; then + echo 'ERROR: electron version mismatch' + exit 1 + fi + ''; + + buildPhase = '' + runHook preBuild + + npm run build + + # electron-builder needs to mutate the copied Electron.app, which is + # read-only in the nix store. Copy it to a writable location first. + cp -r ${electron.dist} electron-dist + chmod -R u+w electron-dist + + # Produce an unpacked Electron app without code-signing / notarisation. + npm exec electron-builder -- \ + --dir \ + --c.electronDist=electron-dist \ + --c.electronVersion=${electron.version} \ + --c.mac.identity=null \ + --c.mac.notarize=false + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + '' + + lib.optionalString stdenv.hostPlatform.isLinux '' + unpacked="release/linux-${lib.optionalString stdenv.hostPlatform.isAarch64 "arm64-"}unpacked" + + mkdir -p "$out/share/lib/breaktimer" + cp -r "$unpacked"/{locales,resources{,.pak}} "$out/share/lib/breaktimer" + + makeWrapper '${lib.getExe electron}' "$out/bin/breaktimer" \ + --add-flags "$out/share/lib/breaktimer/resources/app.asar" \ + --add-flags "\''${NIXOS_OZONE_WL:+\''${WAYLAND_DISPLAY:+--ozone-platform-hint=auto --enable-features=UseOzonePlatform,WaylandWindowDecorations,WebRTCPipeWireCapturer}}" \ + --set-default ELECTRON_IS_DEV 0 \ + --inherit-argv0 + + install -Dm644 resources/icon.png \ + "$out/share/icons/hicolor/512x512/apps/breaktimer.png" + '' + + lib.optionalString stdenv.hostPlatform.isDarwin '' + mkdir -p "$out/Applications" + cp -R release/mac-*/BreakTimer.app "$out/Applications/" + + mkdir -p "$out/bin" + makeWrapper \ + "$out/Applications/BreakTimer.app/Contents/MacOS/BreakTimer" \ + "$out/bin/breaktimer" \ + --set-default ELECTRON_IS_DEV 0 + '' + + '' + runHook postInstall + ''; + + desktopItems = [ + (makeDesktopItem { + name = "breaktimer"; + exec = "breaktimer"; + icon = "breaktimer"; + comment = description; + desktopName = "BreakTimer"; + genericName = "Break Reminder"; + categories = [ + "Utility" + "Office" + ]; + }) + ]; + + passthru.updateScript = nix-update-script { }; + + meta = { + inherit description; + homepage = "https://github.com/tom-james-watson/breaktimer-app"; + changelog = "https://github.com/tom-james-watson/breaktimer-app/releases/tag/v${version}"; + license = lib.licenses.gpl3Plus; + maintainers = with lib.maintainers; [ proitheus ]; + mainProgram = "breaktimer"; + platforms = electron.meta.platforms; + }; +}