Skip to content

jamespheffernan/InboxReader

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 

Repository files navigation

Inbox Reader

GTD-style reading app for iPadOS. Capture URLs via Share Sheet, read with clean typography, process into OmniFocus actions.

Xcode Project Setup

1. Create New Project

  1. Open Xcode 15.2+

  2. File → New → Project

  3. Choose App (iOS)

  4. Settings:

    • Product Name: InboxReader
    • Team: Your team
    • Organization Identifier: com.yourname (or your identifier)
    • Interface: SwiftUI
    • Language: Swift
    • Storage: None (we're using SwiftData manually)
    • Uncheck "Include Tests" for now
  5. Save to: ~/Documents/Github/InboxReader

    • Important: Save in the existing folder, Xcode will create the .xcodeproj alongside the existing files

2. Add Swift Package Dependency

Add the swift-readability package for article extraction. The package has been cloned locally to Packages/swift-readability.

  1. File → Add Package Dependencies...
  2. Click "Add Local..." at the bottom of the package picker
  3. Navigate to InboxReader/Packages/swift-readability
  4. Click "Add Package"
  5. Select the Readability library (not ReadabilityUI)
  6. Add to target: InboxReader (main app only, not extension)

Note: This package requires Swift 6.0 (Xcode 16+). If you're on Xcode 15, you may need to modify Packages/swift-readability/Package.swift to change swift-tools-version: 6.0 to swift-tools-version: 5.9.

3. Add Existing Files to Project

  1. In Xcode's Project Navigator, right-click on InboxReader folder
  2. Choose "Add Files to InboxReader..."
  3. Select all .swift files from:
    • InboxReader/Models/
    • InboxReader/Views/
    • InboxReader/Services/
    • InboxReader/Shared/
  4. Make sure "Copy items if needed" is unchecked (files are already in place)
  5. Target: InboxReader

4. Add Share Extension Target

  1. File → New → Target
  2. Choose Share Extension
  3. Settings:
    • Product Name: ShareExtension
    • Language: Swift
    • Uncheck "Include UI Extension (Storyboard)"
  4. When prompted "Activate ShareExtension scheme?" click Activate

5. Add Share Extension Files

  1. Delete the auto-generated ShareViewController.swift in the ShareExtension folder
  2. Add existing files from ShareExtension/ folder:
    • ShareViewController.swift
    • ShareView.swift
  3. Target: ShareExtension

6. Share Extension Must Access Shared Code

The Share Extension needs access to the models and DataConfiguration.

  1. Select ReadingItem.swift in Project Navigator

  2. In File Inspector (right panel), under "Target Membership", check both:

    • ✅ InboxReader
    • ✅ ShareExtension
  3. Repeat for:

    • Schema.swift
    • DataConfiguration.swift

Note: Do NOT add ContentExtractor.swift or ContentProcessor.swift to the Share Extension - these use the Readability package which would exceed extension memory limits.

7. Configure App Group

Both targets need access to the same data store.

  1. Select the project in Navigator (blue icon at top)

  2. Select InboxReader target

  3. Go to "Signing & Capabilities" tab

  4. Click "+ Capability" → App Groups

  5. Click "+" and add: group.com.inboxreader.shared

  6. Select ShareExtension target

  7. Go to "Signing & Capabilities"

  8. Add App Groups capability

  9. Check the same group: group.com.inboxreader.shared

8. Configure Share Extension Info.plist

Select ShareExtension/Info.plist and ensure it contains:

<key>NSExtension</key>
<dict>
    <key>NSExtensionAttributes</key>
    <dict>
        <key>NSExtensionActivationRule</key>
        <dict>
            <key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
            <integer>1</integer>
            <key>NSExtensionActivationSupportsWebPageWithMaxCount</key>
            <integer>1</integer>
            <key>NSExtensionActivationSupportsText</key>
            <true/>
        </dict>
    </dict>
    <key>NSExtensionPointIdentifier</key>
    <string>com.apple.share-services</string>
    <key>NSExtensionPrincipalClass</key>
    <string>$(PRODUCT_MODULE_NAME).ShareViewController</string>
</dict>

9. Add OmniFocus URL Scheme Query

For the main app to check if OmniFocus is installed:

  1. Select InboxReader/Info.plist (or Info tab in target settings)
  2. Add key: LSApplicationQueriesSchemes (Array)
  3. Add item: omnifocus

10. Set Deployment Target

  1. Select project → General tab
  2. Set "Minimum Deployments" to iOS 17.0 for both targets

11. Build and Run

  1. Select an iPad Simulator (e.g., iPad Air)
  2. Build and run the main app (Cmd+R)
  3. To test Share Extension:
    • Run the app once to install it
    • Open Safari on the simulator
    • Navigate to any webpage
    • Tap Share → Select "InboxReader"

Project Structure

InboxReader/
├── InboxReader/
│   ├── InboxReaderApp.swift          # App entry point + sidebar
│   ├── Models/
│   │   ├── ReadingItem.swift         # SwiftData model
│   │   └── Schema.swift              # VersionedSchema
│   ├── Views/
│   │   ├── InboxListView.swift       # Inbox list + row + empty state
│   │   └── StatusListView.swift      # Ideas/Reference/Trash views
│   ├── Services/
│   │   ├── ContentExtractor.swift    # Readability wrapper
│   │   └── ContentProcessor.swift    # Background extraction actor
│   └── Shared/
│       └── DataConfiguration.swift   # App Group + ModelContainer
├── ShareExtension/
│   ├── ShareViewController.swift
│   ├── ShareView.swift
│   └── Info.plist
└── README.md

How Content Extraction Works

  1. User shares a URL via Share Extension
  2. Extension saves URL to SwiftData with needsProcessing = true
  3. Main app launches and calls ContentProcessor.processQueue()
  4. ContentProcessor extracts article using swift-readability
  5. Extracted content (title, HTML, text) saved to the ReadingItem
  6. Item displays in Inbox with extracted title

Troubleshooting

Share Extension doesn't appear

  • Make sure both targets have the same App Group
  • Check that the extension's Info.plist has correct NSExtension configuration
  • Clean build folder (Cmd+Shift+K) and rebuild

Data not syncing between app and extension

  • Verify App Group identifier matches exactly in both targets
  • Check that shared files have both targets checked in Target Membership

"Cannot find type 'ReadingItem' in scope" in ShareExtension

  • Add the model files to ShareExtension target membership

"No such module 'Readability'" error

  • Make sure you added the swift-readability local package (Step 2)
  • The package is in Packages/swift-readability - add it via File → Add Package → Add Local...
  • Only the main app target should import Readability, not the extension
  • If using Xcode 15, edit Packages/swift-readability/Package.swift to use Swift 5.9

Content extraction not working

  • Check network connectivity
  • Some sites block automated requests
  • Fallback to basic HTML fetch is attempted if Readability fails

About

A GTD-style iPad reading inbox that turns captured URLs into OmniFocus actions.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages