Skip to content

Commit 0636e17

Browse files
committed
refactor: centralize app group, endpoints, and key constants
1 parent 17ee351 commit 0636e17

File tree

11 files changed

+39
-23
lines changed

11 files changed

+39
-23
lines changed

app/CoursesWidget/CoursesWidget.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import os
1111

1212
struct Provider: TimelineProvider {
1313
private static let logger = Logger(
14-
subsystem: "group.cantpr09ram.dauphin", category: "CoursesWidget")
14+
subsystem: Constants.loggerSubsystem, category: "CoursesWidget")
1515

1616
// MARK: - Placeholder
1717

@@ -64,7 +64,7 @@ struct Provider: TimelineProvider {
6464
// MARK: - Helpers
6565

6666
private func getSsoStuNo() -> String? {
67-
guard let defaults = UserDefaults(suiteName: "group.cantpr09ram.dauphin") else {
67+
guard let defaults = UserDefaults(suiteName: Constants.appGroupSuiteName) else {
6868
Provider.logger.error("App Group defaults unavailable.")
6969
return nil
7070
}
@@ -79,7 +79,7 @@ struct Provider: TimelineProvider {
7979
}
8080

8181
private func loadCoursesFromCache() -> [Course]? {
82-
guard let defaults = UserDefaults(suiteName: "group.cantpr09ram.dauphin") else {
82+
guard let defaults = UserDefaults(suiteName: Constants.appGroupSuiteName) else {
8383
Provider.logger.error("App Group defaults unavailable.")
8484
return nil
8585
}

app/StdID/StdID.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ struct SimpleEntry: TimelineEntry {
99
}
1010

1111
struct Provider: TimelineProvider {
12-
private static let logger = Logger(subsystem: "group.cantpr09ram.dauphin", category: "StdID")
12+
private static let logger = Logger(subsystem: Constants.loggerSubsystem, category: "StdID")
1313
func placeholder(in _: Context) -> SimpleEntry { SimpleEntry(date: .now, ssoStuNo: "") }
1414

1515
func getSnapshot(in _: Context, completion: @escaping (SimpleEntry) -> Void) {
@@ -29,7 +29,7 @@ struct Provider: TimelineProvider {
2929
}
3030

3131
private func fetchSsoStuNo() -> String {
32-
let defaults = UserDefaults(suiteName: "group.cantpr09ram.dauphin")
32+
let defaults = UserDefaults(suiteName: Constants.appGroupSuiteName)
3333
defaults?.synchronize()
3434
guard let value = defaults?.string(forKey: Constants.ssoTokenKey) else {
3535
Provider.logger.info("ssoStuNo not found, returning default value.")

app/Tests/ModelsTests/WidgetCacheDecodeTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import Testing
77
@Test("widget-style decoder reads cache payload") func widgetStyleDecoderReadsCachePayload()
88
throws
99
{
10-
let suiteName = "group.cantpr09ram.dauphin.tests.\(UUID().uuidString)"
10+
let suiteName = "\(Constants.appGroupSuiteName).tests.\(UUID().uuidString)"
1111
let key = "courses"
1212

1313
let cache = DefaultsCourseCache(suiteName: suiteName, key: key)

app/dauphin/Utilities/Constants.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,25 @@
55
// Created by \u8b19 on 11/17/24.
66
//
77

8+
import Foundation
9+
810
enum Constants {
11+
static let loggerSubsystem = "group.cantpr09ram.dauphin"
12+
static let appGroupSuiteName = "group.cantpr09ram.dauphin"
13+
914
static let ssoTokenKey = "ssoStuNo"
1015
static let isLoggedInKey = "isLoggedIn"
1116
static let loginSuccessNotification = "LoginSuccess"
1217
static let courses = "Courses"
18+
19+
static let keychainAESKey = "AES256KEY"
20+
static let keychainAESIV = "AES256IV"
21+
22+
static let courseAPIEndpoint = "https://ilifeapi.az.tku.edu.tw/api/ilifeStuClassApi"
23+
static let eventXMLAPIEndpoint = "https://ilifeapi.az.tku.edu.tw/data/xml_cal.ashx"
24+
static let ssoLoginURL = "https://sso.tku.edu.tw/ilife/CoWork/AndroidSsoLogin.cshtml"
25+
}
26+
27+
extension Notification.Name {
28+
static let loginSuccess = Notification.Name(Constants.loginSuccessNotification)
1329
}

app/dauphin/Utilities/Courses/CourseAPIClient.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ protocol CourseAPIClient { func fetchCoursesData(encryptedQuery: String) async t
44

55
struct DefaultCourseAPIClient: CourseAPIClient {
66
func fetchCoursesData(encryptedQuery: String) async throws -> Data {
7-
var comps = URLComponents(string: "https://ilifeapi.az.tku.edu.tw/api/ilifeStuClassApi")!
7+
var comps = URLComponents(string: Constants.courseAPIEndpoint)!
88
comps.queryItems = [URLQueryItem(name: "q", value: encryptedQuery)]
99
guard let url = comps.url else { throw URLError(.badURL) }
1010
let (data, resp) = try await URLSession.shared.data(from: url)

app/dauphin/Utilities/Key/KeyConstants.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ import OSLog
33

44
enum KeyConstants {
55
private static let logger = Logger(
6-
subsystem: "group.cantpr09ram.dauphin", category: "KeyConstants")
6+
subsystem: Constants.loggerSubsystem, category: "KeyConstants")
77

88
static func loadAPIKeys() async throws {
9-
if let key = KeychainManager.shared.get(forKey: "AES256KEY"),
10-
let iv = KeychainManager.shared.get(forKey: "AES256IV"),
9+
if let key = KeychainManager.shared.get(forKey: Constants.keychainAESKey),
10+
let iv = KeychainManager.shared.get(forKey: Constants.keychainAESIV),
1111
!key.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty,
1212
!iv.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
1313
{
@@ -43,8 +43,8 @@ enum KeyConstants {
4343
userInfo: [NSLocalizedDescriptionKey: "AES key or IV is empty."])
4444
}
4545

46-
KeychainManager.shared.save(key, forKey: "AES256KEY")
47-
KeychainManager.shared.save(iv, forKey: "AES256IV")
46+
KeychainManager.shared.save(key, forKey: Constants.keychainAESKey)
47+
KeychainManager.shared.save(iv, forKey: Constants.keychainAESIV)
4848
logger.info("API keys successfully saved to Keychain")
4949
} catch {
5050
logger.error("Failed to load or decode 'api.plist': \(error.localizedDescription)")

app/dauphin/View/LibSSoLoginView.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import WebKit
44

55
struct LibSSOLoginView: UIViewRepresentable {
66
private static let logger = Logger(
7-
subsystem: "group.cantpr09ram.dauphin", category: "LibSSOLogin")
7+
subsystem: Constants.loggerSubsystem, category: "LibSSOLogin")
88
@ObservedObject var viewModel: AuthViewModel
99

1010
class Coordinator: NSObject, WKNavigationDelegate, WKScriptMessageHandler {
@@ -94,7 +94,7 @@ struct LibSSOLoginView: UIViewRepresentable {
9494
let webView = WKWebView(frame: .zero, configuration: config)
9595
webView.navigationDelegate = context.coordinator
9696

97-
if let url = URL(string: "https://sso.tku.edu.tw/ilife/CoWork/AndroidSsoLogin.cshtml") {
97+
if let url = URL(string: Constants.ssoLoginURL) {
9898
let request = URLRequest(url: url)
9999
webView.load(request)
100100
}

app/dauphin/ViewModels/AuthViewModel.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import os
66

77
@MainActor final class AuthViewModel: ObservableObject {
88
private static let logger = Logger(
9-
subsystem: "group.cantpr09ram.dauphin", category: "AuthViewModel")
10-
private let appGroupDefaults = UserDefaults(suiteName: "group.cantpr09ram.dauphin")
9+
subsystem: Constants.loggerSubsystem, category: "AuthViewModel")
10+
private let appGroupDefaults = UserDefaults(suiteName: Constants.appGroupSuiteName)
1111

1212
@Published var isLoggedIn: Bool {
1313
didSet { appGroupDefaults?.set(isLoggedIn, forKey: Constants.isLoggedInKey) }

app/dauphin/ViewModels/CourseViewModel.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import SwiftUI
66
@MainActor final class CourseViewModel: ObservableObject {
77

88
private static let logger = Logger(
9-
subsystem: "group.cantpr09ram.dauphin", category: "CourseViewModel")
9+
subsystem: Constants.loggerSubsystem, category: "CourseViewModel")
1010

1111
// 對外狀態:維持不變
1212
@Published var weekCourses: [Course] = []
@@ -36,7 +36,7 @@ import SwiftUI
3636
) {
3737
// Cache 與 Parser 預設注入
3838
let cache = DefaultsCourseCache(
39-
suiteName: "group.cantpr09ram.dauphin", key: Constants.courses)
39+
suiteName: Constants.appGroupSuiteName, key: Constants.courses)
4040
let parser = DefaultCourseParser(
4141
htmlStrip: { text in
4242
text.replacingOccurrences(of: "<[^>]+>", with: "", options: .regularExpression)
@@ -47,8 +47,8 @@ import SwiftUI
4747

4848
if let enc = encryptor {
4949
self.encryptor = enc
50-
} else if let key = KeychainManager.shared.get(forKey: "AES256KEY"),
51-
let iv = KeychainManager.shared.get(forKey: "AES256IV")
50+
} else if let key = KeychainManager.shared.get(forKey: Constants.keychainAESKey),
51+
let iv = KeychainManager.shared.get(forKey: Constants.keychainAESIV)
5252
{
5353
let helper = CustomAES256Helper(key: key, iv: iv)
5454
self.encryptor = { helper.encrypt(data: $0) }

app/dauphin/ViewModels/EventViewModel.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ import OSLog
33

44
@MainActor final class EventViewModel: ObservableObject {
55
private static let logger = Logger(
6-
subsystem: "group.cantpr09ram.dauphin", category: "EventViewModel")
6+
subsystem: Constants.loggerSubsystem, category: "EventViewModel")
77
@Published private(set) var events: [CalendarEvent] = []
88

99
func loadXMLData(withQuery query: [String: String]) async {
10-
var components = URLComponents(string: "https://ilifeapi.az.tku.edu.tw/data/xml_cal.ashx")
10+
var components = URLComponents(string: Constants.eventXMLAPIEndpoint)
1111
components?.queryItems = query.map { URLQueryItem(name: $0.key, value: $0.value) }
1212

1313
guard let url = components?.url else {

0 commit comments

Comments
 (0)