Skip to content

feat: fix resource bundle crash and integrate uBlock Origin with sett…#160

Open
shantanunautiyal wants to merge 18 commits intosozercan:mainfrom
shantanunautiyal:main
Open

feat: fix resource bundle crash and integrate uBlock Origin with sett…#160
shantanunautiyal wants to merge 18 commits intosozercan:mainfrom
shantanunautiyal:main

Conversation

@shantanunautiyal
Copy link
Copy Markdown

@shantanunautiyal shantanunautiyal commented Mar 29, 2026

feat: Fix Resource Bundle Crash and Integrate uBlock Origin

This PR resolves a critical startup crash in packaged app bundles and integrates the uBlock Origin web extension to provide native ad-blocking and privacy protection for Kaset.

Description

The main objective of this PR was to fix a crash occurring when the app is packaged as a .app bundle (due to Bundle.module limitations in SwiftPM executable targets) and to enhance the YouTube Music experience by integrating an industry-standard ad-blocker directly into the WebKit view.

AI Prompt (Optional)

🤖 AI Prompt Used

AI Tool: Antigravity (Google Deepmind)

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 📚 Documentation update
  • 🎨 UI/UX improvement

Related Issues

Fixes the immediate EXC_BREAKPOINT crash on app launch when bundled.

Changes Made

  • Safe Resource Discovery: Replaced Bundle.module with a custom PackageResourceLookup helper that correctly identifies the resource bundle inside Contents/Resources/ in a packaged .app.
  • uBlock Origin Integration:
    • Added the uBlock Origin (v1.70.0) manifest and files to the project.
    • Updated WebKitManager to load the extension via WKWebExtensionController.
  • Settings UI Enhancements:
    • Added a new Content Blocking section to GeneralSettingsView.
    • Real-time status indicator ("Active" vs "Not loaded") and version display.
  • Modernization:
    • Migrated legacy .strings localizations to the modern .xcstrings format.
    • Enhanced DiagnosticsLogger for better troubleshooting of WebKit and App lifecycle events.
  • Documentation: Added docs/ublock-origin.md with detailed integration info and update guides.

Testing

  • Manual testing performed (verified app launches without crash)
  • Verified uBlock Origin loading status in Settings UI
  • Confirmed ad-blocking behavior on music.youtube.com
  • UI tested on macOS 26 (Liquid Glass effects maintained)

Checklist

  • My code follows the project's style guidelines
  • I have updated documentation if needed
  • My changes generate no new warnings

Screenshots

The new Content Blocking section can be found under Settings > General:

  • Green shield icon and "Active • v1.70.0" text confirms successful integration.

Additional Notes

The resource bundle relocation fix is crucial for any SPM-based macOS executable that targets an .app bundle distribution while using the standard Bundle.module pattern for localized strings or assets.

shantanunautiyal and others added 3 commits March 29, 2026 11:13
…ings UI

- Fix resource bundle accessor crash when packaged as .app by using robust PackageResourceLookup helper\n- Integrate uBlock Origin web extension in WebKitManager\n- Add Content Blocking status and version to GeneralSettingsView\n- Modernize localizations with xcstrings\n- Add uBlock Origin integration documentation\n- Improve diagnostics logging and UI test configuration
@sozercan
Copy link
Copy Markdown
Owner

sozercan commented Apr 2, 2026

@shantanunautiyal thanks for the PR! instead of bundling ublock directly, can you introduce an extensions manager where users can bring their own extensions?

@shantanunautiyal
Copy link
Copy Markdown
Author

@sozercan , Will definetely proceed in this side. Thanks for your suggestion.

shantanunautiyal and others added 3 commits April 3, 2026 11:54
- Removed hardcoded uBlock Origin from WebKitManager.
- Created ExtensionsManager to dynamically load user-managed extensions.
- Added 'Extensions' tab to Settings UI for users to add/remove their own extensions.
- Configured NSOpenPanel to handle safe directory imports.
- Added required App Sandbox file access enhancements `com.apple.security.files.user-selected.read-only` and `com.apple.security.files.bookmarks.app-scope` to support persistent WebKit extension access.
- Updated documentation and added ADR 0013.
- Bumped app version to 1.1.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Sertac Ozercan <sozercan@gmail.com>
# Conflicts:
#	Sources/Kaset/Resources/Localizable.xcstrings
#	Sources/Kaset/Resources/ar.lproj/Localizable.strings
#	Sources/Kaset/Resources/en.lproj/Localizable.strings
#	Sources/Kaset/Resources/tr.lproj/Localizable.strings
@shantanunautiyal
Copy link
Copy Markdown
Author

shantanunautiyal commented Apr 3, 2026

@sozercan

Screenshot 2026-04-03 at 12 00 46 PM image

What's Changed

This PR completely overhauls the content-blocking architecture by moving from a hardcoded, bundled extension to a flexible "Bring Your Own" Extensions Manager. It enables users to securely inject and manage their own WebKit-compatible extensions, significantly reducing the app's bundle size and increasing user agency.

✨ New Features

  • Bring Your Own Extensions: Added a dynamic ExtensionsManager that allows users to locally load and manage any WebKit-compatible extension (Manifest V3/V2).
  • Extensions Settings Dashboard: Introduced an Extensions tab under Settings ⌘, where users can view, add, and manage their installed extensions.

🛠 Architecture & Sandbox Improvements

  • Security-Scoped Bookmarks: Implemented robust App Sandbox integration using the com.apple.security.files.bookmarks.app-scope entitlement so Kaset can securely retain access to user-selected extension directories across app restarts.
  • NSOpenPanel Fix: Fixed a known bug with file pickers silently failing to render inside SwiftUI Settings TabViews by directly deferring to macOS NSOpenPanel.runModal natively on the main thread.
  • Decoupled Bundles: Deleted all hardcoded uBlockOrigin files (.js, .html, .xml) from the Git tree to slim down the repo size and separate concerns.

🐛 Bug Fixes & Chores

  • Resolves GitHub merge conflicts affecting Localizable.xcstrings vs legacy .strings files.
  • Painlessly propagates upstream Korean (ko) localization changes.
  • Added an Architecture Decision Record (docs/adr/0013-extensions-manager.md) detailing the transition away from bundled extensions.
  • Bumped project marketing version to 1.1.

📝 How to test

  1. Run Kaset and navigate to Settings -> Extensions.
  2. Click Add Extension...
  3. Select an extracted WebKit extension folder containing a manifest.json file.
  4. Restart the app when prompted and verify the extension operates seamlessly on the internal browser.

…ring & dynamic path resolution

- Implemented manifest.json parsing for automatic dashboard path discovery
- Resolved Code -1008 navigation error by sharing WKProcessPool across all webviews
- Bypassed sandbox permission blocks by implementing containerized storage in Application Support
- Linked shared Extension Controller to Options/Popup windows
- Reverted to folder selection to ensure valid sandbox scoping for extension bundles
- Add .gitkeep to Sources/Kaset/Extensions/ so git tracks the empty
  directory (fixes 'missing inputs' build error on CI)
- Fix SwiftFormat: sorted imports, trailing spaces, redundant
  @ViewBuilder, self-insertion, unused args, andOperator, indentation
  in #if blocks, preferKeyPath, consecutiveBlankLines, wrapPropertyBodies
- Fix ExtensionsManager.removeExtension() using wrong directory name
  ('Extensions' → 'ManagedExtensions') and remove unused variable
- ToastView: .regularMaterial → .glassEffect(.regular) for floating toast
- WhatsNewView: .thinMaterial badge → .glassEffect(.regular, in: .capsule)
- WhatsNewView: .borderedProminent → .buttonStyle(.glassProminent)
  for the Continue button (system glass prominent style)
This standardizes multiple views in Kaset to use the new Liquid Glass
button style in replace of older flat `.borderedProminent` forms, including:
- OnboardingView
- PlaylistDetailView
- LikedMusicView
- ArtistDetailView
- PodcastsView
- ErrorView
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants