IceCubes/IceCubesApp/App/SideBarView.swift

144 lines
4.2 KiB
Swift
Raw Normal View History

2023-01-16 19:51:05 +01:00
import Account
2023-01-16 21:15:33 +01:00
import AppAccount
2023-01-17 11:36:01 +01:00
import DesignSystem
import Env
import SwiftUI
2023-01-16 19:51:05 +01:00
struct SideBarView<Content: View>: View {
@EnvironmentObject private var appAccounts: AppAccountsManager
2023-01-16 19:51:05 +01:00
@EnvironmentObject private var currentAccount: CurrentAccount
@EnvironmentObject private var theme: Theme
@EnvironmentObject private var watcher: StreamWatcher
@EnvironmentObject private var userPreferences: UserPreferences
2023-01-16 19:51:05 +01:00
@Binding var selectedTab: Tab
@Binding var popToRootTab: Tab
var tabs: [Tab]
@ObservedObject var routerPath = RouterPath()
2023-01-16 21:15:33 +01:00
@ViewBuilder var content: () -> Content
2023-01-17 11:36:01 +01:00
private func badgeFor(tab: Tab) -> Int {
if tab == .notifications && selectedTab != tab {
return watcher.unreadNotificationsCount + userPreferences.pushNotificationsCount
}
return 0
}
private var profileView: some View {
Button {
selectedTab = .profile
} label: {
AppAccountsSelectorView(routerPath: RouterPath(),
accountCreationEnabled: false,
avatarSize: .status)
}
.frame(width: .sidebarWidth, height: 60)
.background(selectedTab == .profile ? theme.secondaryBackgroundColor : .clear)
}
private func makeIconForTab(tab: Tab) -> some View {
ZStack(alignment: .topTrailing) {
Image(systemName: tab.iconName)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 24, height: 24)
.foregroundColor(tab == selectedTab ? theme.tintColor : theme.labelColor)
if let badge = badgeFor(tab: tab), badge > 0 {
ZStack {
Circle()
.fill(.red)
Text(String(badge))
.foregroundColor(.white)
2023-01-17 21:08:05 +01:00
.font(.caption2)
}
.frame(width: 20, height: 20)
.offset(x: 10, y: -10)
}
}
.contentShape(Rectangle())
.frame(width: .sidebarWidth, height: 50)
}
private var postButton: some View {
Button {
routerPath.presentedSheet = .newStatusEditor(visibility: userPreferences.serverPreferences?.postVisibility ?? .pub)
} label: {
Image(systemName: "square.and.pencil")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 20, height: 30)
}
.buttonStyle(.borderedProminent)
.keyboardShortcut("n", modifiers: .command)
}
private func makeAccountButton(account: AppAccount) -> some View {
Button {
if account.id == appAccounts.currentAccount.id {
selectedTab = .profile
} else {
withAnimation {
appAccounts.currentAccount = account
}
}
} label: {
AppAccountView(viewModel: .init(appAccount: account, isCompact: true))
}
.frame(width: .sidebarWidth, height: 50)
.padding(.vertical, 8)
.background(selectedTab == .profile && account.id == appAccounts.currentAccount.id ?
theme.secondaryBackgroundColor : .clear)
}
private var tabsView: some View {
ForEach(tabs) { tab in
Button {
if tab == selectedTab {
popToRootTab = .other
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
popToRootTab = tab
}
}
selectedTab = tab
if tab == .notifications {
watcher.unreadNotificationsCount = 0
userPreferences.pushNotificationsCount = 0
}
} label: {
makeIconForTab(tab: tab)
}
.background(tab == selectedTab ? theme.secondaryBackgroundColor : .clear)
}
}
2023-01-16 19:51:05 +01:00
var body: some View {
HStack(spacing: 0) {
ScrollView {
VStack(alignment: .center) {
if appAccounts.availableAccounts.isEmpty {
tabsView
} else {
ForEach(appAccounts.availableAccounts) { account in
makeAccountButton(account: account)
if account.id == appAccounts.currentAccount.id {
tabsView
2023-01-16 19:51:05 +01:00
}
}
}
postButton
.padding(.top, 12)
Spacer()
2023-01-16 19:51:05 +01:00
}
}
.frame(width: .sidebarWidth)
.scrollContentBackground(.hidden)
.background(.thinMaterial)
2023-01-16 19:51:05 +01:00
Divider()
.edgesIgnoringSafeArea(.top)
2023-01-16 21:15:33 +01:00
content()
2023-01-16 19:51:05 +01:00
}
.background(.thinMaterial)
.withSheetDestinations(sheetDestinations: $routerPath.presentedSheet)
2023-01-16 19:51:05 +01:00
}
}