Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Ruddarr.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@
BB8100092CD5976B00499666 /* radarr-history.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "radarr-history.json"; sourceTree = "<group>"; };
BB83AFA42CB2080C00349997 /* InstanceCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceCommand.swift; sourceTree = "<group>"; };
BB846F2E2E7DE1BC00E0A367 /* NotificationService.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NotificationService.entitlements; sourceTree = "<group>"; };
CC5E00012F5A000100000020 /* ShareExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ShareExtension.entitlements; sourceTree = "<group>"; };
BB865E602B83C11E00ADCEFE /* Error.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Error.swift; sourceTree = "<group>"; };
BB89058A2E41359E0057C62B /* SeasonCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeasonCard.swift; sourceTree = "<group>"; };
BB89ABC52B756B91009FB62D /* MovieReleaseRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MovieReleaseRow.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -645,6 +646,7 @@
CC5E00012F5A000100000004 /* ShareExtension */ = {
isa = PBXGroup;
children = (
CC5E00012F5A000100000020 /* ShareExtension.entitlements */,
CC5E00012F5A000100000003 /* Info.plist */,
CC5E00012F5A000100000002 /* ShareViewController.swift */,
CC5E00012F5A000100000012 /* ShareURLHandler.swift */,
Expand Down Expand Up @@ -1616,6 +1618,7 @@
CC5E00012F5A00010000000D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
Expand Down Expand Up @@ -1652,6 +1655,7 @@
CC5E00012F5A00010000000E /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
Expand Down
4 changes: 4 additions & 0 deletions Ruddarr/Ruddarr.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,9 @@
</array>
<key>com.apple.developer.ubiquity-kvstore-identifier</key>
<string>$(TeamIdentifierPrefix)$(CFBundleIdentifier)</string>
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.ruddarr</string>
</array>
</dict>
</plist>
22 changes: 22 additions & 0 deletions Ruddarr/Services/AppSettings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,20 @@ class AppSettings: ObservableObject {
@CloudStorage("instances") var instances: [Instance] = []
#endif

init() {
NotificationCenter.default.addObserver(
forName: NSUbiquitousKeyValueStore.didChangeExternallyNotification,
object: NSUbiquitousKeyValueStore.default,
queue: .main
) { [weak self] notification in
guard let keys = notification.userInfo?[NSUbiquitousKeyValueStoreChangedKeysKey] as? [String],
keys.contains("instances") else { return }
Task { @MainActor [weak self] in
self?.syncInstancesToAppGroup()
}
}
}

@AppStorage("icon", store: dependencies.store) var icon: AppIcon = .factory
@AppStorage("theme", store: dependencies.store) var theme: Theme = .factory
@AppStorage("appearance", store: dependencies.store) var appearance: Appearance = .automatic
Expand Down Expand Up @@ -77,6 +91,7 @@ extension AppSettings {
}

Queue.shared.instances = instances
syncInstancesToAppGroup()
}

func deleteInstance(_ instance: Instance) {
Expand All @@ -95,6 +110,13 @@ extension AppSettings {
}

Queue.shared.instances = instances
syncInstancesToAppGroup()
}

func syncInstancesToAppGroup() {
guard let data = try? JSONEncoder().encode(instances),
let defaults = UserDefaults(suiteName: "group.com.ruddarr") else { return }
defaults.set(data, forKey: "instances")
}
}

Expand Down
1 change: 1 addition & 0 deletions Ruddarr/Utilities/View.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ private struct WithAppStateModifier: ViewModifier {
.environment(SonarrInstance(sonarrInstance))
.task {
Queue.shared.instances = settings.instances
settings.syncInstancesToAppGroup()
setSentryContext(for: "Configuration", settings.context())
await setSentryCloudKitContext()
}
Expand Down
2 changes: 1 addition & 1 deletion ShareExtension/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ in the main app (`RadarrInstance`/`SonarrInstance`, `AppSettings`,

## TODOs

- [ ] Sync instances to App Groups shared container from the main app
- [x] Sync instances to App Groups shared container from the main app
- [x] Replace `AsyncImage` with NukeUI `LazyImage` (add Nuke dependency to extension target)
- [ ] Deduplicate models/views by extracting shared code into a framework or Swift package
- [x] Handle case when no instances are configured (show setup instructions)
Expand Down
10 changes: 10 additions & 0 deletions ShareExtension/ShareExtension.entitlements
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?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.security.application-groups</key>
<array>
<string>group.com.ruddarr</string>
</array>
</dict>
</plist>
Loading