Initial commit

Whisper model weights excluded from git — auto-downloaded at first Xcode
build via Scripts/download_whisper_model.sh (~600 MB, one-time).
This commit is contained in:
2026-04-01 15:52:27 -05:00
commit cc353e37ae
62 changed files with 6968 additions and 0 deletions

View File

@@ -0,0 +1,61 @@
//
// DeviceActivityMonitorExtension.swift
// LockInBroMonitor
//
// When a distraction-app usage event exceeds the user's threshold,
// this extension applies a ManagedSettings shield so the app shows
// a "get back to work" overlay. Shields are cleared when the focus
// session schedule ends or the main app calls stopMonitoring().
//
import DeviceActivity
import FamilyControls
import Foundation
import ManagedSettings
class DeviceActivityMonitorExtension: DeviceActivityMonitor {
private let store = ManagedSettingsStore(named: .lockinbro)
private let defaults = UserDefaults(suiteName: "group.com.adipu.LockInBroMobile")
// MARK: - Threshold Reached
override func eventDidReachThreshold(_ event: DeviceActivityEvent.Name, activity: DeviceActivityName) {
super.eventDidReachThreshold(event, activity: activity)
// Load the user's selected distraction apps from the shared App Group
guard let data = defaults?.data(forKey: "screenTimeSelection"),
let selection = try? JSONDecoder().decode(FamilyActivitySelection.self, from: data) else {
return
}
// Apply shield to all selected apps once ANY threshold fires, shield them all.
// This is simpler and gives the user a single nudge rather than per-app shields
// trickling in one-by-one.
store.shield.applications = selection.applicationTokens.isEmpty ? nil : selection.applicationTokens
store.shield.applicationCategories = selection.categoryTokens.isEmpty
? nil
: ShieldSettings.ActivityCategoryPolicy.specific(selection.categoryTokens)
}
// MARK: - Schedule Lifecycle
override func intervalDidStart(for activity: DeviceActivityName) {
super.intervalDidStart(for: activity)
// Ensure shields are clear at the start of each monitoring interval
store.shield.applications = nil
store.shield.applicationCategories = nil
}
override func intervalDidEnd(for activity: DeviceActivityName) {
super.intervalDidEnd(for: activity)
// Clean up shields when the schedule interval ends
store.shield.applications = nil
store.shield.applicationCategories = nil
}
}
// Mirror the named store constant from the main app
extension ManagedSettingsStore.Name {
static let lockinbro = ManagedSettingsStore.Name("lockinbro")
}

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.deviceactivity.monitor-extension</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).DeviceActivityMonitorExtension</string>
</dict>
</dict>
</plist>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.family-controls</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.adipu.LockInBroMobile</string>
</array>
</dict>
</plist>