{"id":16786523,"url":"https://github.com/ephread/thebell","last_synced_at":"2025-03-16T23:23:27.520Z","repository":{"id":161155054,"uuid":"634327855","full_name":"ephread/TheBell","owner":"ephread","description":"A round-based HIIT timer for Apple Watch.","archived":false,"fork":false,"pushed_at":"2024-01-09T07:38:59.000Z","size":2121,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"develop","last_synced_at":"2025-03-08T22:42:07.509Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Swift","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ephread.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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}},"created_at":"2023-04-29T19:08:30.000Z","updated_at":"2024-01-09T16:22:27.000Z","dependencies_parsed_at":null,"dependency_job_id":"7552260c-e34b-415b-ac8c-70a0a74882f8","html_url":"https://github.com/ephread/TheBell","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ephread%2FTheBell","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ephread%2FTheBell/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ephread%2FTheBell/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ephread%2FTheBell/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ephread","download_url":"https://codeload.github.com/ephread/TheBell/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243945726,"owners_count":20372922,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":[],"created_at":"2024-10-13T08:12:28.367Z","updated_at":"2025-03-16T23:23:27.495Z","avatar_url":"https://github.com/ephread.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ![The Bell](Documentation/git_banner.png)\n\n\u003cdiv align=\"center\"\u003e\n\u003cp\u003eA timer app designed for high-intensity interval workouts.\u003c/p\u003e\n\u003ca href=\"https://apps.apple.com/us/app/apple-store/id1522205874\"\u003e\n\u003cimg src=\"Documentation/download_on_the_app_store.svg\" alt=\"Download on the App Store\" /\u003e\n\u003c/a\u003e\n\u003c/div\u003e\n\n## Table of Content\n\n- [Table of Content](#table-of-content)\n- [History](#history)\n- [Getting Started](#getting-started)\n  - [Requirements](#requirements)\n  - [Installation](#installation)\n- [Architecture \\\u0026 Rational](#architecture--rational)\n  - [Overview](#overview)\n  - [Tiers and naming conventions](#tiers-and-naming-conventions)\n  - [Navigation](#navigation)\n  - [Why do audio assets sound silly?](#why-do-audio-assets-sound-silly)\n  - [Future](#future)\n- [License](#license)\n\n## History\n\nDuring the 2020 lockdowns, I created The Bell app as a way to further explore watchOS development. Initially built using WatchKit, I later discovered that newer APIs were SwiftUI-only after the release of the Apple Watch Series 7.\n\nIn early 2023, I decided to revisit the app and update it by transitioning the UI layer to SwiftUI and implementing async/await APIs. With no intention of monetizing it, I chose to open-source The Bell as a functional proof-of-concept.\n\nThroughout the process, I reworked approximately 70% of the app's codebase. Looking back, if I were to start from scratch today, I would likely opt for an Elm/redux-inspired architecture over MVVM.\n\n## Getting Started\n\n### Requirements\n\n- Xcode 15+\n- watchOS 10+\n\n### Installation\n\n1. Clone the repository.\n2. (Optional) Install [Mint] and ensure it's available in the `PATH` loaded by Xcode.\n   - Run `mint bootstrap`\n3. Copy `main.xcconfig.example` and rename it to `main.xcconfig`\n   - In `main.xccconfig`, set `DEVELOPMENT_TEAM` to a valid identifier and `DISAMBIGUATOR` to `${DEVELOPMENT_TEAM}`.\n   - Alternatively, if you plan to run the app on the simulator, you can leave\n     `DEVELOPMENT_TEAM` and `DISAMBIGUATOR` blank.\n4. Copy the content of `Supporting Files/Assets/Sounds/cc0` to `Supporting Files/Assets/Sounds/`, see [Audio Assets] for more information.\n5. Open Xcode and run the project!\n\n[Mint]: https://github.com/yonaskolb/Mint\n[Audio Assets]: #why-do-audio-assets-sound-silly\n\n## Architecture \u0026 Rational\n\n### Overview\n\nThe Bell uses a three-tier architecture with MVVM in the presentation layer. While the layers are not completely separated, they could be easily decoupled with minimal work. For example:\n\n1. the simplicity of the data model in The Bell allows for the presentation layer to directly query repositories, as the data is often not converted or manipulated by the application layer;\n2. `UserPreference` and `Workout` are both plain structs, easily created and mocked and thus not abstracted;\n3. application-level data models like `WorkoutSummary` are also freely passed around.\n\nHowever, a more complex app would benefit from having different types encapsulating the data in the different layers, even if they match 1:1 (in that case, type aliases could be used).\n\nThe Bell relies heavily on protocols and dependency injection to ensure that view models, managers, and helpers can be tested in isolation.\n\n### Tiers and naming conventions\n\n- **Presentation Layer:** Contains all the UI-related code, including MVVM's Views and View Models.\n    - _Standard suffixes:_ `-View` (suffixes `Button`, `Label` etc. are also possible), `-ViewModel`\n    - _Directory:_ `Sources/Presentation`\n- **Application Layer:** Contains the application logic and abstractions to system components, such as HealthKit, AVFoundation and Haptic Feedback. HealthKit can be considered part of MVVM's Models.\n    - _Standard suffixes:_ `-Manager`\n    - _Directory:_ `Sources/Application`\n- **Data Layer:** Contains repositories and the database logic, aka MVVM's Models.\n    - _Standard suffixes:_ `-Repository`\n    - _Directory:_ `Sources/Data`\n\nAll tiers may also contain `-Helper` types.\n\n### Navigation\n\nThe Bell has a very simple navigation pattern, therefore, `NavigationPath` and/or Coordinators are not involved.\n\n### Why do audio assets sound silly?\n\nThe audio assets used in the App Store version of the app cannot be freely distributed, so I had to replace them with public domain equivalents. I intentionally chose some silly sounds to keep things fun and lighthearted. Who knew that public-domain audio could be so fun?\n\n### Future\n\nHere are some tasks that I plan to work on for The Bell as time allows.\n\n- [ ] Improve the test structure and split test cases between unit and integration tests,\n      especially around time-sensitive code.\n- [ ] Save the workout state in the database instead of using UserDefaults,\n      as this is a remnant of early prototypes.\n- [ ] Allow the creation and management of multiple workouts.\n\n## License\n\nThe codebase is licensed under the terms of the Apache License 2.0, see [LICENSE]\nfor more information. It includes code inspired by DebouncedOnChange,\nlicensed under the terms of the MIT license.\n\nImage assets are licensed under the terms of the Creative Commons\nAttribution-NonCommercial-NoDerivatives 4.0 International License, see [LICENSE.CC-BY-NC-ND]\nfor more information.\n\nAudio assets are licensed under terms of the Creative Commons CC0 1.0 Universal License,\nsee [LICENSE.CC0]. They were sourced from freesound.org and remixed:\n\n- [sheepbone flute] by [magnuswaker]\n- [Loony \u0026 Wacky » Boing 1] by [Hedmarking]\n\n[LICENSE]: LICENSE\n[LICENSE.CC-BY-NC-ND]: LICENSE.CC-BY-NC-ND\n[LICENSE.CC0]: LICENSE.CC0\n\n[DebouncedOnChange]: https://github.com/Tunous/DebouncedOnChange\n\n[freesound.org]: https://freesound.org/\n\n[sheepbone flute]: https://freesound.org/people/Hedmarking/sounds/179061/\n[Loony \u0026 Wacky » Boing 1]: https://freesound.org/people/magnuswaker/sounds/540788/\n\n[magnuswaker]: https://freesound.org/people/magnuswaker/\n[Hedmarking]: https://freesound.org/people/Hedmarking/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fephread%2Fthebell","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fephread%2Fthebell","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fephread%2Fthebell/lists"}