From 666e2b4d5f17cf926a307c7700cbb0306e36cdd8 Mon Sep 17 00:00:00 2001 From: Thomas Ricouard Date: Mon, 16 Jan 2023 19:51:05 +0100 Subject: [PATCH] Refactor macOS / iPad sidebar --- IceCubesApp.xcodeproj/project.pbxproj | 4 ++ IceCubesApp/App/IceCubesApp.swift | 75 ++++++++------------------- IceCubesApp/App/SideBarView.swift | 55 ++++++++++++++++++++ 3 files changed, 81 insertions(+), 53 deletions(-) create mode 100644 IceCubesApp/App/SideBarView.swift diff --git a/IceCubesApp.xcodeproj/project.pbxproj b/IceCubesApp.xcodeproj/project.pbxproj index f3656bbd..f9055bc8 100644 --- a/IceCubesApp.xcodeproj/project.pbxproj +++ b/IceCubesApp.xcodeproj/project.pbxproj @@ -54,6 +54,7 @@ 9FAD85A2297456A400496AB1 /* Env in Frameworks */ = {isa = PBXBuildFile; productRef = 9FAD85A1297456A400496AB1 /* Env */; }; 9FAD85A4297456A800496AB1 /* DesignSystem in Frameworks */ = {isa = PBXBuildFile; productRef = 9FAD85A3297456A800496AB1 /* DesignSystem */; }; 9FAD85A8297582F100496AB1 /* QuickLookRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FAD85A7297582F100496AB1 /* QuickLookRepresentable.swift */; }; + 9FAD85CF2975B68900496AB1 /* SideBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FAD85CE2975B68900496AB1 /* SideBarView.swift */; }; 9FAE4ACB293783B000772766 /* SettingsTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FAE4ACA293783B000772766 /* SettingsTab.swift */; }; 9FAE4ACE29379A5A00772766 /* KeychainSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 9FAE4ACD29379A5A00772766 /* KeychainSwift */; }; 9FBFE63D292A715500C250E9 /* IceCubesApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FBFE63C292A715500C250E9 /* IceCubesApp.swift */; }; @@ -139,6 +140,7 @@ 9FAD858F29743F7400496AB1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 9FAD859629743F7E00496AB1 /* IceCubesShareExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = IceCubesShareExtension.entitlements; sourceTree = ""; }; 9FAD85A7297582F100496AB1 /* QuickLookRepresentable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickLookRepresentable.swift; sourceTree = ""; }; + 9FAD85CE2975B68900496AB1 /* SideBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SideBarView.swift; sourceTree = ""; }; 9FAE4AC8293774FF00772766 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 9FAE4ACA293783B000772766 /* SettingsTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsTab.swift; sourceTree = ""; }; 9FBFE639292A715500C250E9 /* IceCubesApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = IceCubesApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -221,6 +223,7 @@ 9F398AA52935FE8A00A889F2 /* AppRouteur.swift */, 639CDF9B296AC82F00C35E58 /* SafariRouteur.swift */, 9FAD85A7297582F100496AB1 /* QuickLookRepresentable.swift */, + 9FAD85CE2975B68900496AB1 /* SideBarView.swift */, ); path = App; sourceTree = ""; @@ -526,6 +529,7 @@ 9FE151A6293C90F900E9683D /* IconSelectorView.swift in Sources */, 9F2B92FC295DA94500DE16D0 /* InstanceInfoView.swift in Sources */, 9F35DB4C2952005C00B3281A /* MessagesTab.swift in Sources */, + 9FAD85CF2975B68900496AB1 /* SideBarView.swift in Sources */, 9FAE4ACB293783B000772766 /* SettingsTab.swift in Sources */, 9F7335F92968576500AFF0BA /* DisplaySettingsView.swift in Sources */, 9F2A540729699698009B2D7C /* SupportAppView.swift in Sources */, diff --git a/IceCubesApp/App/IceCubesApp.swift b/IceCubesApp/App/IceCubesApp.swift index d29cc5ea..dbc59bde 100644 --- a/IceCubesApp/App/IceCubesApp.swift +++ b/IceCubesApp/App/IceCubesApp.swift @@ -25,6 +25,7 @@ struct IceCubesApp: App { @State private var selectedTab: Tab = .timeline @State private var selectSidebarItem: Tab? = .timeline @State private var popToRootTab: Tab = .other + @State private var sideBarLoadedTabs: [Tab] = [] private var availableTabs: [Tab] { appAccountsManager.currentClient.isAuth ? Tab.loggedInTabs() : Tab.loggedOutTab() @@ -81,48 +82,31 @@ struct IceCubesApp: App { } private var sidebarView: some View { - HStack(spacing: 0) { - VStack(alignment: .center) { - if let account = currentAccount.account { - AvatarView(url: account.avatar) - .frame(width: 70, height: 50) - .background(selectedTab == .profile ? theme.secondaryBackgroundColor : .clear) - .onTapGesture { - selectedTab = .profile - } - } + SideBarView(selectedTab: $selectedTab, + popToRootTab: $popToRootTab, + tabs: availableTabs) { selectedTab in + ZStack { ForEach(availableTabs) { tab in - Button { - if tab == selectedTab { - popToRootTab = .other - DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) { - popToRootTab = tab - } - } - selectedTab = tab - } label: { - Image(systemName: tab.iconName) - .resizable() - .aspectRatio(contentMode: .fit) - .frame(width: 24, height: 24) - .foregroundColor(tab == selectedTab ? theme.tintColor : .gray) + if let account = currentAccount.account { + AccountDetailView(account: account) + .opacity(selectedTab == .profile ? 1 : 0) + } + if tab == selectedTab || sideBarLoadedTabs.contains(tab) { + tab + .makeContentView(popToRootTab: $popToRootTab) + .opacity(tab == selectedTab ? 1 : 0) + .id(tab) + .onAppear { + if !sideBarLoadedTabs.contains(tab) { + sideBarLoadedTabs.append(tab) + } + } + } else { + EmptyView() } - .frame(width: 70, height: 50) - .background(tab == selectedTab ? theme.secondaryBackgroundColor : .clear) } - Spacer() - } - .frame(width: 70) - .background(.clear) - Divider() - .edgesIgnoringSafeArea(.top) - if selectedTab == .profile, let account = currentAccount.account { - AccountDetailView(account: account) - } else { - selectedTab.makeContentView(popToRootTab: $popToRootTab) } } - .background(.thinMaterial) } private var tabBarView: some View { @@ -149,22 +133,7 @@ struct IceCubesApp: App { } } } - - private var splitView: some View { - NavigationSplitView { - List(availableTabs, selection: $selectSidebarItem) { tab in - NavigationLink(value: tab) { - tab.label - } - } - .scrollContentBackground(.hidden) - .background(theme.secondaryBackgroundColor) - .navigationSplitViewColumnWidth(200) - } detail: { - selectSidebarItem?.makeContentView(popToRootTab: $popToRootTab) - } - } - + private func setNewClientsInEnv(client: Client) { currentAccount.setClient(client: client) currentInstance.setClient(client: client) diff --git a/IceCubesApp/App/SideBarView.swift b/IceCubesApp/App/SideBarView.swift new file mode 100644 index 00000000..83498ecc --- /dev/null +++ b/IceCubesApp/App/SideBarView.swift @@ -0,0 +1,55 @@ +import SwiftUI +import Env +import Account +import DesignSystem + +struct SideBarView: View { + @EnvironmentObject private var currentAccount: CurrentAccount + @EnvironmentObject private var theme: Theme + + @Binding var selectedTab: Tab + @Binding var popToRootTab: Tab + var tabs: [Tab] + @ViewBuilder var content: (Tab) -> Content + + var body: some View { + HStack(spacing: 0) { + VStack(alignment: .center) { + if let account = currentAccount.account { + AvatarView(url: account.avatar) + .frame(width: 70, height: 50) + .background(selectedTab == .profile ? theme.secondaryBackgroundColor : .clear) + .onTapGesture { + selectedTab = .profile + } + } + ForEach(tabs) { tab in + Button { + if tab == selectedTab { + popToRootTab = .other + DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) { + popToRootTab = tab + } + } + selectedTab = tab + } label: { + Image(systemName: tab.iconName) + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: 24, height: 24) + .foregroundColor(tab == selectedTab ? theme.tintColor : .gray) + } + .frame(width: 70, height: 50) + .background(tab == selectedTab ? theme.secondaryBackgroundColor : .clear) + } + Spacer() + } + .frame(width: 70) + .background(.clear) + Divider() + .edgesIgnoringSafeArea(.top) + content(selectedTab) + } + .background(.thinMaterial) + } +}