RepoPilotOpen in app →

hyperoslo/Whisper

:mega: Whisper is a component that will make the task of display messages and in-app notifications simple. It has three different views inside

Mixed

Stale — last commit 4y ago

worst of 4 axes
Use as dependencyConcerns

non-standard license (Other); last commit was 4y ago…

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • 18 active contributors
  • Distributed ownership (top contributor 38% of recent commits)
  • Other licensed
Show 4 more →
  • CI configured
  • Stale — last commit 4y ago
  • Non-standard license (Other) — review terms
  • No test directory detected
What would change the summary?
  • Use as dependency ConcernsMixed if: clarify license terms

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Forkable" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Forkable
[![RepoPilot: Forkable](https://repopilot.app/api/badge/hyperoslo/whisper?axis=fork)](https://repopilot.app/r/hyperoslo/whisper)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/hyperoslo/whisper on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: hyperoslo/Whisper

Generated by RepoPilot · 2026-05-10 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/hyperoslo/Whisper shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

WAIT — Stale — last commit 4y ago

  • 18 active contributors
  • Distributed ownership (top contributor 38% of recent commits)
  • Other licensed
  • CI configured
  • ⚠ Stale — last commit 4y ago
  • ⚠ Non-standard license (Other) — review terms
  • ⚠ No test directory detected

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live hyperoslo/Whisper repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/hyperoslo/Whisper.

What it runs against: a local clone of hyperoslo/Whisper — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in hyperoslo/Whisper | Confirms the artifact applies here, not a fork | | 2 | License is still Other | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 1351 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>hyperoslo/Whisper</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of hyperoslo/Whisper. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/hyperoslo/Whisper.git
#   cd Whisper
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of hyperoslo/Whisper and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "hyperoslo/Whisper(\\.git)?\\b" \\
  && ok "origin remote is hyperoslo/Whisper" \\
  || miss "origin remote is not hyperoslo/Whisper (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(Other)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"Other\"" package.json 2>/dev/null) \\
  && ok "license is Other" \\
  || miss "license drift — was Other at generation time"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "Source/Message.swift" \\
  && ok "Source/Message.swift" \\
  || miss "missing critical file: Source/Message.swift"
test -f "Source/WhisperView.swift" \\
  && ok "Source/WhisperView.swift" \\
  || miss "missing critical file: Source/WhisperView.swift"
test -f "Source/WhisperFactory.swift" \\
  && ok "Source/WhisperFactory.swift" \\
  || miss "missing critical file: Source/WhisperFactory.swift"
test -f "Source/ShoutFactory.swift" \\
  && ok "Source/ShoutFactory.swift" \\
  || miss "missing critical file: Source/ShoutFactory.swift"
test -f "Source/WhistleFactory.swift" \\
  && ok "Source/WhistleFactory.swift" \\
  || miss "missing critical file: Source/WhistleFactory.swift"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 1351 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~1321d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/hyperoslo/Whisper"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

Whisper is a Swift UI component library for displaying transient and persistent in-app notifications across iOS apps via three distinct message types: Whispers (persistent messages below navigation bars), Shouts (full in-app announcements with optional tap actions), and Whistles (minimal discrete notifications). It handles automatic scroll view inset management and view controller transitions transparently, eliminating manual offset calculations. Standard CocoaPods library structure: Source/ contains the core implementation (Config.swift and Configuration/ modules), Demo/WhisperDemo/ provides a runnable example app with UIViewController demos (ViewController.swift, TableViewController.swift), and Images/ holds marketing screenshots. Single-framework design with no submodules or plugins.

👥Who it's for

iOS developers building consumer-facing apps who need to display contextual notifications, error messages, and user feedback without implementing custom notification UI or managing complex scroll view geometry. Particularly valuable for teams building apps with UINavigationController-based navigation that need consistent, reusable notification patterns.

🌱Maturity & risk

Actively maintained but not heavily updated; CircleCI passes, has CocoaPods distribution, includes a working Demo app (Demo/WhisperDemo/), and clear CHANGELOG.md. No visible recent commit dates in file list suggests it reached stable state. Production-ready for notification use cases, though update cadence suggests it's in maintenance rather than active feature development.

Single-language codebase with 30,707 lines of Swift (minimal Ruby tooling at 682 lines); no visible dependency lock file indicates either shallow external dependencies or missing Podfile.lock in provided file list. No test file paths visible in top 60 files (only WhisperTests/WhisperTests.swift exists), raising coverage concerns. Risk of iOS version compatibility drift if not regularly updated for new OS releases.

Active areas of work

No recent activity indicators visible in provided file list; repo appears in stable/maintenance state. CHANGELOG.md and CONTRIBUTING.md exist, suggesting past activity governance but no specific ongoing work is evident from the 60-file snapshot provided.

🚀Get running

Check README for instructions.

Daily commands: Open Demo/WhisperDemo/WhisperDemo.xcworkspace (not .xcodeproj) in Xcode. Select WhisperDemo or WhisperTests scheme and press Cmd+R (run) or Cmd+U (test). The demo app displays three view controllers (in ViewController.swift and TableViewController.swift) that showcase each notification type.

🗺️Map of the codebase

  • Source/Message.swift — Defines the core Message model that all three notification types (Whisper, Shout, Whistle) use; fundamental data structure for the entire library.
  • Source/WhisperView.swift — Core UI component that renders the main notification views; implements the display logic shared across different notification styles.
  • Source/WhisperFactory.swift — Factory for creating and configuring Whisper notifications; entry point for the primary use case of displaying persistent bottom-bar messages.
  • Source/ShoutFactory.swift — Factory for creating in-app notification Shouts; handles the lifecycle and presentation of modal-style notifications.
  • Source/WhistleFactory.swift — Factory for creating Whistle notifications; implements the lightweight notification variant with distinct presentation behavior.
  • Source/Config.swift — Central configuration and global state management; controls timing, animation, and appearance defaults across all notification types.
  • Source/Showing.swift — Protocol that defines the contract for displayable notifications; abstracts common interface for Whisper, Shout, and Whistle implementations.

🧩Components & responsibilities

  • Message (Swift struct) — Immutable data container holding notification content (title, subtitle, image) and styling hints (colors, fonts); no logic.
    • Failure mode: Invalid or missing required fields cause runtime crashes when WhisperView tries to render; no validation.
  • WhisperFactory (Swift class, factory pattern) — Builds and returns a configured WhisperView instance; orchestrates Message creation and applies Whisper-specific layout (bottom-of-bar positioning).
    • Failure mode: If called on deallocated object or during view lifecycle edge cases, may leak memory or cause orphaned animations.
  • ShoutFactory (Swift class, factory pattern, UIView animations) — Creates in-app modal notifications with centered positioning and overlay backdrop; handles interrupt logic.
    • Failure mode: Multiple concurrent Shouts may overlap unpredictably; no queue mechanism to serialize display.
  • WhistleFactory (Swift class, factory pattern) — Produces lightweight top-of-screen notifications with minimal footprint; quick auto-hide behavior.
    • Failure mode: May be obscured by system status bar or notch; no collision detection with other UI elements.
  • WhisperView (UIView, CABasicAnimation, AutoLayout) — UIView subclass implementing animation, layout constraints, and gesture handling; core rendering engine for all notification styles.
    • Failure mode: Constraint conflicts with host view can cause layout warnings;

🛠️How to make changes

Add a new notification style variant

  1. Create a new factory class in Source/ following the pattern of WhisperFactory.swift or ShoutFactory.swift (Source/MyNotificationFactory.swift)
  2. Ensure your factory returns instances conforming to the Showing protocol defined in Source/Showing.swift (Source/Showing.swift)
  3. Customize presentation logic by extending WhisperView.swift or creating a variant; leverage UIView+Extensions.swift for animations (Source/WhisperView.swift)
  4. Register default styling in Source/Config.swift and add any color/font presets to Source/Configuration/ (Source/Config.swift)

Add a new color or font preset

  1. Open Source/Configuration/ColorList.swift and add a new static color property or enum case (Source/Configuration/ColorList.swift)
  2. Alternatively, add font presets to Source/Configuration/FontList.swift following existing naming conventions (Source/Configuration/FontList.swift)
  3. Update Source/Config.swift to reference new preset in default configuration if needed (Source/Config.swift)
  4. Test in Demo/WhisperDemo/WhisperDemo/ViewController.swift by creating a Message with the new preset (Demo/WhisperDemo/WhisperDemo/ViewController.swift)

Extend Message data model with custom properties

  1. Modify Source/Message.swift to add new properties (e.g., custom metadata, callbacks, or formatting hints) (Source/Message.swift)
  2. Update WhisperFactory.swift, ShoutFactory.swift, and WhistleFactory.swift to accept and propagate the new property (Source/WhisperFactory.swift)
  3. Modify Source/WhisperView.swift to use the new property during rendering or animation (Source/WhisperView.swift)
  4. Add test cases in Demo/WhisperDemo/WhisperTests/WhisperTests.swift to validate the new behavior (Demo/WhisperDemo/WhisperTests/WhisperTests.swift)

🔧Why these technologies

  • Swift — Native iOS development language; provides strong typing and modern syntax for building robust UI components.
  • UIKit — Primary framework for iOS UI rendering; WhisperView extends UIView to leverage native animation and layout capabilities.
  • CocoaPods (Whisper.podspec) — Standard iOS dependency management; allows easy integration into other projects and version control.
  • Protocol-Oriented Design (Showing protocol) — Enables polymorphism across three distinct notification types without inheritance complexity; maintains clean separation of concerns.

⚖️Trade-offs already made

  • Global Config singleton state for defaults

    • Why: Simplifies API and reduces boilerplate; developers don't pass timing/color to every notification.
    • Consequence: Thread-safety concerns if Config is mutated from multiple threads; less flexibility per-instance without wrapper objects.
  • Factory pattern instead of direct class constructors

    • Why: Centralizes notification creation logic; allows lazy initialization and builder-style fluent API.
    • Consequence: Adds abstraction layer that may feel heavyweight for simple use cases; more files to understand.
  • UIView-based rendering rather than SwiftUI

    • Why: Compatibility with older iOS versions; UIKit is battle-tested and widely understood.
    • Consequence: Not composable with modern SwiftUI code; future Swift-only projects may find integration awkward.
  • Message struct instead of multiple subclasses

    • Why: Lightweight, flexible data carrier; avoids class hierarchy complexity.
    • Consequence: Less type safety for variant-specific properties; all notification types share same Message structure even if fields don't apply.

🚫Non-goals (don't propose these)

  • Does not handle push notifications or remote alert delivery
  • Does not include persistence or logging of notifications
  • Does not provide SwiftUI wrappers (UIKit-only)
  • Does not manage view controller hierarchy or navigation
  • Does not support real-time streaming or live-updating notifications

🪤Traps & gotchas

The Whisper namespace wrapper is required for show/hide calls due to naming conflicts with UIViewController.show() — accidentally calling .show() on the controller directly will not display the notification. ScrollView inset adjustment is automatic but may cause layout issues if custom inset code runs elsewhere in the view controller. Demo uses xcworkspace, not xcodeproj — opening the .xcodeproj directly will fail to find CocoaPods dependencies.

🏗️Architecture

💡Concepts to learn

  • UIViewController Extension Injection — Whisper adds show/hide methods to UIViewController via extensions; understanding how Swift extensions inject behavior into system frameworks is core to this library's API design
  • UIScrollView Content Inset Adjustment — Whisper automatically manages scrollView.contentInset and contentOffset to prevent notifications from overlapping content; this is a critical iOS layout technique Whisper hides from the user
  • UIView Animation Completion Callbacks — Whisper uses UIView.animate(withDuration:animations:completion:) to show/hide notifications and trigger user-provided completion closures; essential to understand for customizing animation behavior
  • Namespace Wrapper Pattern — Whisper wraps its API in a Whisper enum/struct namespace to avoid conflicts with UIViewController.show(); this pattern solves naming collision problems in Swift APIs
  • CocoaPods Podspec Distribution — Whisper is distributed via CocoaPods; understanding how .podspec files declare dependencies, source paths, and version requirements is necessary for publishing or modifying this library
  • UIViewController Transition Coordination — Whisper adjusts notification state during view controller transitions; transitionCoordinator() is used to animate notifications alongside navigation push/pop events
  • toast-swift/Toast-Swift — Direct competitor providing simple toast notification view for iOS; different API (extension method pattern) but solves same notification display problem
  • scalessec/Noti — Similar iOS in-app notification library with customizable appearance; alternative to Whisper's three-type approach
  • indragiek/INTULocationManager — Demonstrates CocoaPods library distribution and UIViewController extension patterns common in hyperoslo's ecosystem
  • hyperoslo/Hue — Sibling hyperoslo library for color management; commonly used alongside Whisper for notification color customization
  • realm/realm-swift — Ecosystem complement for apps using Whisper to display data persistence notifications and sync status messages

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive unit tests for WhisperView, ShoutFactory, and WhistleFactory

The repo has a test file (Demo/WhisperDemo/WhisperTests/WhisperTests.swift) but it appears minimal. The three factory classes (ShoutFactory.swift, WhisperFactory.swift, WhistleFactory.swift) and core WhisperView.swift lack documented test coverage. This is critical for a UI notification library where display logic, animations, and state management are paramount.

  • [ ] Expand Demo/WhisperDemo/WhisperTests/WhisperTests.swift with test cases for WhisperView initialization and lifecycle
  • [ ] Add tests for ShoutFactory.swift covering message creation and configuration application
  • [ ] Add tests for WhistleFactory.swift and WhistleFactory display behavior
  • [ ] Add tests for Message.swift model validation and property handling
  • [ ] Add tests for UIView+Extensions.swift utility methods used across the library
  • [ ] Verify ColorList.swift and FontList.swift configuration application in tests

Add CI workflow for tvOS and watchOS compatibility testing

The podspec and project structure suggest this is an iOS library, but Whisper's notification patterns could benefit from tvOS and watchOS support. The current CircleCI badge in README indicates basic CI exists, but there's no visible GitHub Actions workflow file. Adding explicit platform-specific tests would increase confidence in cross-platform compatibility and catch regressions early.

  • [ ] Create .github/workflows/test.yml with separate jobs for iOS, tvOS, and watchOS targets
  • [ ] Add tvOS and watchOS to Whisper.podspec platform specifications if not already present
  • [ ] Test WhisperView, ShoutFactory, and WhistleFactory rendering on tvOS (larger screens, remote interaction)
  • [ ] Test notification behavior on watchOS (compact display constraints)
  • [ ] Document any platform-specific limitations in README.md

Document and add tests for Configuration API (ColorList.swift, FontList.swift, Config.swift)

The Source/Configuration/ directory exists with ColorList.swift and FontList.swift, but the README doesn't explain how to customize colors and fonts for Whisper, Shout, and Whistle views. This is a high-value developer experience gap. Adding configuration documentation and tests ensures the API is well-defined and doesn't regress.

  • [ ] Review Config.swift, ColorList.swift, and FontList.swift to understand current configuration architecture
  • [ ] Add a 'Customization' or 'Configuration' section to README.md with code examples for changing colors and fonts
  • [ ] Create unit tests in WhisperTests.swift validating that ColorList and FontList configurations are correctly applied to each view type
  • [ ] Add tests confirming that custom configurations don't break layout or accessibility
  • [ ] Document any limitation on which properties can be customized per view type (Whisper vs Shout vs Whistle)

🌿Good first issues

  • Add unit tests for the three message types (Message, Announcement, Murmur) in WhisperTests.swift covering initialization, property mutation, and animation completion callbacks — currently only one test file exists with likely minimal coverage
  • Document the UIViewController extension methods that inject show/hide/present functionality by adding inline comments to the source files explaining scroll view inset math — no visible inline documentation in provided structure
  • Add a fourth demo view controller in Demo/WhisperDemo/WhisperDemo/ showing Whisper/Shout/Whistle stacking behavior when multiple notifications are queued, with a commented code example

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 27bb55c — Merge pull request #217 from jesster2k10/patch-1 (3lvis)
  • 80dbb40 — Merge pull request #3 from jesster2k10/patch-2 (jesseonol)
  • 59cc811 — Merge pull request #2 from jesster2k10/patch-3 (jesseonol)
  • fcf276f — [feat]: customisable dimensions (jesseonol)
  • ce8a4f7 — Merge pull request #1 from jesster2k10/patch-2 (jesseonol)
  • 62ecf82 — [feat] allow custom fonts (jesseonol)
  • 711f8bf — [feat] allow custom whisper font (jesseonol)
  • 16ef882 — Update README.md (3lvis)
  • db4d7f4 — Fix demo (3lvis)
  • fd0dee7 — Merge pull request #216 from hyperoslo/update-swift-5 (3lvis)

🔒Security observations

The Whisper library is a relatively small UI component library for iOS with moderate security posture. No critical vulnerabilities were identified based on the file structure analysis. However, the analysis is limited by the absence of actual source code content and configuration files. Primary concerns are: (1) Potential unvalidated user input in message display components, (2) Dependency management and outdated packages requiring audit, (3) Lack of visible security policies and guidelines. The codebase would benefit from implementing input validation, establishing a security.md file, implementing automated security testing in CI/CD, and conducting regular dependency audits. As an open-source library, the project should prioritize establishing responsible disclosure procedures and security guidelines.

  • Low · Potential Use of Outdated Dependencies — Whisper.podspec, Demo/WhisperDemo/Podfile. The codebase uses CocoaPods for dependency management (Whisper.podspec, Podfile present). Without access to the actual Podfile.lock and current dependency versions, there is a risk that dependencies may be outdated and contain known vulnerabilities. The podspec file should be reviewed to ensure all dependencies are pinned to secure, up-to-date versions. Fix: Regularly audit dependencies using tools like pod outdated, update to the latest secure versions, and implement dependency vulnerability scanning in CI/CD pipeline (e.g., using OWASP Dependency-Check or similar).
  • Low · Missing Input Validation in UI Components — Source/Message.swift, Source/WhisperView.swift, Source/ShoutFactory.swift. The codebase contains UI notification components (Whisper, Shout, Whistle) that display user-provided messages. Without visible input validation in the source files (Source/Message.swift, Source/WhisperView.swift), there is a potential risk of displaying unsanitized content that could be exploited for UI manipulation or rendering attacks. Fix: Implement proper input validation and sanitization for all user-supplied content before displaying in UI components. Validate message length, character encoding, and HTML/special characters if applicable.
  • Low · No Visible Security Policies or Guidelines — CONTRIBUTING.md, Repository root. The CONTRIBUTING.md file is present but the security posture documentation is not visible in the provided file list. There is no evident security policy, responsible disclosure process, or security guidelines for contributors. Fix: Create a SECURITY.md file documenting security policies, responsible disclosure procedures, and guidelines for reporting vulnerabilities. Reference OWASP guidelines for secure code practices.
  • Low · Potential XSS Risk in Demo Application — Demo/WhisperDemo/WhisperDemo/ViewController.swift, Demo/WhisperDemo/WhisperDemo/TableViewController.swift. The demo application (Demo/WhisperDemo) includes test files and view controllers that may accept or display user input. Without visible sanitization logic in TableViewController.swift and ViewController.swift, there could be potential for XSS-like attacks if untrusted content is displayed. Fix: Ensure all user input in demo and production code is validated and sanitized before display. Use native iOS safe rendering methods and avoid any dynamic content evaluation.
  • Low · CI/CD Configuration Not Fully Visible — circle.yml. The circle.yml file is present indicating CircleCI usage, but its configuration is not provided. Security checks, dependency scanning, and code quality gates may not be properly configured in the CI/CD pipeline. Fix: Ensure the CI/CD pipeline includes: static code analysis (SwiftLint), dependency vulnerability scanning, SAST tools, code coverage requirements, and automated security testing. Configure branch protection rules on GitHub/GitLab.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Mixed signals · hyperoslo/Whisper — RepoPilot