{"id":50574712,"url":"https://github.com/drakotrogdor/168_clock","last_synced_at":"2026-06-04T21:00:49.106Z","repository":{"id":362493945,"uuid":"1259302699","full_name":"DrakoTrogdor/168_clock","owner":"DrakoTrogdor","description":"A desktop clock whose hour hand sweeps the entire week, not just 12 hours. One full revolution = 168 hours, Sunday 00:00:00 → Saturday 23:59:59.","archived":false,"fork":false,"pushed_at":"2026-06-04T13:43:59.000Z","size":353,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-04T14:07:35.615Z","etag":null,"topics":["clock","clockface","fun","workweek"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DrakoTrogdor.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-04T11:26:59.000Z","updated_at":"2026-06-04T13:42:37.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/DrakoTrogdor/168_clock","commit_stats":null,"previous_names":["drakotrogdor/168_clock"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/DrakoTrogdor/168_clock","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DrakoTrogdor%2F168_clock","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DrakoTrogdor%2F168_clock/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DrakoTrogdor%2F168_clock/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DrakoTrogdor%2F168_clock/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DrakoTrogdor","download_url":"https://codeload.github.com/DrakoTrogdor/168_clock/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DrakoTrogdor%2F168_clock/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33917202,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-04T02:00:06.755Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clock","clockface","fun","workweek"],"created_at":"2026-06-04T21:00:27.770Z","updated_at":"2026-06-04T21:00:49.083Z","avatar_url":"https://github.com/DrakoTrogdor.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 168‑Hour Week Clock\n\n[![CI](https://github.com/DrakoTrogdor/168_clock/actions/workflows/ci.yml/badge.svg)](https://github.com/DrakoTrogdor/168_clock/actions/workflows/ci.yml)\n\n\u003e A desktop clock whose hour hand sweeps the **entire week**, not just 12 hours. One full revolution = 168 hours, Sunday 00:00 → Saturday 23:59:59.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"preview.png\" alt=\"168-Hour Week Clock\" width=\"540\"\u003e\n\u003c/p\u003e\n\nA small native desktop app (Windows · macOS · Linux) written in Rust and rendered on the GPU with [`wgpu`](https://github.com/gfx-rs/wgpu). Instead of a 12‑hour dial, the face is divided into **7 days × 24 hours = 168 ticks**, so the slow hand tells you where you are in the *week* at a glance. The minute and second hands behave normally.\n\n---\n\n## Features\n\n- **168‑hour dial** — the hour hand makes one full turn per week; each of the 168 ticks is one hour.\n- **Normal minute \u0026 second hands** — 60 divisions each, with a smooth (sub‑second) second sweep.\n- **Seven‑color bezel \u0026 day labels** — one colored arc and one name (SUN … SAT) per day.\n- **Work‑hours highlight** — the 9 am–5 pm ticks on Monday–Friday are marked in green.\n- **Numeric readouts on the hands** — the hour hand's tip shows the hour (`00`–`23`), the minute hand's tip shows the minute (`00`–`59`), engraved into each hand.\n- **\"Business‑hours\" color cue** — those tip numbers sweep **green → amber → red** during the weekday workday (amber at noon) and stay dark otherwise.\n- **Full‑screen desktop‑widget mode** — press **F11** to go borderless and clip the window to the clock face, so the desktop shows through around it.\n- **No font dependency** — all text is a tiny built‑in vector stroke font drawn with the same triangle pipeline.\n\n## How to read it\n\n| Element | Meaning |\n| --- | --- |\n| **Hour hand** (short, stout) | Points at the current **hour of the week** — 168 positions, one full turn per week. 12 o'clock is **Sunday 00:00**, advancing clockwise. Its tip shows the hour of day, `00`–`23`. |\n| **Minute hand** (long, thin) | Normal — one turn per hour. Its tip shows the minute, `00`–`59`. |\n| **Second hand** (red, sweeping) | Normal — one turn per minute. |\n| **168 tick marks** | The only graduations on the face — one per hour of the week. The 7 day boundaries (midnights) are longer and white. |\n| **Colored bezel** | Seven arcs, one per day, Sunday → Saturday clockwise. |\n| **Green ticks** | The 9 am–5 pm hours, Monday–Friday. |\n| **Hand‑tip number color** | Dark on weekends and outside 9–5; green→amber→red during the weekday workday (peak amber at noon). |\n\n## Controls\n\n| Key | Action |\n| --- | --- |\n| **F11** | Toggle borderless full‑screen. The title bar is removed and everything outside the clock face becomes transparent (the desktop shows through). |\n| **Esc** | Exit full‑screen. |\n| Close button | Quit. |\n\n## Building \u0026 running\n\n### Prerequisites\n\n- [Rust](https://rustup.rs/) (stable toolchain, edition 2021).\n- Windows 10/11 with a Direct3D 12‑capable GPU.\n\n### Run\n\n```sh\ncargo run --release\n```\n\n### Build a standalone binary\n\n```sh\ncargo build --release\n```\n\nThe executable is written to `target/release/week-clock.exe`. Release builds use the `windows` subsystem, so no console window is shown.\n\n## How it works\n\n- **Rendering** — the whole clock is rebuilt every frame as a few thousand colored triangles (face, bezel, ticks, labels, hands) and uploaded to a single vertex buffer. A minimal 2D pipeline with 4× MSAA draws it. There is no retained scene graph; the CPU‑side geometry is cheap enough to regenerate per frame.\n- **Time** — local time (including DST) comes from [`chrono`](https://github.com/chronotope/chrono); the hour‑of‑week, minute, and second are turned into hand angles.\n- **Text** — digits and day names are a hand‑authored vector stroke font (`glyph()` in `src/lib.rs`), so there's no glyph‑rasterization or font‑atlas dependency.\n- **Full‑screen transparency** is handled per platform:\n  - **Windows** — the window is clipped to the clock circle with a Win32 window region (`SetWindowRgn`); a shaped window forces DWM composition, so the see‑through effect works even full‑screen. (Per‑pixel GPU alpha is unreliable with DXGI flip‑model swapchains.)\n  - **macOS / Linux** — a transparent window plus a non‑opaque surface alpha mode; in full‑screen the background is cleared to alpha 0, leaving only the opaque clock circle so the desktop shows around it. macOS uses *simple* full‑screen (not a separate Space) to keep the live desktop behind the clock.\n\n## Platform support\n\n| OS | Status | Transparent full‑screen |\n| --- | --- | --- |\n| **Windows 10/11** | Built \u0026 tested | Window‑region clip |\n| **Linux** (Wayland, or X11 + compositor) | Builds \u0026 initializes (verified on WSL2 Debian 13) | GPU alpha |\n| **macOS** | Cross‑platform code, not verified | GPU alpha (simple full‑screen) |\n\nWindows is the primary, tested target. The Linux build is verified to compile and bring up `winit` + `wgpu` (Vulkan), selecting the transparency‑capable surface path. The macOS path uses the standard `winit`/`wgpu` approach but has not been verified — please report issues.\n\n- **Linux** needs a compositing window manager for the transparency (always present under Wayland; under X11, run a compositor such as `picom`). Without one, full‑screen simply shows the opaque dark background.\n- **macOS** keeps the desktop visible behind the clock by using *simple* full‑screen rather than a separate Space.\n\n## Built with\n\n- [`wgpu`](https://github.com/gfx-rs/wgpu) — GPU rendering (Direct3D 12 on Windows, Metal on macOS, Vulkan on Linux)\n- [`winit`](https://github.com/rust-windowing/winit) — windowing and input\n- [`chrono`](https://github.com/chronotope/chrono) — local time\n- [`bytemuck`](https://github.com/Lokathor/bytemuck), [`pollster`](https://github.com/zesterer/pollster) — glue; [`raw-window-handle`](https://github.com/rust-windowing/raw-window-handle) for the window handle (Windows only)\n\n## Project layout\n\n```\n.\n├── src/\n│   ├── lib.rs           # the entire app: rendering, geometry, font, input, android_main\n│   └── main.rs          # thin desktop binary entry point\n├── assets/              # icon (svg/png/ico/icns) + macOS Info.plist\n├── scripts/             # icon generator + raster asset pipeline\n├── .github/workflows/   # CI + release workflows\n├── build.rs             # version embedding + Windows icon resource\n├── Cargo.toml\n└── README.md\n```\n\n## Contributing\n\n`main` is protected — changes land via pull request with green CI. A typical loop:\n\n```sh\ngit switch -c my-change\n# ...edit...\ncargo run --release                          # see it\ncargo clippy --all-targets -- -D warnings    # CI enforces this\ngit commit -am \"Describe the change\"\ngit push -u origin my-change\n# open a PR; once CI (build + clippy on Windows/Linux/macOS) is green, merge\n```\n\nCI ([ci.yml](.github/workflows/ci.yml)) runs `cargo build` and `cargo clippy -D warnings` on Windows, Linux, and macOS for every push and pull request.\n\n### Versioning\n\nThe version is `MAJOR.MINOR.PATCH` (source of truth: `Cargo.toml`), embedded at build time by [`build.rs`](build.rs) and shown in the window title. Bump it with the `BUMP` env var; `build.rs` rewrites `Cargo.toml` with odometer roll-over — `MINOR`/`PATCH` are single digits `0–9`, `MAJOR` is uncapped:\n\n```sh\nBUMP=patch cargo build \u0026\u0026 unset BUMP   # 1.2.9 → 1.3.0\nBUMP=minor cargo build \u0026\u0026 unset BUMP   # 1.9.4 → 2.0.0\nBUMP=major cargo build \u0026\u0026 unset BUMP   # 1.2.3 → 2.0.0\n```\n\n`BUMP` is one‑shot — always `unset` it after (PowerShell: `Remove-Item Env:BUMP`), or the next rebuild will bump again.\n\n### Cutting a release\n\nPush a semver tag and the [release workflow](.github/workflows/release.yml) builds and uploads native binaries for all three platforms to a new GitHub Release:\n\n```sh\ngit tag v0.1.0\ngit push origin v0.1.0\n```\n\n### Icons\n\nThe icon is generated from [`assets/icon.svg`](assets/icon.svg) (by `scripts/gen_icon.py`). Run `scripts/build-icons.sh` to regenerate the raster assets — `icon.png`, `icon.ico`, `icon.icns`, and the Android `android-res/mipmap-*/ic_launcher.png` — which needs `librsvg2-bin`, `icoutils`, and `icnsutils`.\n\n- **Windows** — `icon.ico` is embedded into the `.exe` at build time (`build.rs` + `winresource`) and also set as the runtime window icon.\n- **Linux** — set as the runtime window icon (X11; under Wayland the icon comes from a `.desktop` file).\n- **macOS** — winit can't set a window icon, so build a `.app` with [`cargo-bundle`](https://github.com/burtonageo/cargo-bundle) (`cargo install cargo-bundle \u0026\u0026 cargo bundle --release`); it uses `assets/icon.icns` via the `[package.metadata.bundle]` config.\n- **Android** — the `assets/android-res/mipmap-*` launcher icons, referenced as `@mipmap/ic_launcher` via `[package.metadata.android]`.\n\n### Android (experimental)\n\nThe same code runs full-screen on Android — the app is a library crate (`weekclock`) with an `android_main` entry built as a `cdylib`, and the surface is recreated on `Resumed`/`Suspended`. Build an APK with [`cargo-apk`](https://crates.io/crates/cargo-apk) (needs the Android SDK + NDK and the `aarch64-linux-android` Rust target):\n\n```sh\nrustup target add aarch64-linux-android\ncargo install cargo-apk\ncargo apk build --lib            # debug, auto-signed: target/debug/apk/*.apk\n```\n\nCI also builds the APK and uploads it as an artifact. A release APK needs your own signing keystore (`[package.metadata.android.signing.release]`). Status: builds and type-checks; on-device behavior (resume/suspend, local time) still being validated.\n\n## License\n\nReleased under the [MIT License](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrakotrogdor%2F168_clock","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdrakotrogdor%2F168_clock","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrakotrogdor%2F168_clock/lists"}