A native swift / swiftUI Bluesky client

updates to swiftData models

+60
Plume/Models/PLMModel.swift
··· 1 + // 2 + // SBModel.swift 3 + // Plume 4 + // 5 + // Created by Thomas Rademaker on 9/1/23. 6 + // 7 + 8 + import SwiftUI 9 + @preconcurrency import SwiftData 10 + 11 + typealias PlumeSchema = PlumeSchemaV1 12 + 13 + enum PlumeSchemaV1: VersionedSchema, Sendable { 14 + static let versionIdentifier = Schema.Version(1, 0, 0) 15 + 16 + static var models: [any PersistentModel.Type] { 17 + [ 18 + PLMSession.self, 19 + PLMTimeline.self, 20 + PLMProfile.self, 21 + ] 22 + } 23 + } 24 + 25 + 26 + struct PlumeDataContainerViewModifier: ViewModifier { 27 + let container: ModelContainer 28 + let schema = Schema(PlumeSchema.models) 29 + 30 + init(inMemory: Bool) { 31 + do { 32 + let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: inMemory) 33 + container = try ModelContainer(for: schema, configurations: modelConfiguration) 34 + } catch { 35 + fatalError("Failed to create ModelContainer") 36 + } 37 + } 38 + 39 + func body(content: Content) -> some View { 40 + content 41 + .modelContainer(container) 42 + } 43 + } 44 + 45 + class PlumeModelOptions { 46 + // #if DEBUG 47 + // public static let inMemoryPersistence = true 48 + // #else 49 + // public static let inMemoryPersistence = false 50 + // #endif 51 + 52 + static let inMemoryPersistence = false 53 + } 54 + 55 + 56 + extension View { 57 + func setupModel(inMemory: Bool = PlumeModelOptions.inMemoryPersistence) -> some View { 58 + modifier(PlumeDataContainerViewModifier(inMemory: inMemory)) 59 + } 60 + }
+64
Plume/Models/PLMProfile.swift
··· 1 + // 2 + // PLMProfile.swift 3 + // 4 + // 5 + // Created by Thomas Rademaker on 9/6/23. 6 + // 7 + 8 + import Foundation 9 + @preconcurrency import SwiftData 10 + import bskyKit 11 + 12 + typealias PLMProfile = PlumeSchema.PLMProfile 13 + 14 + extension PlumeSchema { 15 + 16 + @Model 17 + public class PLMProfile { 18 + @Attribute(.unique) public var did: String 19 + public var handle: String 20 + public var displayName: String 21 + public var profileDescription: String 22 + public var avatar: String 23 + public var banner: String 24 + public var followsCount: Int 25 + public var followersCount: Int 26 + public var postsCount: Int 27 + public var indexedAt: Date 28 + // TODO: bring back viewer and labels 29 + // public var viewer: Viewer 30 + // public var labels: [String] 31 + @Attribute(.externalStorage) public var avatarOnDisk: Data? 32 + public var session: PLMSession? 33 + 34 + public init(_ profile: Profile) { 35 + self.did = profile.did 36 + self.handle = profile.handle 37 + self.displayName = profile.displayName ?? "" 38 + self.profileDescription = profile.description ?? "" 39 + self.avatar = profile.avatar ?? "" 40 + self.banner = profile.banner ?? "" 41 + self.followsCount = profile.followsCount ?? 0 42 + self.followersCount = profile.followersCount ?? 0 43 + self.postsCount = profile.postsCount ?? 0 44 + self.indexedAt = profile.indexedAt ?? .now 45 + // self.viewer = profile.viewer 46 + // self.labels = profile.labels 47 + } 48 + 49 + public init(did: String, handle: String, displayName: String, profileDescription: String, avatar: String, banner: String, followsCount: Int, followersCount: Int, postsCount: Int, indexedAt: Date/*, viewer: Viewer, labels: [String]*/) { 50 + self.did = did 51 + self.handle = handle 52 + self.displayName = displayName 53 + self.profileDescription = profileDescription 54 + self.avatar = avatar 55 + self.banner = banner 56 + self.followsCount = followsCount 57 + self.followersCount = followersCount 58 + self.postsCount = postsCount 59 + self.indexedAt = indexedAt 60 + // self.viewer = viewer 61 + // self.labels = labels 62 + } 63 + } 64 + }
+107
Plume/Models/PLMSession.swift
··· 1 + // 2 + // SBSession.swift 3 + // Plume 4 + // 5 + // Created by Thomas Rademaker on 9/1/23. 6 + // 7 + 8 + import Foundation 9 + @preconcurrency import SwiftData 10 + import bskyKit 11 + 12 + typealias PLMSession = PlumeSchema.PLMSession 13 + 14 + extension PlumeSchema { 15 + 16 + /* 17 + public enum ACSessionSchemaV1: VersionedSchema { 18 + public static var versionIdentifier = Schema.Version(1, 0, 0) 19 + 20 + public static var models: [any PersistentModel.Type] { 21 + [ACSession.self] 22 + } 23 + 24 + // @Model 25 + // public class ACSession { 26 + // @Attribute(.unique) public var did: String 27 + // public var handle: String 28 + // public var email: String? 29 + // 30 + //// @Relationship(deleteRule: .cascade, inverse: \SBProfile.session) public var profile: SBProfile? 31 + //// @Relationship(deleteRule: .cascade, inverse: \ACPreferences.session) public var preferences: ACPreferences? 32 + //// @Relationship(deleteRule: .cascade, inverse: \ACTimeline.session) public var timeline: ACTimeline? 33 + // 34 + // init(did: String, handle: String, email: String? = nil/*, profile: SBProfile? = nil, preferences: ACPreferences? = nil, timeline: ACTimeline? = nil*/) { 35 + // self.did = did 36 + // self.handle = handle 37 + // self.email = email 38 + //// self.profile = profile 39 + //// self.preferences = preferences 40 + //// self.timeline = timeline 41 + // } 42 + // } 43 + }*/ 44 + 45 + @Model 46 + public class PLMSession { 47 + @Attribute(.unique) public var did: String 48 + public var handle: String 49 + public var email: String? 50 + 51 + // @Relationship(deleteRule: .cascade, inverse: \SBProfile.session) public var profile: SBProfile? 52 + // @Relationship(deleteRule: .cascade, inverse: \ACPreferences.session) public var preferences: ACPreferences? 53 + // @Relationship(deleteRule: .cascade, inverse: \ACTimeline.session) public var timeline: ACTimeline? 54 + 55 + init(did: String, handle: String, email: String? = nil/*, profile: SBProfile? = nil, preferences: ACPreferences? = nil, timeline: ACTimeline? = nil*/) { 56 + self.did = did 57 + self.handle = handle 58 + self.email = email 59 + // self.profile = profile 60 + // self.preferences = preferences 61 + // self.timeline = timeline 62 + } 63 + } 64 + /* 65 + extension SBSession { 66 + @discardableResult 67 + public static func update(did: String, handle: String, email: String?, accessJwt: String?, refreshJwt: String?) -> PersistentIdentifier? { 68 + do { 69 + let context = ModelContext(ACModel.shared.container) 70 + context.autosaveEnabled = false 71 + guard let state = try context.fetch(FetchDescriptor<ACState>()).first else { return nil } 72 + state.currentSessionDid = did 73 + 74 + let acSession: SBSession 75 + 76 + if let storedSession = try context.fetch(FetchDescriptor<SBSession>(predicate: #Predicate { $0.did == did })).first { 77 + acSession = storedSession 78 + } else { 79 + acSession = SBSession(did: did, handle: handle, email: email) 80 + context.insert(acSession) 81 + } 82 + 83 + acSession.handle = handle 84 + acSession.email = email 85 + try? context.save() 86 + 87 + if let accessJwt = accessJwt, let refreshJwt = refreshJwt { 88 + try Vault.savePrivateKey(accessJwt, keychainConfiguration: KeychainConfiguration(serviceName: Constants.serviceName, accessGroup: nil, accountName: "\(Constants.accessJWT)\(did)")) 89 + try Vault.savePrivateKey(refreshJwt, keychainConfiguration: KeychainConfiguration(serviceName: Constants.serviceName, accessGroup: nil, accountName: "\(Constants.refreshJWT)\(did)")) 90 + 91 + AtProtocol.updateTokens(access: accessJwt, refresh: refreshJwt) 92 + } 93 + 94 + return acSession.id 95 + } catch { 96 + return nil 97 + } 98 + } 99 + 100 + public static var current: SBSession? { 101 + let context = ModelContext(ACModel.shared.container) 102 + let did = ACState.current.currentSessionDid 103 + guard let session = try? context.fetch(FetchDescriptor<ACSession>(predicate: #Predicate { $0.did == did })).first else { return nil } 104 + return session 105 + } 106 + }*/ 107 + }
+20
Plume/Models/PLMTimeline.swift
··· 1 + import Foundation 2 + @preconcurrency import SwiftData 3 + import bskyKit 4 + 5 + typealias PLMTimeline = PlumeSchema.PLMTimeline 6 + 7 + extension PlumeSchema { 8 + @Model 9 + class PLMTimeline { 10 + var feed: [TimelineItem] 11 + var cursor: String 12 + var session: PLMSession? 13 + 14 + init(feed: [TimelineItem], cursor: String, session: PLMSession? = nil) { 15 + self.feed = feed 16 + self.cursor = cursor 17 + self.session = session 18 + } 19 + } 20 + }
-80
Plume/Models/SBModel.swift
··· 1 - // 2 - // SBModel.swift 3 - // Plume 4 - // 5 - // Created by Thomas Rademaker on 9/1/23. 6 - // 7 - 8 - import SwiftUI 9 - import SwiftData 10 - 11 - //public typealias ACFeed = ACFeedSchemaV1.ACFeed 12 - //public typealias ACPreferences = ACPreferencesSchemaV1.ACPreferences 13 - //public typealias SBProfile = ACProfileSchemaV1.SBProfile 14 - //public typealias SBSession = ACSessionSchemaV1.SBSession 15 - //public typealias ACTimeline = ACTimelineSchemaV1.ACTimeline 16 - //public typealias ACModel = ACModelSchemaV1.ACModel 17 - 18 - //public enum ACModelSchemaV1: VersionedSchema { 19 - // public static var versionIdentifier = Schema.Version(1, 0, 0) 20 - // 21 - // public static var models: [any PersistentModel.Type] { 22 - // [SBSession.self] 23 - // } 24 - // 25 - // @Model 26 - // public class ACModel { 27 - // public init() {} 28 - // } 29 - //} 30 - 31 - //public extension ACModel { 32 - // static let schema = SwiftData.Schema([ 33 - //// ACModel.self, 34 - //// ACFeed.self, 35 - //// ACPreferences.self, 36 - //// SBProfile.self, 37 - // SBSession.self, 38 - //// ACTimeline.self, 39 - // ]) 40 - //} 41 - 42 - //struct ACModelViewModifier: ViewModifier { 43 - // @Environment(\.modelContext) private var modelContext 44 - // 45 - // func body(content: Content) -> some View { 46 - // content.onAppear { 47 - // DataGeneration.generateAllData(modelContext: modelContext) 48 - // } 49 - // } 50 - //} 51 - 52 - struct PlumeDataContainerViewModifier: ViewModifier { 53 - let container: ModelContainer 54 - let schema = Schema([ 55 - SBSession.self, 56 - SBTimeline.self, 57 - SBProfile.self, 58 - // ACFeed.self, 59 - ]) 60 - 61 - init(inMemory: Bool) { 62 - do { 63 - let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: inMemory) 64 - container = try ModelContainer(for: schema, configurations: modelConfiguration) 65 - } catch { 66 - fatalError("Failed to create ModelContainer") 67 - } 68 - } 69 - 70 - func body(content: Content) -> some View { 71 - content 72 - .modelContainer(container) 73 - } 74 - } 75 - 76 - public extension View { 77 - func setupModel(inMemory: Bool = SBModelOptions.inMemoryPersistence) -> some View { 78 - modifier(PlumeDataContainerViewModifier(inMemory: inMemory)) 79 - } 80 - }
-17
Plume/Models/SBModelOptions.swift
··· 1 - // 2 - // SBModelOptions.swift 3 - // Plume 4 - // 5 - // Created by Thomas Rademaker on 10/22/23. 6 - // 7 - 8 - import Foundation 9 - 10 - public class SBModelOptions { 11 - public static let inMemoryPersistence = true 12 - // #if DEBUG 13 - // public static let inMemoryPersistence = true 14 - // #else 15 - // public static let inMemoryPersistence = false 16 - // #endif 17 - }
-59
Plume/Models/SBProfile.swift
··· 1 - // 2 - // SBProfile.swift 3 - // 4 - // 5 - // Created by Thomas Rademaker on 9/6/23. 6 - // 7 - 8 - import Foundation 9 - import SwiftData 10 - import bskyKit 11 - 12 - @Model 13 - public class SBProfile { 14 - @Attribute(.unique) public var did: String 15 - public var handle: String 16 - public var displayName: String 17 - public var profileDescription: String 18 - public var avatar: String 19 - public var banner: String 20 - public var followsCount: Int 21 - public var followersCount: Int 22 - public var postsCount: Int 23 - public var indexedAt: Date 24 - // TODO: bring back viewer and labels 25 - // public var viewer: Viewer 26 - // public var labels: [String] 27 - @Attribute(.externalStorage) public var avatarOnDisk: Data? 28 - public var session: SBSession? 29 - 30 - public init(_ profile: Profile) { 31 - self.did = profile.did 32 - self.handle = profile.handle 33 - self.displayName = profile.displayName ?? "" 34 - self.profileDescription = profile.description ?? "" 35 - self.avatar = profile.avatar ?? "" 36 - self.banner = profile.banner ?? "" 37 - self.followsCount = profile.followsCount ?? 0 38 - self.followersCount = profile.followersCount ?? 0 39 - self.postsCount = profile.postsCount ?? 0 40 - self.indexedAt = profile.indexedAt ?? .now 41 - // self.viewer = profile.viewer 42 - // self.labels = profile.labels 43 - } 44 - 45 - public init(did: String, handle: String, displayName: String, profileDescription: String, avatar: String, banner: String, followsCount: Int, followersCount: Int, postsCount: Int, indexedAt: Date/*, viewer: Viewer, labels: [String]*/) { 46 - self.did = did 47 - self.handle = handle 48 - self.displayName = displayName 49 - self.profileDescription = profileDescription 50 - self.avatar = avatar 51 - self.banner = banner 52 - self.followsCount = followsCount 53 - self.followersCount = followersCount 54 - self.postsCount = postsCount 55 - self.indexedAt = indexedAt 56 - // self.viewer = viewer 57 - // self.labels = labels 58 - } 59 - }
-102
Plume/Models/SBSession.swift
··· 1 - // 2 - // SBSession.swift 3 - // Plume 4 - // 5 - // Created by Thomas Rademaker on 9/1/23. 6 - // 7 - 8 - import SwiftData 9 - import SwiftUI 10 - import Vault 11 - import bskyKit 12 - /* 13 - public enum ACSessionSchemaV1: VersionedSchema { 14 - public static var versionIdentifier = Schema.Version(1, 0, 0) 15 - 16 - public static var models: [any PersistentModel.Type] { 17 - [ACSession.self] 18 - } 19 - 20 - // @Model 21 - // public class ACSession { 22 - // @Attribute(.unique) public var did: String 23 - // public var handle: String 24 - // public var email: String? 25 - // 26 - //// @Relationship(deleteRule: .cascade, inverse: \SBProfile.session) public var profile: SBProfile? 27 - //// @Relationship(deleteRule: .cascade, inverse: \ACPreferences.session) public var preferences: ACPreferences? 28 - //// @Relationship(deleteRule: .cascade, inverse: \ACTimeline.session) public var timeline: ACTimeline? 29 - // 30 - // init(did: String, handle: String, email: String? = nil/*, profile: SBProfile? = nil, preferences: ACPreferences? = nil, timeline: ACTimeline? = nil*/) { 31 - // self.did = did 32 - // self.handle = handle 33 - // self.email = email 34 - //// self.profile = profile 35 - //// self.preferences = preferences 36 - //// self.timeline = timeline 37 - // } 38 - // } 39 - }*/ 40 - 41 - @Model 42 - public class SBSession { 43 - @Attribute(.unique) public var did: String 44 - public var handle: String 45 - public var email: String? 46 - 47 - // @Relationship(deleteRule: .cascade, inverse: \SBProfile.session) public var profile: SBProfile? 48 - // @Relationship(deleteRule: .cascade, inverse: \ACPreferences.session) public var preferences: ACPreferences? 49 - // @Relationship(deleteRule: .cascade, inverse: \ACTimeline.session) public var timeline: ACTimeline? 50 - 51 - init(did: String, handle: String, email: String? = nil/*, profile: SBProfile? = nil, preferences: ACPreferences? = nil, timeline: ACTimeline? = nil*/) { 52 - self.did = did 53 - self.handle = handle 54 - self.email = email 55 - // self.profile = profile 56 - // self.preferences = preferences 57 - // self.timeline = timeline 58 - } 59 - } 60 - /* 61 - extension SBSession { 62 - @discardableResult 63 - public static func update(did: String, handle: String, email: String?, accessJwt: String?, refreshJwt: String?) -> PersistentIdentifier? { 64 - do { 65 - let context = ModelContext(ACModel.shared.container) 66 - context.autosaveEnabled = false 67 - guard let state = try context.fetch(FetchDescriptor<ACState>()).first else { return nil } 68 - state.currentSessionDid = did 69 - 70 - let acSession: SBSession 71 - 72 - if let storedSession = try context.fetch(FetchDescriptor<SBSession>(predicate: #Predicate { $0.did == did })).first { 73 - acSession = storedSession 74 - } else { 75 - acSession = SBSession(did: did, handle: handle, email: email) 76 - context.insert(acSession) 77 - } 78 - 79 - acSession.handle = handle 80 - acSession.email = email 81 - try? context.save() 82 - 83 - if let accessJwt = accessJwt, let refreshJwt = refreshJwt { 84 - try Vault.savePrivateKey(accessJwt, keychainConfiguration: KeychainConfiguration(serviceName: Constants.serviceName, accessGroup: nil, accountName: "\(Constants.accessJWT)\(did)")) 85 - try Vault.savePrivateKey(refreshJwt, keychainConfiguration: KeychainConfiguration(serviceName: Constants.serviceName, accessGroup: nil, accountName: "\(Constants.refreshJWT)\(did)")) 86 - 87 - AtProtocol.updateTokens(access: accessJwt, refresh: refreshJwt) 88 - } 89 - 90 - return acSession.id 91 - } catch { 92 - return nil 93 - } 94 - } 95 - 96 - public static var current: SBSession? { 97 - let context = ModelContext(ACModel.shared.container) 98 - let did = ACState.current.currentSessionDid 99 - guard let session = try? context.fetch(FetchDescriptor<ACSession>(predicate: #Predicate { $0.did == did })).first else { return nil } 100 - return session 101 - } 102 - }*/
-36
Plume/Models/SBTimeline.swift
··· 1 - import SwiftData 2 - import bskyKit 3 - // 4 - //public enum ACTimelineSchemaV1: VersionedSchema { 5 - // public static var versionIdentifier = Schema.Version(1, 0, 0) 6 - // 7 - // public static var models: [any PersistentModel.Type] { 8 - // [ACTimeline.self] 9 - // } 10 - // 11 - // @Model 12 - // public class ACTimeline { 13 - // public var feed: [TimelineItem] 14 - // public var cursor: String 15 - // public var session: SBSession? 16 - // 17 - // init(feed: [TimelineItem], cursor: String, session: SBSession?) { 18 - // self.feed = feed 19 - // self.cursor = cursor 20 - // self.session = session 21 - // } 22 - // } 23 - //} 24 - 25 - @Model 26 - class SBTimeline { 27 - var feed: [TimelineItem] 28 - var cursor: String 29 - var session: SBSession? 30 - 31 - init(feed: [TimelineItem], cursor: String, session: SBSession? = nil) { 32 - self.feed = feed 33 - self.cursor = cursor 34 - self.session = session 35 - } 36 - }
+7 -7
Plume/Models/previews/PreviewContainer.swift
··· 13 13 fileprivate struct SampleDataTimeline: PreviewModifier { 14 14 15 15 static func makeSharedContext() throws -> ModelContainer { 16 - let container = try ModelContainer(for: SBTimeline.self, configurations: ModelConfiguration(isStoredInMemoryOnly: true)) 16 + let container = try ModelContainer(for: PLMTimeline.self, configurations: ModelConfiguration(isStoredInMemoryOnly: true)) 17 17 18 18 if let timeline: Timeline = object(resourceName: "timeline") { 19 - let acTimeline = SBTimeline(feed: timeline.feed, cursor: timeline.cursor, session: nil) 20 - container.mainContext.insert(acTimeline) 19 + let plmTimeline = PLMTimeline(feed: timeline.feed, cursor: timeline.cursor, session: nil) 20 + container.mainContext.insert(plmTimeline) 21 21 } 22 22 23 23 try container.mainContext.save() ··· 31 31 32 32 fileprivate struct SampleDataSession: PreviewModifier { 33 33 static func makeSharedContext() async throws -> ModelContainer { 34 - let container = try ModelContainer(for: SBSession.self, configurations: ModelConfiguration(isStoredInMemoryOnly: true)) 34 + let container = try ModelContainer(for: PLMSession.self, configurations: ModelConfiguration(isStoredInMemoryOnly: true)) 35 35 36 36 return container 37 37 } ··· 43 43 44 44 fileprivate struct SampleDataProfile: PreviewModifier { 45 45 static func makeSharedContext() async throws -> ModelContainer { 46 - let container = try ModelContainer(for: SBProfile.self, configurations: ModelConfiguration(isStoredInMemoryOnly: true)) 46 + let container = try ModelContainer(for: PLMProfile.self, configurations: ModelConfiguration(isStoredInMemoryOnly: true)) 47 47 if let profile: Profile = object(resourceName: "profile") { 48 - let sbProfile = SBProfile(profile) 49 - container.mainContext.insert(sbProfile) 48 + let plmProfile = PLMProfile(profile) 49 + container.mainContext.insert(plmProfile) 50 50 } 51 51 52 52 try container.mainContext.save()
+1 -1
Plume/Modules/AppModel.swift
··· 11 11 fileprivate struct AppModelViewModifier: ViewModifier { 12 12 @Environment(AppState.self) private var state 13 13 @Environment(Services.self) private var services 14 - @Query private var sessions: [SBSession] 14 + @Query private var sessions: [PLMSession] 15 15 @State private var checkLoginStatusTrigger = PlainTaskTrigger() 16 16 @AppStorage(Constants.UserDefaults.currentSessionDid) private var currentSessionDid: String? 17 17 @AppStorage(Constants.UserDefaults.hostURL) private var hostURL: String?
+3 -3
Plume/Modules/Main/Home/HomePresenter.swift
··· 48 48 struct HomeView: View { 49 49 @Environment(HomeState.self) private var state 50 50 @Environment(Services.self) private var services 51 - @Query private var sessions: [SBSession] 52 - @Query private var timelines: [SBTimeline] 51 + @Query private var sessions: [PLMSession] 52 + @Query private var timelines: [PLMTimeline] 53 53 54 54 var body: some View { 55 55 TimelineListView(timelines: timelines) ··· 83 83 84 84 fileprivate struct HomeFeedFilter: View { 85 85 @Environment(HomeState.self) private var state 86 - @Query private var sessions: [SBSession] 86 + @Query private var sessions: [PLMSession] 87 87 // @Query private var feeds: [ACFeed] 88 88 // @State private var feed: ACFeed? 89 89 @AppStorage(Constants.UserDefaults.currentSessionDid) private var currentSessionDid: String?
+2 -2
Plume/Modules/Main/Home/TimelineListView.swift
··· 13 13 struct TimelineListView: View { 14 14 @Environment(HomeState.self) private var state 15 15 @Namespace private var topID 16 - var timelines: [SBTimeline] 16 + var timelines: [PLMTimeline] 17 17 18 18 var body: some View { 19 19 @Bindable var state = state ··· 395 395 } 396 396 397 397 #Preview(traits: .sampleTimeline) { 398 - @Previewable @Query var timelines: [SBTimeline] 398 + @Previewable @Query var timelines: [PLMTimeline] 399 399 400 400 TimelineListView(timelines: timelines) 401 401 .environment(HomeState(parentState: .init()))
+2 -2
Plume/Modules/Main/Profile/ProfilePresenter.swift
··· 38 38 39 39 fileprivate struct ProfileHeaderView: View { 40 40 var currentSessionDid: String? 41 - @Query private var profiles: [SBProfile] 41 + @Query private var profiles: [PLMProfile] 42 42 43 43 init(currentSessionDid: String?) { 44 44 let did = currentSessionDid ?? "" 45 - _profiles = Query(filter: #Predicate<SBProfile> { $0.did == did }) 45 + _profiles = Query(filter: #Predicate<PLMProfile> { $0.did == did }) 46 46 } 47 47 48 48 private var profileURL: String? {
+12 -12
Plume/Networking/Services.swift
··· 94 94 ) 95 95 96 96 // Get OAuth config from Info.plist 97 - var clientMetadataURL = Bundle.main.object( 97 + let clientMetadataURL = Bundle.main.object( 98 98 forInfoDictionaryKey: Constants.OAuth.clientMetadataURLKey 99 99 ) as? String ?? "" 100 100 ··· 260 260 // } 261 261 262 262 func getTimeline(for sessionID: PersistentIdentifier, limit: Int) async { 263 - guard let session = modelContext.model(for: sessionID) as? SBSession else { return } 263 + guard let session = modelContext.model(for: sessionID) as? PLMSession else { return } 264 264 do { 265 265 let bskyService = await BskyService() 266 266 let timeline = try await bskyService.getTimeline(limit: limit) 267 267 268 - let acTimeline = SBTimeline(feed: timeline.feed, cursor: timeline.cursor, session: session) 269 - modelContext.insert(acTimeline) 268 + let plmTimeline = PLMTimeline(feed: timeline.feed, cursor: timeline.cursor, session: session) 269 + modelContext.insert(plmTimeline) 270 270 try modelContext.save() 271 271 } catch { 272 272 print("### error: \(error)") ··· 286 286 287 287 func logout() async throws { 288 288 guard let did = currentSessionDid else { return } 289 - let sessions = try modelContext.fetch(FetchDescriptor<SBSession>(predicate: #Predicate { $0.did == did })) 289 + let sessions = try modelContext.fetch(FetchDescriptor<PLMSession>(predicate: #Predicate { $0.did == did })) 290 290 guard let currentSession = sessions.first else { return } 291 291 modelContext.delete(currentSession) 292 292 try? modelContext.save() ··· 297 297 } 298 298 299 299 private func updateSession(did: String, handle: String, email: String?, accessJwt: String?, refreshJwt: String?) async throws { 300 - let acSession: SBSession 300 + let plmSession: PLMSession 301 301 302 - if let storedSession = try modelContext.fetch(FetchDescriptor<SBSession>(predicate: #Predicate { $0.did == did })).first { 303 - acSession = storedSession 302 + if let storedSession = try modelContext.fetch(FetchDescriptor<PLMSession>(predicate: #Predicate { $0.did == did })).first { 303 + plmSession = storedSession 304 304 } else { 305 - acSession = SBSession(did: did, handle: handle, email: email) 306 - modelContext.insert(acSession) 305 + plmSession = PLMSession(did: did, handle: handle, email: email) 306 + modelContext.insert(plmSession) 307 307 } 308 308 309 - acSession.handle = handle 310 - acSession.email = email 309 + plmSession.handle = handle 310 + plmSession.email = email 311 311 try? modelContext.save() 312 312 currentSessionDid = did 313 313