diff --git a/Nio.xcodeproj/project.pbxproj b/Nio.xcodeproj/project.pbxproj index f010d43a..e1e3e6c9 100644 --- a/Nio.xcodeproj/project.pbxproj +++ b/Nio.xcodeproj/project.pbxproj @@ -29,6 +29,8 @@ 3984654823B8D809006C173B /* SDWebImageSwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = 3984654723B8D809006C173B /* SDWebImageSwiftUI */; }; 39BA0721240B1A2600FD28C6 /* AccountStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39BA0720240B1A2600FD28C6 /* AccountStore.swift */; }; 39BA0723240B3C9A00FD28C6 /* MXCredentials+Keychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39BA0722240B3C9A00FD28C6 /* MXCredentials+Keychain.swift */; }; + 39BA0725240B4E8D00FD28C6 /* AppSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39BA0724240B4E8D00FD28C6 /* AppSettings.swift */; }; + 39BA0727240B534600FD28C6 /* Color+allAccent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39BA0726240B534600FD28C6 /* Color+allAccent.swift */; }; 39C931DD2384328A004449E1 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39C931DC2384328A004449E1 /* AppDelegate.swift */; }; 39C931DF2384328A004449E1 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39C931DE2384328A004449E1 /* SceneDelegate.swift */; }; 39C931E12384328A004449E1 /* RootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39C931E02384328A004449E1 /* RootView.swift */; }; @@ -96,6 +98,8 @@ 3984654423B7ECBA006C173B /* MXURL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXURL.swift; sourceTree = ""; }; 39BA0720240B1A2600FD28C6 /* AccountStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountStore.swift; sourceTree = ""; }; 39BA0722240B3C9A00FD28C6 /* MXCredentials+Keychain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MXCredentials+Keychain.swift"; sourceTree = ""; }; + 39BA0724240B4E8D00FD28C6 /* AppSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSettings.swift; sourceTree = ""; }; + 39BA0726240B534600FD28C6 /* Color+allAccent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Color+allAccent.swift"; sourceTree = ""; }; 39C931D92384328A004449E1 /* Nio.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Nio.app; sourceTree = BUILT_PRODUCTS_DIR; }; 39C931DC2384328A004449E1 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 39C931DE2384328A004449E1 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -156,6 +160,7 @@ isa = PBXGroup; children = ( 3902B8A22395935600698B87 /* SettingsView.swift */, + 39BA0724240B4E8D00FD28C6 /* AppSettings.swift */, ); path = Settings; sourceTree = ""; @@ -308,6 +313,7 @@ CAC46D7623A6CB6C0079C24F /* MXEventType+Equatable.swift */, CAC46D6223A278F40079C24F /* PreviewProvider+Enumeration.swift */, 39BA0722240B3C9A00FD28C6 /* MXCredentials+Keychain.swift */, + 39BA0726240B534600FD28C6 /* Color+allAccent.swift */, ); path = Extensions; sourceTree = ""; @@ -604,12 +610,14 @@ 39BA0723240B3C9A00FD28C6 /* MXCredentials+Keychain.swift in Sources */, CAC46D6323A278F40079C24F /* PreviewProvider+Enumeration.swift in Sources */, 392389D6238F3EB200B2E1DF /* NIORoomSummary.swift in Sources */, + 39BA0725240B4E8D00FD28C6 /* AppSettings.swift in Sources */, 39D166C82385C832006DD257 /* EventContainerView.swift in Sources */, CAC46D6B23A55E940079C24F /* PeekableIterator.swift in Sources */, CAC46D5823A272D10079C24F /* MessageViewModel.swift in Sources */, 39C931DF2384328A004449E1 /* SceneDelegate.swift in Sources */, 3902B8A32395935600698B87 /* SettingsView.swift in Sources */, 39C931F523846966004449E1 /* LoginView.swift in Sources */, + 39BA0727240B534600FD28C6 /* Color+allAccent.swift in Sources */, CAC46D5D23A276700079C24F /* Color+Named.swift in Sources */, 3902B89E2393FE8200698B87 /* GenericEventView.swift in Sources */, 392389982388998F00B2E1DF /* ActivityIndicator.swift in Sources */, diff --git a/Nio/Conversations/RecentRoomsView.swift b/Nio/Conversations/RecentRoomsView.swift index fa483b2b..378faa5a 100644 --- a/Nio/Conversations/RecentRoomsView.swift +++ b/Nio/Conversations/RecentRoomsView.swift @@ -3,6 +3,7 @@ import SwiftMatrixSDK struct RecentRoomsContainerView: View { @EnvironmentObject var store: AccountStore + @EnvironmentObject var settings: AppSettings @State private var selectedNavigationItem: SelectedNavigationItem? @@ -13,6 +14,8 @@ struct RecentRoomsContainerView: View { NavigationSheet(selectedItem: $0) // This really shouldn't be necessary. SwiftUI bug? .environmentObject(self.store) + .environmentObject(self.settings) + .accentColor(self.settings.accentColor) } .onAppear { self.store.startListeningForRoomEvents() @@ -74,7 +77,7 @@ private struct NavigationSheet: View { switch selectedItem { case .settings: return AnyView( - SettingsView() + SettingsContainerView() ) case .newMessage: return AnyView( diff --git a/Nio/Extensions/Color+allAccent.swift b/Nio/Extensions/Color+allAccent.swift new file mode 100644 index 00000000..ea9d0960 --- /dev/null +++ b/Nio/Extensions/Color+allAccent.swift @@ -0,0 +1,29 @@ +import SwiftUI + +extension Color { + static var allAccentOptions: [Color] { + [ + .purple, + .blue, + .red, + .orange, + .green, + .gray, + .yellow + ] + } + + init?(description: String) { + switch description { + case "purple": self = .purple + case "blue": self = .blue + case "red": self = .red + case "orange": self = .orange + case "green": self = .green + case "gray": self = .gray + case "yellow": self = .yellow + default: self = .purple + } + } +} + diff --git a/Nio/SceneDelegate.swift b/Nio/SceneDelegate.swift index 77d67f82..99331775 100644 --- a/Nio/SceneDelegate.swift +++ b/Nio/SceneDelegate.swift @@ -13,10 +13,12 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). let accountStore = AccountStore() + let appSettings = AppSettings() let rootView = RootView() .environmentObject(accountStore) - .accentColor(.purple) + .environmentObject(appSettings) + .accentColor(appSettings.accentColor) // Use a UIHostingController as window root view controller. if let windowScene = scene as? UIWindowScene { diff --git a/Nio/Settings/AppSettings.swift b/Nio/Settings/AppSettings.swift new file mode 100644 index 00000000..19169c27 --- /dev/null +++ b/Nio/Settings/AppSettings.swift @@ -0,0 +1,19 @@ +import Foundation +import SwiftUI +import Combine + +class AppSettings: ObservableObject { + var accentColor: Color { + get { + guard + let stored = UserDefaults.standard.string(forKey: "accentColor"), + let color = Color(description: stored) + else { return .purple } + return color + } + set { + UserDefaults.standard.set(newValue.description, forKey: "accentColor") + objectWillChange.send() + } + } +} diff --git a/Nio/Settings/SettingsView.swift b/Nio/Settings/SettingsView.swift index 1438cb8e..6f86cbde 100644 --- a/Nio/Settings/SettingsView.swift +++ b/Nio/Settings/SettingsView.swift @@ -1,20 +1,43 @@ import SwiftUI -struct SettingsView: View { +struct SettingsContainerView: View { @EnvironmentObject var store: AccountStore + @EnvironmentObject var settings: AppSettings + + var body: some View { + SettingsView(accentColor: $settings.accentColor, logoutAction: { self.store.logout() }) + } +} + +struct SettingsView: View { + @Binding var accentColor: Color + var logoutAction: () -> Void var body: some View { NavigationView { - List { + Form { + Section { + Picker(selection: $accentColor, label: Text("Accent Color")) { + ForEach(Color.allAccentOptions, id: \.self) { color in + HStack { + Circle() + .frame(width: 20) + .foregroundColor(color) + Text(color.description.capitalized) + } + .tag(color) + } + } + } + Section { Button(action: { - self.store.logout() + self.logoutAction() }, label: { Text("Log Out") }) } } - .listStyle(GroupedListStyle()) .navigationBarTitle("Settings", displayMode: .inline) } } @@ -22,6 +45,6 @@ struct SettingsView: View { struct SettingsView_Previews: PreviewProvider { static var previews: some View { - SettingsView() + SettingsView(accentColor: .constant(.purple), logoutAction: {}) } }