feat: actually implement system audio + refactor
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
// 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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user