112 lines
3.9 KiB
Swift
112 lines
3.9 KiB
Swift
// LocalStorageManager.swift
|
|
// Handles local storage of meetings and app data
|
|
|
|
import Foundation
|
|
|
|
/// Manages local file storage for meetings and app data
|
|
class LocalStorageManager {
|
|
static let shared = LocalStorageManager()
|
|
|
|
private let documentsDirectory: URL
|
|
private let meetingsDirectory: URL
|
|
|
|
private init() {
|
|
// Get the app's documents directory
|
|
documentsDirectory = FileManager.default.urls(for: .documentDirectory,
|
|
in: .userDomainMask).first!
|
|
|
|
// Create meetings subdirectory
|
|
meetingsDirectory = documentsDirectory.appendingPathComponent("Meetings")
|
|
|
|
// Ensure directory exists
|
|
try? FileManager.default.createDirectory(at: meetingsDirectory,
|
|
withIntermediateDirectories: true)
|
|
}
|
|
|
|
// MARK: - Meeting Management
|
|
|
|
/// Saves a meeting to local storage
|
|
/// - Parameter meeting: The meeting to save
|
|
/// - Returns: True if successful, false otherwise
|
|
func saveMeeting(_ meeting: Meeting) -> Bool {
|
|
let fileURL = meetingsDirectory.appendingPathComponent("\(meeting.id.uuidString).json")
|
|
|
|
do {
|
|
let encoder = JSONEncoder()
|
|
encoder.outputFormatting = .prettyPrinted
|
|
encoder.dateEncodingStrategy = .iso8601
|
|
|
|
let data = try encoder.encode(meeting)
|
|
try data.write(to: fileURL)
|
|
|
|
print("✅ Saved meeting: \(meeting.id)")
|
|
return true
|
|
} catch {
|
|
print("❌ Failed to save meeting: \(error)")
|
|
return false
|
|
}
|
|
}
|
|
|
|
/// Loads all meetings from local storage
|
|
/// - Returns: Array of meetings, sorted by date (newest first)
|
|
func loadMeetings() -> [Meeting] {
|
|
do {
|
|
let fileURLs = try FileManager.default.contentsOfDirectory(at: meetingsDirectory,
|
|
includingPropertiesForKeys: nil)
|
|
.filter { $0.pathExtension == "json" }
|
|
|
|
let decoder = JSONDecoder()
|
|
decoder.dateDecodingStrategy = .iso8601
|
|
|
|
let meetings = fileURLs.compactMap { url -> Meeting? in
|
|
guard let data = try? Data(contentsOf: url),
|
|
let meeting = try? decoder.decode(Meeting.self, from: data) else {
|
|
print("⚠️ Failed to decode meeting at: \(url)")
|
|
return nil
|
|
}
|
|
return meeting
|
|
}
|
|
|
|
return meetings.sorted { $0.date > $1.date }
|
|
} catch {
|
|
print("❌ Failed to load meetings: \(error)")
|
|
return []
|
|
}
|
|
}
|
|
|
|
/// Deletes a meeting from local storage
|
|
/// - Parameter meeting: The meeting to delete
|
|
/// - Returns: True if successful, false otherwise
|
|
func deleteMeeting(_ meeting: Meeting) -> Bool {
|
|
let fileURL = meetingsDirectory.appendingPathComponent("\(meeting.id.uuidString).json")
|
|
|
|
do {
|
|
try FileManager.default.removeItem(at: fileURL)
|
|
print("✅ Deleted meeting: \(meeting.id)")
|
|
return true
|
|
} catch {
|
|
print("❌ Failed to delete meeting: \(error)")
|
|
return false
|
|
}
|
|
}
|
|
|
|
// MARK: - Settings Management
|
|
|
|
/// Saves non-sensitive settings to local storage
|
|
/// - Parameter settings: The settings to save (sensitive data should use Keychain)
|
|
func saveSettings(_ settings: Settings) -> Bool {
|
|
// For now, all settings are stored in Keychain
|
|
// This method is here for future non-sensitive settings
|
|
return true
|
|
}
|
|
|
|
/// Gets the app's documents directory URL
|
|
var documentsDirectoryURL: URL {
|
|
documentsDirectory
|
|
}
|
|
|
|
/// Gets the meetings directory URL
|
|
var meetingsDirectoryURL: URL {
|
|
meetingsDirectory
|
|
}
|
|
} |