Add persistent storage
This commit is contained in:
parent
232d007686
commit
d218e9b600
@ -10,7 +10,9 @@ import CoreBluetooth
|
|||||||
|
|
||||||
struct ContentView: View {
|
struct ContentView: View {
|
||||||
@State var currentView = 0
|
@State var currentView = 0
|
||||||
@StateObject var dataStore = DataStore()
|
@EnvironmentObject var dataStore: DataStore
|
||||||
|
@Environment(\.scenePhase) private var scenePhase
|
||||||
|
let saveAction: ()->Void
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
VStack {
|
||||||
@ -61,14 +63,16 @@ struct ContentView: View {
|
|||||||
}
|
}
|
||||||
.frame(height: UIScreen.main.bounds.height * 0.05)
|
.frame(height: UIScreen.main.bounds.height * 0.05)
|
||||||
}
|
}
|
||||||
|
.onChange(of: scenePhase) { phase in
|
||||||
|
if phase == .inactive { saveAction() }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ContentView_Previews: PreviewProvider {
|
struct ContentView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
ContentView()
|
ContentView(saveAction: {})
|
||||||
.environmentObject(DataStore())
|
.environmentObject(DataStore())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,16 +8,93 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
@MainActor
|
||||||
class DataStore: ObservableObject {
|
class DataStore: ObservableObject {
|
||||||
@Published var personalID: String
|
@Published var personalID: String
|
||||||
@Published var friends: [String]
|
@Published var friends: [String:Int]
|
||||||
@Published var feeds: [Feed]
|
@Published var feedStores: [FeedStore]
|
||||||
|
|
||||||
init(personalID: String = "", friends: [String] = [], feeds: [Feed] = []) {
|
init(personalID: String = "", friends: [String:Int] = [:], feedStores: [FeedStore] = []) {
|
||||||
self.personalID = personalID
|
self.personalID = personalID
|
||||||
self.friends = friends
|
self.friends = friends
|
||||||
self.feeds = feeds
|
self.feedStores = feedStores
|
||||||
|
}
|
||||||
|
|
||||||
|
private func fileURL(for filename: String) throws -> URL {
|
||||||
|
try FileManager.default.url(for: .documentDirectory,
|
||||||
|
in: .userDomainMask,
|
||||||
|
appropriateFor: nil,
|
||||||
|
create: false)
|
||||||
|
.appendingPathComponent("\(filename).json")
|
||||||
|
}
|
||||||
|
|
||||||
|
func savePersonalID() async throws {
|
||||||
|
let task = Task {
|
||||||
|
let data = try JSONEncoder().encode(personalID)
|
||||||
|
let outfile = try fileURL(for: "personalID")
|
||||||
|
try data.write(to: outfile)
|
||||||
|
}
|
||||||
|
_ = try await task.value
|
||||||
|
}
|
||||||
|
|
||||||
|
func saveFriends() async throws {
|
||||||
|
let task = Task {
|
||||||
|
let data = try JSONEncoder().encode(friends)
|
||||||
|
let outfile = try fileURL(for: "friends")
|
||||||
|
try data.write(to: outfile)
|
||||||
|
}
|
||||||
|
_ = try await task.value
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadPersonalID() async throws {
|
||||||
|
let task = Task<String, Error> {
|
||||||
|
let fileURL = try self.fileURL(for: "personalID")
|
||||||
|
let data = try Data(contentsOf: fileURL)
|
||||||
|
let personalID = try JSONDecoder().decode(String.self, from: data)
|
||||||
|
return personalID
|
||||||
|
}
|
||||||
|
let personalID = try await task.value
|
||||||
|
self.personalID = personalID
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadFriends() async throws {
|
||||||
|
let task = Task<[String:Int], Error> {
|
||||||
|
let fileURL = try self.fileURL(for: "friends")
|
||||||
|
let data = try Data(contentsOf: fileURL)
|
||||||
|
let friends = try JSONDecoder().decode([String:Int].self, from: data)
|
||||||
|
return friends
|
||||||
|
}
|
||||||
|
let friends = try await task.value
|
||||||
|
self.friends = friends
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadFeedStores() async throws {
|
||||||
|
let task = Task<[FeedStore], Error> {
|
||||||
|
var feedStores: [FeedStore] = []
|
||||||
|
for feedStore in self.feedStores {
|
||||||
|
try await feedStore.load()
|
||||||
|
feedStores.append(feedStore)
|
||||||
|
}
|
||||||
|
return feedStores
|
||||||
|
}
|
||||||
|
let feedStores = try await task.value
|
||||||
|
self.feedStores = feedStores
|
||||||
|
}
|
||||||
|
|
||||||
|
func saveFeedStores() async throws {
|
||||||
|
let task = Task {
|
||||||
|
for feedStore in self.feedStores {
|
||||||
|
try await feedStore.save(feed: feedStore.feed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ = try await task.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extension DataStore {
|
||||||
|
static let sampleDataStore = DataStore(personalID: "BOB", friends: SettingsView_Previews.friends, feedStores: [FeedStore(feed: Feed.sampleFeed), FeedStore(feed: Feed.sampleFeed2)])
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,10 +9,33 @@ import SwiftUI
|
|||||||
|
|
||||||
@main
|
@main
|
||||||
struct RippleChatApp: App {
|
struct RippleChatApp: App {
|
||||||
|
@StateObject private var dataStore = DataStore()
|
||||||
var body: some Scene {
|
var body: some Scene {
|
||||||
WindowGroup {
|
WindowGroup {
|
||||||
ContentView()
|
ContentView() {
|
||||||
|
Task {
|
||||||
|
do {
|
||||||
|
try await dataStore.savePersonalID()
|
||||||
|
try await dataStore.saveFriends()
|
||||||
|
try await dataStore.saveFeedStores()
|
||||||
|
} catch {
|
||||||
|
fatalError(error.localizedDescription)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.environmentObject(dataStore)
|
||||||
|
.task {
|
||||||
|
do {
|
||||||
|
try await dataStore.loadPersonalID()
|
||||||
|
try await dataStore.loadFriends()
|
||||||
|
try await dataStore.loadFeedStores()
|
||||||
|
} catch {
|
||||||
|
// Handle the error
|
||||||
|
print("Error loading data: \(error)")
|
||||||
|
fatalError(error.localizedDescription)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,9 +22,9 @@ struct FeedListView: View {
|
|||||||
Button("Save Feed") {
|
Button("Save Feed") {
|
||||||
Task {
|
Task {
|
||||||
do {
|
do {
|
||||||
for feed in feedStores {
|
try await DataStore.sampleDataStore.saveFriends()
|
||||||
try await feed.save(feed: feed.feed)
|
try await DataStore.sampleDataStore.savePersonalID()
|
||||||
}
|
try await DataStore.sampleDataStore.saveFeedStores()
|
||||||
} catch {
|
} catch {
|
||||||
fatalError(error.localizedDescription)
|
fatalError(error.localizedDescription)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,18 +20,24 @@ struct SettingsEditView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Section(header: Text("Friends")) {
|
Section(header: Text("Friends")) {
|
||||||
ForEach(dataStore.friends) { friend in
|
ForEach(dataStore.friends.keys.sorted(), id: \.self) { friend in
|
||||||
Label(friend, systemImage: "person")
|
if let seq = dataStore.friends[friend] {
|
||||||
|
Label("\(friend) - SEQ: \(seq)", systemImage: "person")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onDelete { indexSet in do {
|
||||||
|
indexSet.forEach { index in
|
||||||
|
let key = dataStore.friends.keys.sorted()[index]
|
||||||
|
dataStore.friends.removeValue(forKey: key)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
.onDelete {indices in
|
|
||||||
dataStore.friends.remove(atOffsets: indices)
|
|
||||||
}
|
}
|
||||||
HStack {
|
HStack {
|
||||||
TextField("New Feed", text: $newFeedID)
|
TextField("New Feed", text: $newFeedID)
|
||||||
Button(action: {
|
Button(action: {
|
||||||
withAnimation {
|
withAnimation {
|
||||||
let feedid = newFeedID
|
dataStore.friends[newFeedID] = 0
|
||||||
dataStore.friends.append(feedid)
|
|
||||||
newFeedID = ""
|
newFeedID = ""
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
|
|||||||
@ -22,8 +22,10 @@ struct SettingsView: View {
|
|||||||
Label(dataStore.personalID, systemImage: "person.crop.circle")
|
Label(dataStore.personalID, systemImage: "person.crop.circle")
|
||||||
}
|
}
|
||||||
Section(header: Text("Friends")) {
|
Section(header: Text("Friends")) {
|
||||||
ForEach(dataStore.friends) { friend in
|
ForEach(dataStore.friends.keys.sorted(), id: \.self) { friend in
|
||||||
Label(friend, systemImage: "person")
|
if let seq = dataStore.friends[friend] {
|
||||||
|
Label("\(friend) - SEQ: \(seq)", systemImage: "person")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -62,9 +64,9 @@ struct SettingsView: View {
|
|||||||
|
|
||||||
struct SettingsView_Previews: PreviewProvider {
|
struct SettingsView_Previews: PreviewProvider {
|
||||||
static var friends = [
|
static var friends = [
|
||||||
"BOS",
|
"BOS":1,
|
||||||
"ALI",
|
"ALI":2,
|
||||||
"CYN"
|
"CYN":3
|
||||||
]
|
]
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
SettingsView()
|
SettingsView()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user