wip
This commit is contained in:
parent
c426847700
commit
acf2807056
|
@ -100,12 +100,6 @@ extension Client {
|
||||||
_ = try await connection.module(.roster).removeItem(jid: JID(roster.contactBareJid))
|
_ = try await connection.module(.roster).removeItem(jid: JID(roster.contactBareJid))
|
||||||
}
|
}
|
||||||
|
|
||||||
func setActive(_ active: Bool) {
|
|
||||||
Task {
|
|
||||||
try? await credentials.setActive(flag: active)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func connect() async {
|
func connect() async {
|
||||||
guard credentials.isActive, state == .enabled(.disconnected) else {
|
guard credentials.isActive, state == .enabled(.disconnected) else {
|
||||||
return
|
return
|
||||||
|
|
|
@ -5,7 +5,7 @@ import Photos
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
final class SettingsStore: ObservableObject {
|
final class ChatSettingsStore: ObservableObject {
|
||||||
@Published var chat: Chat?
|
@Published var chat: Chat?
|
||||||
|
|
||||||
private let client: Client
|
private let client: Client
|
||||||
|
@ -21,7 +21,7 @@ final class SettingsStore: ObservableObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension SettingsStore {
|
extension ChatSettingsStore {
|
||||||
func setSecured(_ secured: Bool) {
|
func setSecured(_ secured: Bool) {
|
||||||
Task {
|
Task {
|
||||||
try? await chat?.setEncrypted(secured)
|
try? await chat?.setEncrypted(secured)
|
||||||
|
@ -30,7 +30,7 @@ extension SettingsStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Processing attachments
|
// MARK: - Processing attachments
|
||||||
private extension SettingsStore {
|
private extension ChatSettingsStore {
|
||||||
func subscribe() {
|
func subscribe() {
|
||||||
chatCancellable = ValueObservation.tracking(Chat
|
chatCancellable = ValueObservation.tracking(Chat
|
||||||
.filter(Column("account") == roster.bareJid && Column("participant") == roster.contactBareJid)
|
.filter(Column("account") == roster.bareJid && Column("participant") == roster.contactBareJid)
|
|
@ -131,7 +131,7 @@ extension ClientsStore {
|
||||||
// MARK: - Produce stores for conversation
|
// MARK: - Produce stores for conversation
|
||||||
extension ClientsStore {
|
extension ClientsStore {
|
||||||
// swiftlint:disable:next large_tuple
|
// swiftlint:disable:next large_tuple
|
||||||
func conversationStores(for roster: Roster) async throws -> (MessagesStore, AttachmentsStore, SettingsStore) {
|
func conversationStores(for roster: Roster) async throws -> (MessagesStore, AttachmentsStore, ChatSettingsStore) {
|
||||||
while !ready {
|
while !ready {
|
||||||
await Task.yield()
|
await Task.yield()
|
||||||
}
|
}
|
||||||
|
@ -142,12 +142,12 @@ extension ClientsStore {
|
||||||
|
|
||||||
let conversationStore = MessagesStore(roster: roster, client: client)
|
let conversationStore = MessagesStore(roster: roster, client: client)
|
||||||
let attachmentsStore = AttachmentsStore(roster: roster, client: client)
|
let attachmentsStore = AttachmentsStore(roster: roster, client: client)
|
||||||
let settingsStore = SettingsStore(roster: roster, client: client)
|
let settingsStore = ChatSettingsStore(roster: roster, client: client)
|
||||||
return (conversationStore, attachmentsStore, settingsStore)
|
return (conversationStore, attachmentsStore, settingsStore)
|
||||||
}
|
}
|
||||||
|
|
||||||
// swiftlint:disable:next large_tuple
|
// swiftlint:disable:next large_tuple
|
||||||
func conversationStores(for chat: Chat) async throws -> (MessagesStore, AttachmentsStore, SettingsStore) {
|
func conversationStores(for chat: Chat) async throws -> (MessagesStore, AttachmentsStore, ChatSettingsStore) {
|
||||||
while !ready {
|
while !ready {
|
||||||
await Task.yield()
|
await Task.yield()
|
||||||
}
|
}
|
||||||
|
@ -159,7 +159,7 @@ extension ClientsStore {
|
||||||
let roster = try await chat.fetchRoster()
|
let roster = try await chat.fetchRoster()
|
||||||
let conversationStore = MessagesStore(roster: roster, client: client)
|
let conversationStore = MessagesStore(roster: roster, client: client)
|
||||||
let attachmentsStore = AttachmentsStore(roster: roster, client: client)
|
let attachmentsStore = AttachmentsStore(roster: roster, client: client)
|
||||||
let settingsStore = SettingsStore(roster: roster, client: client)
|
let settingsStore = ChatSettingsStore(roster: roster, client: client)
|
||||||
return (conversationStore, attachmentsStore, settingsStore)
|
return (conversationStore, attachmentsStore, settingsStore)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
32
ConversationsClassic/AppData/Store/GlobalSettingsStore.swift
Normal file
32
ConversationsClassic/AppData/Store/GlobalSettingsStore.swift
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import Combine
|
||||||
|
import Foundation
|
||||||
|
import GRDB
|
||||||
|
import Photos
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
final class GlobalSettingsStore: ObservableObject {
|
||||||
|
static let shared = GlobalSettingsStore()
|
||||||
|
|
||||||
|
@Published var credentials: [Credentials] = []
|
||||||
|
|
||||||
|
private var credentialsCancellable: AnyCancellable?
|
||||||
|
|
||||||
|
init() {
|
||||||
|
subscribe()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension GlobalSettingsStore {
|
||||||
|
func subscribe() {
|
||||||
|
credentialsCancellable = ValueObservation.tracking(Credentials
|
||||||
|
.fetchAll
|
||||||
|
)
|
||||||
|
.publisher(in: Database.shared.dbQueue, scheduling: .immediate)
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
|
.sink { _ in
|
||||||
|
} receiveValue: { [weak self] credentials in
|
||||||
|
self?.credentials = credentials
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ import SwiftUI
|
||||||
@MainActor
|
@MainActor
|
||||||
struct ConversationsClassic: App {
|
struct ConversationsClassic: App {
|
||||||
private let clientsStore = ClientsStore.shared
|
private let clientsStore = ClientsStore.shared
|
||||||
|
private let globalSettingsStore = GlobalSettingsStore.shared
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
// There's a bug on iOS 17 where sheet may not load with large title, even if modifiers are set, which causes some tests to fail
|
// There's a bug on iOS 17 where sheet may not load with large title, even if modifiers are set, which causes some tests to fail
|
||||||
|
@ -16,6 +17,7 @@ struct ConversationsClassic: App {
|
||||||
WindowGroup {
|
WindowGroup {
|
||||||
RootView()
|
RootView()
|
||||||
.environmentObject(clientsStore)
|
.environmentObject(clientsStore)
|
||||||
|
.environmentObject(globalSettingsStore)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct WelcomeScreen: View {
|
struct WelcomeScreen: View {
|
||||||
|
@EnvironmentObject var globalSettingsStore: GlobalSettingsStore
|
||||||
@Environment(\.router) var router
|
@Environment(\.router) var router
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
@ -9,6 +10,23 @@ struct WelcomeScreen: View {
|
||||||
Color.Material.Background.light
|
Color.Material.Background.light
|
||||||
.ignoresSafeArea()
|
.ignoresSafeArea()
|
||||||
|
|
||||||
|
if !globalSettingsStore.credentials.isEmpty && globalSettingsStore.credentials.allSatisfy({ !$0.isActive }) {
|
||||||
|
VStack {
|
||||||
|
HStack {
|
||||||
|
Spacer()
|
||||||
|
Image(systemName: "gear")
|
||||||
|
.foregroundColor(.Material.Elements.active)
|
||||||
|
.tappablePadding(.symmetric(10)) {
|
||||||
|
router.showScreen(.push) { _ in
|
||||||
|
SettingsScreen()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// content
|
// content
|
||||||
VStack(spacing: 32) {
|
VStack(spacing: 32) {
|
||||||
// icon
|
// icon
|
||||||
|
|
|
@ -7,7 +7,7 @@ struct ConversationScreen: View {
|
||||||
@Environment(\.router) var router
|
@Environment(\.router) var router
|
||||||
@StateObject var messagesStore: MessagesStore
|
@StateObject var messagesStore: MessagesStore
|
||||||
@StateObject var attachments: AttachmentsStore
|
@StateObject var attachments: AttachmentsStore
|
||||||
@StateObject var settings: SettingsStore
|
@StateObject var settings: ChatSettingsStore
|
||||||
|
|
||||||
@State private var autoScroll = true
|
@State private var autoScroll = true
|
||||||
@State private var firstIsVisible = true
|
@State private var firstIsVisible = true
|
||||||
|
|
|
@ -5,7 +5,7 @@ import SwiftUI
|
||||||
|
|
||||||
struct ConversationSettingsScreen: View {
|
struct ConversationSettingsScreen: View {
|
||||||
@Environment(\.router) var router
|
@Environment(\.router) var router
|
||||||
@EnvironmentObject var settingsStore: SettingsStore
|
@EnvironmentObject var settingsStore: ChatSettingsStore
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ZStack {
|
ZStack {
|
||||||
|
|
|
@ -2,6 +2,7 @@ import SwiftUI
|
||||||
|
|
||||||
struct SettingsScreen: View {
|
struct SettingsScreen: View {
|
||||||
@EnvironmentObject var clientsStore: ClientsStore
|
@EnvironmentObject var clientsStore: ClientsStore
|
||||||
|
@EnvironmentObject var settingsStore: GlobalSettingsStore
|
||||||
@Environment(\.router) var router
|
@Environment(\.router) var router
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
@ -22,19 +23,21 @@ struct SettingsScreen: View {
|
||||||
// Accounts section
|
// Accounts section
|
||||||
SharedSectionTitle(text: L10n.Settings.Section.Accounts.title)
|
SharedSectionTitle(text: L10n.Settings.Section.Accounts.title)
|
||||||
|
|
||||||
ForEach(clientsStore.clients) { client in
|
ForEach(settingsStore.credentials) { creds in
|
||||||
SharedListRow(
|
SharedListRow(
|
||||||
iconType: .charCircle(client.credentials.bareJid),
|
iconType: .charCircle(creds.bareJid),
|
||||||
text: client.credentials.bareJid,
|
text: creds.bareJid,
|
||||||
controlType: .switcher(isOn: Binding(
|
controlType: .switcher(isOn: Binding(
|
||||||
get: { client.credentials.isActive },
|
get: { creds.isActive },
|
||||||
set: { new in
|
set: { new in
|
||||||
client.setActive(new)
|
Task {
|
||||||
|
try? await creds.setActive(flag: new)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
)
|
)
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
print("Tapped account \(client.credentials.bareJid)")
|
print("Tapped account \(creds.bareJid)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,6 +86,11 @@ struct SettingsScreen: View {
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// .onDisappear {
|
||||||
|
// if settingsStore.credentials.isEmpty || settingsStore.credentials.allSatisfy({ !$0.isActive }) {
|
||||||
|
// router.dismissScreenStack()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder private var addAccountSelector: some View {
|
@ViewBuilder private var addAccountSelector: some View {
|
||||||
|
|
|
@ -3,11 +3,12 @@ import SwiftUI
|
||||||
|
|
||||||
struct RootView: View {
|
struct RootView: View {
|
||||||
@EnvironmentObject var clientsStore: ClientsStore
|
@EnvironmentObject var clientsStore: ClientsStore
|
||||||
|
@EnvironmentObject var globalSettingsStore: GlobalSettingsStore
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Group {
|
Group {
|
||||||
if clientsStore.ready {
|
if clientsStore.ready {
|
||||||
if clientsStore.clients.isEmpty || clientsStore.clients.allSatisfy({ !$0.credentials.isActive }) {
|
if clientsStore.clients.isEmpty || globalSettingsStore.credentials.allSatisfy({ !$0.isActive }) {
|
||||||
RouterView { _ in
|
RouterView { _ in
|
||||||
WelcomeScreen()
|
WelcomeScreen()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue