Skip to content

Commit 4150067

Browse files
authored
Merge pull request #321 from niochat/matrixcore-menu
Sidebar menu showing accounts
2 parents 7d721a2 + cf19967 commit 4150067

File tree

7 files changed

+271
-27
lines changed

7 files changed

+271
-27
lines changed
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
//
2+
// MenuAccountPickerView.swift
3+
// Nio
4+
//
5+
// Created by Finn Behrens on 30.03.22.
6+
//
7+
8+
import MatrixCore
9+
import NioKit
10+
import SwiftUI
11+
12+
public struct MenuAccountPickerContainerView: View {
13+
@Binding var currentAccount: String
14+
15+
@AppStorage("showAccountsInPicker") var showAccounts: Bool = false
16+
17+
public var body: some View {
18+
DisclosureGroup("Accounts", isExpanded: $showAccounts) {
19+
MenuAccountPickerView(currentAccount: $currentAccount)
20+
.frame(maxWidth: .infinity, alignment: .leading)
21+
.padding(.top)
22+
}
23+
}
24+
}
25+
26+
public struct MenuAccountPickerView: View {
27+
@Binding var currentAccount: String
28+
29+
@FetchRequest(sortDescriptors: []) var accounts: FetchedResults<MatrixAccount>
30+
31+
init(currentAccount: Binding<String>) {
32+
_currentAccount = currentAccount
33+
34+
_accounts = FetchRequest<MatrixAccount>(sortDescriptors: [NSSortDescriptor(key: "userID", ascending: true)], predicate: NSPredicate(format: "userID != %@", currentAccount.wrappedValue))
35+
}
36+
37+
public var body: some View {
38+
VStack(alignment: .leading) {
39+
ForEach(accounts, id: \.userID) { account in
40+
Button {
41+
print("switching account to \(account.userID ?? "Unknown user")")
42+
currentAccount = account.userID ?? ""
43+
} label: {
44+
MenuAccountPickerAccountView(account: account).tag(account.userID ?? "Unknown user")
45+
}
46+
.padding(.vertical)
47+
}
48+
49+
Button(action: {
50+
// TODO: implement add account screen
51+
NioAccountStore.logger.fault("Not yet implemented: Add account")
52+
}) {
53+
HStack {
54+
Image(systemName: "plus")
55+
.foregroundColor(.gray)
56+
.imageScale(.large)
57+
Text("Add Account")
58+
.foregroundColor(.gray)
59+
.font(.body)
60+
}
61+
}
62+
}
63+
}
64+
}
65+
66+
struct MenuAccountPickerAccountView: View {
67+
let account: MatrixAccount
68+
69+
var body: some View {
70+
Label {
71+
VStack(alignment: .leading) {
72+
Text(account.displayName ?? account.userID ?? "Unknown user")
73+
.foregroundColor(.gray)
74+
.font(.headline)
75+
if account.displayName != nil {
76+
Text(account.userID ?? "Unknown mxid")
77+
.foregroundColor(.gray)
78+
.font(.subheadline)
79+
}
80+
}
81+
} icon: {
82+
// TODO: avatar
83+
Image(systemName: "person")
84+
.foregroundColor(.gray)
85+
.imageScale(.large)
86+
}
87+
}
88+
}
89+
90+
struct MenuAccountPickerView_Previews: PreviewProvider {
91+
static var previews: some View {
92+
Group {
93+
MenuAccountPickerView(currentAccount: .constant("@amir_sanders:example.com"))
94+
.previewLayout(.fixed(width: 300, height: 200))
95+
96+
MenuAccountPickerContainerView(currentAccount: .constant("@amir_sanders:example.com"), showAccounts: true)
97+
.previewLayout(.fixed(width: 300, height: 200))
98+
.padding()
99+
}
100+
.environment(\.managedObjectContext, MatrixStore.preview.viewContext)
101+
}
102+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//
2+
// MenuOwnAccountView.swift
3+
// NioUIKit_iOS
4+
//
5+
// Created by Finn Behrens on 30.03.22.
6+
//
7+
8+
import MatrixCore
9+
import SwiftUI
10+
11+
struct MenuOwnAccountContainerView: View {
12+
let currentAccount: String
13+
14+
var body: some View {
15+
MenuOwnAccountView(currentAccount: currentAccount)
16+
}
17+
}
18+
19+
struct MenuOwnAccountView: View {
20+
let currentAccount: String
21+
22+
@FetchRequest(sortDescriptors: []) var accounts: FetchedResults<MatrixAccount>
23+
24+
init(currentAccount: String) {
25+
self.currentAccount = currentAccount
26+
27+
_accounts = FetchRequest<MatrixAccount>(sortDescriptors: [NSSortDescriptor(key: "userID", ascending: true)], predicate: NSPredicate(format: "userID == %@", currentAccount))
28+
}
29+
30+
var body: some View {
31+
VStack(alignment: .leading) {
32+
ForEach(accounts, id: \.userID) { account in
33+
NavigationLink(destination: {
34+
Text("Account")
35+
}) {
36+
MenuAccountPickerAccountView(account: account)
37+
}
38+
}
39+
// TODO: add a banner if no accounts are returned, because of an Invalid currentAccount?
40+
}
41+
}
42+
}
43+
44+
struct MenuOwnAccountView_Previews: PreviewProvider {
45+
static var previews: some View {
46+
Group {
47+
MenuOwnAccountView(currentAccount: "@amir_sanders:example.com")
48+
.environment(\.managedObjectContext, MatrixStore.preview.viewContext)
49+
.previewLayout(.fixed(width: 300, height: 60))
50+
}
51+
}
52+
}

NioUIKit/Menu/MenuView.swift

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
//
2+
// MenuView.swift
3+
// Nio
4+
//
5+
// Created by Finn Behrens on 30.03.22.
6+
//
7+
8+
import MatrixCore
9+
import SwiftUI
10+
11+
public struct MenuContainerView<Content: View>: View {
12+
@Binding var currentAccount: String
13+
14+
@State var showMenu: Bool = false
15+
16+
let content: () -> Content
17+
18+
var dragGesture: some Gesture {
19+
DragGesture()
20+
.onEnded { vector in
21+
if vector.translation.width < -100 {
22+
withAnimation {
23+
self.showMenu = false
24+
}
25+
}
26+
}
27+
}
28+
29+
public init(currentAccount: Binding<String>, content: @escaping () -> Content) {
30+
_currentAccount = currentAccount
31+
self.content = content
32+
}
33+
34+
public var body: some View {
35+
GeometryReader { geometry in
36+
ZStack(alignment: .leading) {
37+
content()
38+
.frame(width: geometry.size.width, height: geometry.size.height)
39+
.offset(x: self.showMenu ? geometry.size.width * 0.8 : 0)
40+
.disabled(self.showMenu)
41+
if self.showMenu {
42+
MenuView(currentAccount: $currentAccount)
43+
.frame(width: geometry.size.width * 0.8, height: geometry.size.height)
44+
}
45+
}
46+
.gesture(dragGesture)
47+
}
48+
.toolbar {
49+
ToolbarItem(placement: .navigationBarLeading) {
50+
Button(action: {
51+
withAnimation {
52+
self.showMenu.toggle()
53+
}
54+
}) {
55+
Image(systemName: "line.horizontal.3")
56+
.imageScale(.large)
57+
.rotationEffect(self.showMenu ? .degrees(90) : .zero)
58+
}
59+
}
60+
}
61+
}
62+
}
63+
64+
struct MenuView: View {
65+
@Binding var currentAccount: String
66+
67+
var body: some View {
68+
VStack(alignment: .leading) {
69+
MenuOwnAccountContainerView(currentAccount: currentAccount)
70+
.padding()
71+
72+
// TODO: collapse view
73+
MenuAccountPickerContainerView(currentAccount: $currentAccount)
74+
75+
Spacer(minLength: 0)
76+
}
77+
.padding()
78+
.frame(maxWidth: .infinity, alignment: .leading)
79+
.background(Color(red: 32 / 255, green: 32 / 255, blue: 32 / 255))
80+
}
81+
}
82+
83+
struct MenuView_Previews: PreviewProvider {
84+
static var previews: some View {
85+
Group {
86+
MenuView(currentAccount: .constant("@preview:example.com"))
87+
88+
MenuContainerView(currentAccount: .constant("@preview:example.com")) {
89+
Text("foo")
90+
}
91+
92+
MenuContainerView(currentAccount: .constant("@preview:example.com")) {
93+
Text("foo")
94+
}
95+
}
96+
}
97+
}

configs/Base.xcconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
NIO_NAMESPACE = chat.nio
1212
DEVELOPMENT_TEAM = Z123456789
13+
MARKETING_VERSION = 0.1.0
1314

1415
APPGROUP = $(NIO_NAMESPACE)
1516

nio/LoggedInRootView.swift

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import MatrixCore
99
import NioKit
10+
import NioUIKit
1011
import SwiftUI
1112

1213
struct LoggedInRootView: View {
@@ -16,30 +17,20 @@ struct LoggedInRootView: View {
1617

1718
@EnvironmentObject var store: NioAccountStore
1819

20+
@AppStorage("LastSelectedAccount") var currentSelectedAccountName: String = ""
21+
22+
@State var currentSelectedAccount: NioAccount?
23+
1924
var body: some View {
20-
VStack {
21-
ForEach(Array(store.accounts.keys), id: \.self) { key in
22-
Button((store.accounts[key]?.displayName ?? store.accounts[key]?.userID.FQMXID) ?? "??") {
23-
Task {
24-
do {
25-
try await store.logout(accountName: key)
26-
} catch {
27-
print(error)
28-
}
29-
print("foo")
30-
}
31-
}
32-
}
33-
Button("delete", role: .destructive) {
34-
Task {
35-
try? await self.context.perform {
36-
let accounts = try self.context.fetch(MatrixAccount.fetchRequest())
37-
for account in accounts {
38-
self.context.delete(account)
39-
}
40-
try self.context.save()
41-
}
25+
NavigationView {
26+
MenuContainerView(currentAccount: $currentSelectedAccountName) {
27+
Text("foo")
28+
}.task {
29+
if self.currentSelectedAccount == nil {
30+
self.currentSelectedAccountName = store.accounts.keys.first ?? ""
4231
}
32+
33+
self.currentSelectedAccount = store.accounts[self.currentSelectedAccountName]
4334
}
4435
}
4536
}

nio/RootView.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ import NioUIKit
1111
import SwiftUI
1212

1313
struct RootView: View {
14-
@ObservedObject var account = NioAccountStore.shared
14+
@ObservedObject var store = NioAccountStore.shared
1515

1616
var body: some View {
17-
if account.hasAccount {
17+
if store.hasAccount {
1818
LoggedInRootView()
1919
.environment(\.managedObjectContext, MatrixStore.shared.viewContext)
20-
.environmentObject(account)
20+
.environmentObject(store)
2121
} else {
2222
NavigationView {
2323
VStack {
@@ -29,7 +29,7 @@ struct RootView: View {
2929
NavigationLink("Login") {
3030
LoginContainerView { homeserver, response in
3131
Task {
32-
await account.addAccount(homeserver: homeserver, login: response)
32+
await store.addAccount(homeserver: homeserver, login: response)
3333
}
3434
}
3535
}

project.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ targets:
3232
- NioKit
3333
dependencies:
3434
- package: MatrixCore
35-
product: MatrixClient
35+
product: MatrixCore
3636
configFiles:
3737
Debug: configs/NioKit.xcconfig
3838
Release: configs/NioKit.xcconfig
@@ -62,6 +62,7 @@ targets:
6262
dependencies:
6363
- target: NioKit_iOS
6464
- target: NioUIKit_iOS
65+
scheme: {}
6566
Nio_macOS:
6667
platform: macOS
6768
type: application

0 commit comments

Comments
 (0)