Skip to content

Commit 2dba4ff

Browse files
committed
✨ feat: add automatic widget reload on data changes
Add WidgetReloader dependency to automatically reload widgets when timetable or theme data changes in UserDefaults repositories. This ensures widgets stay in sync with app data without manual refresh.
1 parent c60779c commit 2dba4ff

File tree

4 files changed

+39
-0
lines changed

4 files changed

+39
-0
lines changed

SNUTT/Modules/Feature/Themes/Sources/Infra/ThemeUserDefaultsRepository.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import ThemesInterface
1212

1313
struct ThemeUserDefaultsRepository: ThemeLocalRepository {
1414
@Dependency(\.userDefaults) private var userDefaults
15+
@Dependency(\.widgetReloader) private var widgetReloader
1516

1617
func loadAvailableThemes() -> [Theme] {
1718
guard let data = userDefaults.data(forKey: Keys.availableThemes.rawValue),
@@ -23,6 +24,7 @@ struct ThemeUserDefaultsRepository: ThemeLocalRepository {
2324
func storeAvailableThemes(_ themes: [Theme]) {
2425
guard let data = try? JSONEncoder().encode(themes) else { return }
2526
userDefaults.set(data, forKey: Keys.availableThemes.rawValue)
27+
widgetReloader.reloadAll()
2628
}
2729

2830
private enum Keys: String {

SNUTT/Modules/Feature/Timetable/Sources/Infra/TimetableUserDefaultsRepository.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import TimetableUIComponents
1313

1414
struct TimetableUserDefaultsRepository: TimetableLocalRepository {
1515
@Dependency(\.userDefaults) private var userDefaults
16+
@Dependency(\.widgetReloader) private var widgetReloader
1617

1718
func loadSelectedTimetable() throws -> Timetable {
1819
try userDefaults.object(forKey: Keys.currentTimetable.rawValue, type: Timetable.self)
@@ -21,6 +22,7 @@ struct TimetableUserDefaultsRepository: TimetableLocalRepository {
2122
func storeSelectedTimetable(_ timetable: Timetable) throws {
2223
let data = try JSONEncoder().encode(timetable)
2324
userDefaults.set(data, forKey: Keys.currentTimetable.rawValue)
25+
widgetReloader.reloadAll()
2426
}
2527

2628
func loadTimetableConfiguration() -> TimetableConfiguration {
@@ -29,6 +31,7 @@ struct TimetableUserDefaultsRepository: TimetableLocalRepository {
2931

3032
func storeTimetableConfiguration(_ configuration: TimetableConfiguration) {
3133
userDefaults[\.timetableConfiguration] = configuration
34+
widgetReloader.reloadAll()
3235
}
3336

3437
func configurationValues() -> AsyncStream<TimetableConfiguration> {
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//
2+
// WidgetReloaderDependency.swift
3+
// SNUTT
4+
//
5+
// Copyright © 2026 wafflestudio.com. All rights reserved.
6+
//
7+
8+
import Dependencies
9+
import WidgetKit
10+
11+
public struct WidgetReloader: Sendable {
12+
public let reloadAll: @Sendable () -> Void
13+
14+
public init(reloadAll: @escaping @Sendable () -> Void) {
15+
self.reloadAll = reloadAll
16+
}
17+
}
18+
19+
public enum WidgetReloaderKey: DependencyKey {
20+
public static let liveValue: WidgetReloader = .init(
21+
reloadAll: { WidgetCenter.shared.reloadAllTimelines() }
22+
)
23+
24+
public static let testValue: WidgetReloader = .init(reloadAll: {})
25+
}
26+
27+
extension DependencyValues {
28+
public var widgetReloader: WidgetReloader {
29+
get { self[WidgetReloaderKey.self] }
30+
set { self[WidgetReloaderKey.self] = newValue }
31+
}
32+
}

SNUTT/Project.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ let project = Project.app(
2323
.target(name: "SwiftUIUtility"),
2424
.target(name: "SwiftUtility"),
2525
.target(name: "FoundationUtility"),
26+
.target(name: "DependenciesUtility"),
2627
.target(name: "SharedUIComponents"),
2728
.target(name: "SharedUIMapKit"),
2829
.external(name: "Dependencies"),
@@ -337,6 +338,7 @@ let project = Project.app(
337338
dependencies: [
338339
.external(name: "Dependencies"),
339340
.external(name: "DependenciesAdditions"),
341+
.sdk(name: "WidgetKit", type: .framework),
340342
]
341343
),
342344
.module(

0 commit comments

Comments
 (0)