Skip to content
Merged
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
43 changes: 0 additions & 43 deletions ios/happwn/Core/BackgroundRefresh.swift

This file was deleted.

17 changes: 17 additions & 0 deletions ios/happwn/Core/NotificationService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,27 @@ protocol SubscriptionNotifying {
func notifyChange(subscription: SavedSubscription, added: Int, removed: Int) async
}

/// Lets change notifications appear as a banner even while the app is open
/// (refreshes happen on launch / pull-to-refresh, i.e. in the foreground).
final class NotificationDelegate: NSObject, UNUserNotificationCenterDelegate {
static let shared = NotificationDelegate()

func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.banner, .sound, .list])
}
}

struct NotificationService: SubscriptionNotifying {
/// userInfo key carrying the subscription id (for deep-linking on tap).
static let subscriptionIDKey = "subscriptionID"

/// Show notifications while the app is in the foreground.
func enableForegroundPresentation() {
UNUserNotificationCenter.current().delegate = NotificationDelegate.shared
}

/// Request authorization; returns whether it was granted.
@discardableResult
func requestAuthorization() async -> Bool {
Expand Down
49 changes: 0 additions & 49 deletions ios/happwn/Info.plist

This file was deleted.

21 changes: 0 additions & 21 deletions ios/happwn/Store/Settings.swift
Original file line number Diff line number Diff line change
@@ -1,16 +1,6 @@
import Foundation
import Combine

/// How long the background refresh waits, at minimum, between runs.
/// iOS treats this as a floor, not a guarantee.
enum RefreshInterval: Int, CaseIterable, Identifiable {
case h1 = 1, h3 = 3, h6 = 6, h12 = 12

var id: Int { rawValue }
var seconds: TimeInterval { TimeInterval(rawValue) * 3600 }
var label: String { "\(rawValue) ч" }
}

/// User-editable request identity, appearance, and refresh prefs, persisted in UserDefaults.
final class Settings: ObservableObject {
@Published var userAgent: String {
Expand All @@ -28,12 +18,6 @@ final class Settings: ObservableObject {
@Published var notificationsEnabled: Bool {
didSet { defaults.set(notificationsEnabled, forKey: Keys.notifications) }
}
@Published var backgroundRefreshEnabled: Bool {
didSet { defaults.set(backgroundRefreshEnabled, forKey: Keys.backgroundRefresh) }
}
@Published var minRefreshInterval: RefreshInterval {
didSet { defaults.set(minRefreshInterval.rawValue, forKey: Keys.refreshInterval) }
}

private let defaults: UserDefaults

Expand All @@ -43,8 +27,6 @@ final class Settings: ObservableObject {
static let accent = "happwn.accent"
static let appearance = "happwn.appearance"
static let notifications = "happwn.notificationsEnabled"
static let backgroundRefresh = "happwn.backgroundRefreshEnabled"
static let refreshInterval = "happwn.minRefreshInterval"
}

init(defaults: UserDefaults = .standard) {
Expand All @@ -55,8 +37,5 @@ final class Settings: ObservableObject {
self.appearance = AppAppearance(rawValue: defaults.string(forKey: Keys.appearance) ?? "") ?? .system
// Default ON so the app notifies about config changes (e.g. blocks) out of the box.
self.notificationsEnabled = defaults.object(forKey: Keys.notifications) as? Bool ?? true
self.backgroundRefreshEnabled = defaults.object(forKey: Keys.backgroundRefresh) as? Bool ?? true
let storedInterval = defaults.integer(forKey: Keys.refreshInterval)
self.minRefreshInterval = RefreshInterval(rawValue: storedInterval) ?? .h3
}
}
15 changes: 1 addition & 14 deletions ios/happwn/UI/SettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,23 +37,10 @@ struct SettingsView: View {
Task { await NotificationService().requestAuthorization() }
}
}
Toggle("Фоновое обновление", isOn: $settings.backgroundRefreshEnabled)
.onChange(of: settings.backgroundRefreshEnabled) { enabled in
if enabled {
BackgroundRefresh.schedule(minInterval: settings.minRefreshInterval.seconds)
} else {
BackgroundRefresh.cancel()
}
}
Picker("Проверять не чаще чем", selection: $settings.minRefreshInterval) {
ForEach(RefreshInterval.allCases) { interval in
Text(interval.label).tag(interval)
}
}
} header: {
Text("Обновления")
} footer: {
Text("iOS запускает фоновое обновление по своему усмотрению, ориентируясь на то, как часто ты открываешь приложение — точный интервал не гарантирован.")
Text("Подписки обновляются при открытии приложения и по pull-to-refresh. Если набор конфигов изменился — придёт уведомление.")
}

Section {
Expand Down
21 changes: 3 additions & 18 deletions ios/happwn/happwnApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,9 @@ struct HappwnApp: App {
init() {
let settings = Settings()
let store = SubscriptionStore()
let coordinator = RefreshCoordinator(store: store, settings: settings)
_settings = StateObject(wrappedValue: settings)
_store = StateObject(wrappedValue: store)
_coordinator = StateObject(wrappedValue: coordinator)

BackgroundRefresh.register(
coordinator: { coordinator },
minInterval: { settings.minRefreshInterval.seconds }
)
_coordinator = StateObject(wrappedValue: RefreshCoordinator(store: store, settings: settings))
}

var body: some Scene {
Expand All @@ -30,23 +24,14 @@ struct HappwnApp: App {
.tint(settings.accent.color)
.preferredColorScheme(settings.appearance.colorScheme)
.task {
NotificationService().enableForegroundPresentation()
if settings.notificationsEnabled {
await NotificationService().requestAuthorization()
}
if settings.backgroundRefreshEnabled {
BackgroundRefresh.schedule(minInterval: settings.minRefreshInterval.seconds)
}
}
.onChange(of: scenePhase) { phase in
switch phase {
case .active:
if phase == .active {
Task { await coordinator.refreshAll() }
case .background:
if settings.backgroundRefreshEnabled {
BackgroundRefresh.schedule(minInterval: settings.minRefreshInterval.seconds)
}
default:
break
}
}
}
Expand Down
8 changes: 2 additions & 6 deletions ios/project.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ settings:
GENERATE_INFOPLIST_FILE: YES
INFOPLIST_KEY_UILaunchScreen_Generation: YES
INFOPLIST_KEY_CFBundleDisplayName: happwn
MARKETING_VERSION: "1.0.2"
CURRENT_PROJECT_VERSION: "3"
MARKETING_VERSION: "1.0.3"
CURRENT_PROJECT_VERSION: "4"
SWIFT_VERSION: "5.0"
TARGETED_DEVICE_FAMILY: "1,2"
targets:
Expand All @@ -18,14 +18,10 @@ targets:
platform: iOS
sources:
- path: happwn
excludes:
- "Info.plist"
settings:
base:
PRODUCT_BUNDLE_IDENTIFIER: com.happwn.app
SWIFT_OBJC_BRIDGING_HEADER: happwn/Happwn-Bridging-Header.h
GENERATE_INFOPLIST_FILE: NO
INFOPLIST_FILE: happwn/Info.plist
dependencies:
- framework: HappwnCrypto.xcframework
embed: false
Expand Down
Loading