Skip to content

Commit 0886311

Browse files
authored
Fix sideload install: drop background task / UIBackgroundModes (#4)
Feather failed with 'Unable to Install' (stuck at sending payload). The only bundle difference from the last installable build (v1.0.7) was the background-fetch capability (UIBackgroundModes + BGTaskSchedulerPermittedIdentifiers), which sideload profiles (free cert) reject. - Remove BackgroundRefresh (BGAppRefreshTask) and the background-mode Info.plist keys. - Revert to the generated Info.plist (GENERATE_INFOPLIST_FILE) as in v1.0.7 — no manual plist. - Subscriptions now refresh on app launch / scenePhase active and pull-to-refresh; change notifications still fire and are shown in the foreground via UNUserNotificationCenterDelegate. - Drop the background-refresh toggle and interval from Settings. - Bump to 1.0.3 (build 4). Co-authored-by: useruserdev <256019073+useruserdev@users.noreply.github.com>
1 parent 77ff0fe commit 0886311

7 files changed

Lines changed: 23 additions & 151 deletions

File tree

ios/happwn/Core/BackgroundRefresh.swift

Lines changed: 0 additions & 43 deletions
This file was deleted.

ios/happwn/Core/NotificationService.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,27 @@ protocol SubscriptionNotifying {
77
func notifyChange(subscription: SavedSubscription, added: Int, removed: Int) async
88
}
99

10+
/// Lets change notifications appear as a banner even while the app is open
11+
/// (refreshes happen on launch / pull-to-refresh, i.e. in the foreground).
12+
final class NotificationDelegate: NSObject, UNUserNotificationCenterDelegate {
13+
static let shared = NotificationDelegate()
14+
15+
func userNotificationCenter(_ center: UNUserNotificationCenter,
16+
willPresent notification: UNNotification,
17+
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
18+
completionHandler([.banner, .sound, .list])
19+
}
20+
}
21+
1022
struct NotificationService: SubscriptionNotifying {
1123
/// userInfo key carrying the subscription id (for deep-linking on tap).
1224
static let subscriptionIDKey = "subscriptionID"
1325

26+
/// Show notifications while the app is in the foreground.
27+
func enableForegroundPresentation() {
28+
UNUserNotificationCenter.current().delegate = NotificationDelegate.shared
29+
}
30+
1431
/// Request authorization; returns whether it was granted.
1532
@discardableResult
1633
func requestAuthorization() async -> Bool {

ios/happwn/Info.plist

Lines changed: 0 additions & 49 deletions
This file was deleted.

ios/happwn/Store/Settings.swift

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,6 @@
11
import Foundation
22
import Combine
33

4-
/// How long the background refresh waits, at minimum, between runs.
5-
/// iOS treats this as a floor, not a guarantee.
6-
enum RefreshInterval: Int, CaseIterable, Identifiable {
7-
case h1 = 1, h3 = 3, h6 = 6, h12 = 12
8-
9-
var id: Int { rawValue }
10-
var seconds: TimeInterval { TimeInterval(rawValue) * 3600 }
11-
var label: String { "\(rawValue) ч" }
12-
}
13-
144
/// User-editable request identity, appearance, and refresh prefs, persisted in UserDefaults.
155
final class Settings: ObservableObject {
166
@Published var userAgent: String {
@@ -28,12 +18,6 @@ final class Settings: ObservableObject {
2818
@Published var notificationsEnabled: Bool {
2919
didSet { defaults.set(notificationsEnabled, forKey: Keys.notifications) }
3020
}
31-
@Published var backgroundRefreshEnabled: Bool {
32-
didSet { defaults.set(backgroundRefreshEnabled, forKey: Keys.backgroundRefresh) }
33-
}
34-
@Published var minRefreshInterval: RefreshInterval {
35-
didSet { defaults.set(minRefreshInterval.rawValue, forKey: Keys.refreshInterval) }
36-
}
3721

3822
private let defaults: UserDefaults
3923

@@ -43,8 +27,6 @@ final class Settings: ObservableObject {
4327
static let accent = "happwn.accent"
4428
static let appearance = "happwn.appearance"
4529
static let notifications = "happwn.notificationsEnabled"
46-
static let backgroundRefresh = "happwn.backgroundRefreshEnabled"
47-
static let refreshInterval = "happwn.minRefreshInterval"
4830
}
4931

5032
init(defaults: UserDefaults = .standard) {
@@ -55,8 +37,5 @@ final class Settings: ObservableObject {
5537
self.appearance = AppAppearance(rawValue: defaults.string(forKey: Keys.appearance) ?? "") ?? .system
5638
// Default ON so the app notifies about config changes (e.g. blocks) out of the box.
5739
self.notificationsEnabled = defaults.object(forKey: Keys.notifications) as? Bool ?? true
58-
self.backgroundRefreshEnabled = defaults.object(forKey: Keys.backgroundRefresh) as? Bool ?? true
59-
let storedInterval = defaults.integer(forKey: Keys.refreshInterval)
60-
self.minRefreshInterval = RefreshInterval(rawValue: storedInterval) ?? .h3
6140
}
6241
}

ios/happwn/UI/SettingsView.swift

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,23 +37,10 @@ struct SettingsView: View {
3737
Task { await NotificationService().requestAuthorization() }
3838
}
3939
}
40-
Toggle("Фоновое обновление", isOn: $settings.backgroundRefreshEnabled)
41-
.onChange(of: settings.backgroundRefreshEnabled) { enabled in
42-
if enabled {
43-
BackgroundRefresh.schedule(minInterval: settings.minRefreshInterval.seconds)
44-
} else {
45-
BackgroundRefresh.cancel()
46-
}
47-
}
48-
Picker("Проверять не чаще чем", selection: $settings.minRefreshInterval) {
49-
ForEach(RefreshInterval.allCases) { interval in
50-
Text(interval.label).tag(interval)
51-
}
52-
}
5340
} header: {
5441
Text("Обновления")
5542
} footer: {
56-
Text("iOS запускает фоновое обновление по своему усмотрению, ориентируясь на то, как часто ты открываешь приложение — точный интервал не гарантирован.")
43+
Text("Подписки обновляются при открытии приложения и по pull-to-refresh. Если набор конфигов изменился — придёт уведомление.")
5744
}
5845

5946
Section {

ios/happwn/happwnApp.swift

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,9 @@ struct HappwnApp: App {
1010
init() {
1111
let settings = Settings()
1212
let store = SubscriptionStore()
13-
let coordinator = RefreshCoordinator(store: store, settings: settings)
1413
_settings = StateObject(wrappedValue: settings)
1514
_store = StateObject(wrappedValue: store)
16-
_coordinator = StateObject(wrappedValue: coordinator)
17-
18-
BackgroundRefresh.register(
19-
coordinator: { coordinator },
20-
minInterval: { settings.minRefreshInterval.seconds }
21-
)
15+
_coordinator = StateObject(wrappedValue: RefreshCoordinator(store: store, settings: settings))
2216
}
2317

2418
var body: some Scene {
@@ -30,23 +24,14 @@ struct HappwnApp: App {
3024
.tint(settings.accent.color)
3125
.preferredColorScheme(settings.appearance.colorScheme)
3226
.task {
27+
NotificationService().enableForegroundPresentation()
3328
if settings.notificationsEnabled {
3429
await NotificationService().requestAuthorization()
3530
}
36-
if settings.backgroundRefreshEnabled {
37-
BackgroundRefresh.schedule(minInterval: settings.minRefreshInterval.seconds)
38-
}
3931
}
4032
.onChange(of: scenePhase) { phase in
41-
switch phase {
42-
case .active:
33+
if phase == .active {
4334
Task { await coordinator.refreshAll() }
44-
case .background:
45-
if settings.backgroundRefreshEnabled {
46-
BackgroundRefresh.schedule(minInterval: settings.minRefreshInterval.seconds)
47-
}
48-
default:
49-
break
5035
}
5136
}
5237
}

ios/project.yml

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ settings:
88
GENERATE_INFOPLIST_FILE: YES
99
INFOPLIST_KEY_UILaunchScreen_Generation: YES
1010
INFOPLIST_KEY_CFBundleDisplayName: happwn
11-
MARKETING_VERSION: "1.0.2"
12-
CURRENT_PROJECT_VERSION: "3"
11+
MARKETING_VERSION: "1.0.3"
12+
CURRENT_PROJECT_VERSION: "4"
1313
SWIFT_VERSION: "5.0"
1414
TARGETED_DEVICE_FAMILY: "1,2"
1515
targets:
@@ -18,14 +18,10 @@ targets:
1818
platform: iOS
1919
sources:
2020
- path: happwn
21-
excludes:
22-
- "Info.plist"
2321
settings:
2422
base:
2523
PRODUCT_BUNDLE_IDENTIFIER: com.happwn.app
2624
SWIFT_OBJC_BRIDGING_HEADER: happwn/Happwn-Bridging-Header.h
27-
GENERATE_INFOPLIST_FILE: NO
28-
INFOPLIST_FILE: happwn/Info.plist
2925
dependencies:
3026
- framework: HappwnCrypto.xcframework
3127
embed: false

0 commit comments

Comments
 (0)