mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2025-01-27 12:59:17 +01:00
Refactor App level to App + App View -> Slideover = phone layout on iPad
This commit is contained in:
parent
84898c3b8e
commit
c328c6c0be
@ -58,6 +58,8 @@
|
|||||||
9F55C68D2955968700F94077 /* ExploreTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F55C68C2955968700F94077 /* ExploreTab.swift */; };
|
9F55C68D2955968700F94077 /* ExploreTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F55C68C2955968700F94077 /* ExploreTab.swift */; };
|
||||||
9F55C6902955993C00F94077 /* Explore in Frameworks */ = {isa = PBXBuildFile; productRef = 9F55C68F2955993C00F94077 /* Explore */; };
|
9F55C6902955993C00F94077 /* Explore in Frameworks */ = {isa = PBXBuildFile; productRef = 9F55C68F2955993C00F94077 /* Explore */; };
|
||||||
9F5E581929545BE700A53960 /* Env in Frameworks */ = {isa = PBXBuildFile; productRef = 9F5E581829545BE700A53960 /* Env */; };
|
9F5E581929545BE700A53960 /* Env in Frameworks */ = {isa = PBXBuildFile; productRef = 9F5E581829545BE700A53960 /* Env */; };
|
||||||
|
9F6028562B3F36AE00476078 /* AppView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F6028552B3F36AE00476078 /* AppView.swift */; };
|
||||||
|
9F6028582B3F3B7600476078 /* ToolbarTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F6028572B3F3B7600476078 /* ToolbarTab.swift */; };
|
||||||
9F654BEF299AC45B00D27FA5 /* ReportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F654BEE299AC45B00D27FA5 /* ReportView.swift */; };
|
9F654BEF299AC45B00D27FA5 /* ReportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F654BEE299AC45B00D27FA5 /* ReportView.swift */; };
|
||||||
9F7335EA2966B3F800AFF0BA /* Conversations in Frameworks */ = {isa = PBXBuildFile; productRef = 9F7335E92966B3F800AFF0BA /* Conversations */; };
|
9F7335EA2966B3F800AFF0BA /* Conversations in Frameworks */ = {isa = PBXBuildFile; productRef = 9F7335E92966B3F800AFF0BA /* Conversations */; };
|
||||||
9F7335ED2967463400AFF0BA /* AVKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F7335EB2967461B00AFF0BA /* AVKit.framework */; };
|
9F7335ED2967463400AFF0BA /* AVKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F7335EB2967461B00AFF0BA /* AVKit.framework */; };
|
||||||
@ -84,8 +86,6 @@
|
|||||||
9FB143D12983104700A27BB1 /* glass.caf in Resources */ = {isa = PBXBuildFile; fileRef = 9F2A542B296B1177009B2D7C /* glass.caf */; };
|
9FB143D12983104700A27BB1 /* glass.caf in Resources */ = {isa = PBXBuildFile; fileRef = 9F2A542B296B1177009B2D7C /* glass.caf */; };
|
||||||
9FB143D22983104A00A27BB1 /* glass.wav in Resources */ = {isa = PBXBuildFile; fileRef = 9F2A542D296B1CC0009B2D7C /* glass.wav */; };
|
9FB143D22983104A00A27BB1 /* glass.wav in Resources */ = {isa = PBXBuildFile; fileRef = 9F2A542D296B1CC0009B2D7C /* glass.wav */; };
|
||||||
9FB183222AE9268800BBB692 /* IceCubesApp+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FB183212AE9268800BBB692 /* IceCubesApp+Menu.swift */; };
|
9FB183222AE9268800BBB692 /* IceCubesApp+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FB183212AE9268800BBB692 /* IceCubesApp+Menu.swift */; };
|
||||||
9FB183252AE926E900BBB692 /* IceCubesApp+Sidebar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FB183242AE926E900BBB692 /* IceCubesApp+Sidebar.swift */; };
|
|
||||||
9FB183272AE9279F00BBB692 /* IceCubesApp+Tabbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FB183262AE9279F00BBB692 /* IceCubesApp+Tabbar.swift */; };
|
|
||||||
9FB183292AE9449100BBB692 /* IceCubesApp+Scene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FB183282AE9449100BBB692 /* IceCubesApp+Scene.swift */; };
|
9FB183292AE9449100BBB692 /* IceCubesApp+Scene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FB183282AE9449100BBB692 /* IceCubesApp+Scene.swift */; };
|
||||||
9FBFE63D292A715500C250E9 /* IceCubesApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FBFE63C292A715500C250E9 /* IceCubesApp.swift */; };
|
9FBFE63D292A715500C250E9 /* IceCubesApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FBFE63C292A715500C250E9 /* IceCubesApp.swift */; };
|
||||||
9FBFE64E292A72BD00C250E9 /* Network in Frameworks */ = {isa = PBXBuildFile; productRef = 9FBFE64D292A72BD00C250E9 /* Network */; };
|
9FBFE64E292A72BD00C250E9 /* Network in Frameworks */ = {isa = PBXBuildFile; productRef = 9FBFE64D292A72BD00C250E9 /* Network */; };
|
||||||
@ -206,6 +206,8 @@
|
|||||||
9F55C68C2955968700F94077 /* ExploreTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExploreTab.swift; sourceTree = "<group>"; };
|
9F55C68C2955968700F94077 /* ExploreTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExploreTab.swift; sourceTree = "<group>"; };
|
||||||
9F55C68E295598F900F94077 /* Explore */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Explore; path = Packages/Explore; sourceTree = "<group>"; };
|
9F55C68E295598F900F94077 /* Explore */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Explore; path = Packages/Explore; sourceTree = "<group>"; };
|
||||||
9F5E581729545B5500A53960 /* Env */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Env; path = Packages/Env; sourceTree = "<group>"; };
|
9F5E581729545B5500A53960 /* Env */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Env; path = Packages/Env; sourceTree = "<group>"; };
|
||||||
|
9F6028552B3F36AE00476078 /* AppView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppView.swift; sourceTree = "<group>"; };
|
||||||
|
9F6028572B3F3B7600476078 /* ToolbarTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolbarTab.swift; sourceTree = "<group>"; };
|
||||||
9F62216829A68DA4007B77CA /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
9F62216829A68DA4007B77CA /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||||
9F654BEE299AC45B00D27FA5 /* ReportView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportView.swift; sourceTree = "<group>"; };
|
9F654BEE299AC45B00D27FA5 /* ReportView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportView.swift; sourceTree = "<group>"; };
|
||||||
9F7335E82966B3DC00AFF0BA /* Conversations */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Conversations; path = Packages/Conversations; sourceTree = "<group>"; };
|
9F7335E82966B3DC00AFF0BA /* Conversations */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Conversations; path = Packages/Conversations; sourceTree = "<group>"; };
|
||||||
@ -225,8 +227,6 @@
|
|||||||
9FAE4AC8293774FF00772766 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
|
9FAE4AC8293774FF00772766 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
|
||||||
9FAE4ACA293783B000772766 /* SettingsTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsTab.swift; sourceTree = "<group>"; };
|
9FAE4ACA293783B000772766 /* SettingsTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsTab.swift; sourceTree = "<group>"; };
|
||||||
9FB183212AE9268800BBB692 /* IceCubesApp+Menu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "IceCubesApp+Menu.swift"; sourceTree = "<group>"; };
|
9FB183212AE9268800BBB692 /* IceCubesApp+Menu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "IceCubesApp+Menu.swift"; sourceTree = "<group>"; };
|
||||||
9FB183242AE926E900BBB692 /* IceCubesApp+Sidebar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "IceCubesApp+Sidebar.swift"; sourceTree = "<group>"; };
|
|
||||||
9FB183262AE9279F00BBB692 /* IceCubesApp+Tabbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "IceCubesApp+Tabbar.swift"; sourceTree = "<group>"; };
|
|
||||||
9FB183282AE9449100BBB692 /* IceCubesApp+Scene.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "IceCubesApp+Scene.swift"; sourceTree = "<group>"; };
|
9FB183282AE9449100BBB692 /* IceCubesApp+Scene.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "IceCubesApp+Scene.swift"; sourceTree = "<group>"; };
|
||||||
9FBFE639292A715500C250E9 /* Ice Cubes.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Ice Cubes.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
9FBFE639292A715500C250E9 /* Ice Cubes.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Ice Cubes.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
9FBFE63C292A715500C250E9 /* IceCubesApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IceCubesApp.swift; sourceTree = "<group>"; };
|
9FBFE63C292A715500C250E9 /* IceCubesApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IceCubesApp.swift; sourceTree = "<group>"; };
|
||||||
@ -432,6 +432,7 @@
|
|||||||
9F4A48182976B21900A1A038 /* ProfileTab.swift */,
|
9F4A48182976B21900A1A038 /* ProfileTab.swift */,
|
||||||
9F15D5FF2B3D6A850008C220 /* NavigationTab.swift */,
|
9F15D5FF2B3D6A850008C220 /* NavigationTab.swift */,
|
||||||
9F15D6032B3DC2180008C220 /* NavigationSheet.swift */,
|
9F15D6032B3DC2180008C220 /* NavigationSheet.swift */,
|
||||||
|
9F6028572B3F3B7600476078 /* ToolbarTab.swift */,
|
||||||
);
|
);
|
||||||
path = Tabs;
|
path = Tabs;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -441,9 +442,8 @@
|
|||||||
children = (
|
children = (
|
||||||
9FBFE63C292A715500C250E9 /* IceCubesApp.swift */,
|
9FBFE63C292A715500C250E9 /* IceCubesApp.swift */,
|
||||||
9FB183212AE9268800BBB692 /* IceCubesApp+Menu.swift */,
|
9FB183212AE9268800BBB692 /* IceCubesApp+Menu.swift */,
|
||||||
9FB183242AE926E900BBB692 /* IceCubesApp+Sidebar.swift */,
|
|
||||||
9FB183262AE9279F00BBB692 /* IceCubesApp+Tabbar.swift */,
|
|
||||||
9FB183282AE9449100BBB692 /* IceCubesApp+Scene.swift */,
|
9FB183282AE9449100BBB692 /* IceCubesApp+Scene.swift */,
|
||||||
|
9F6028552B3F36AE00476078 /* AppView.swift */,
|
||||||
);
|
);
|
||||||
path = Main;
|
path = Main;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -822,14 +822,12 @@
|
|||||||
files = (
|
files = (
|
||||||
9FE151A6293C90F900E9683D /* IconSelectorView.swift in Sources */,
|
9FE151A6293C90F900E9683D /* IconSelectorView.swift in Sources */,
|
||||||
9FB183222AE9268800BBB692 /* IceCubesApp+Menu.swift in Sources */,
|
9FB183222AE9268800BBB692 /* IceCubesApp+Menu.swift in Sources */,
|
||||||
9FB183252AE926E900BBB692 /* IceCubesApp+Sidebar.swift in Sources */,
|
|
||||||
9F7D939A29805DBD00EE6B7A /* AccountSettingView.swift in Sources */,
|
9F7D939A29805DBD00EE6B7A /* AccountSettingView.swift in Sources */,
|
||||||
069709AA298C9AD7006E4CB5 /* AboutView.swift in Sources */,
|
069709AA298C9AD7006E4CB5 /* AboutView.swift in Sources */,
|
||||||
9F2B92FC295DA94500DE16D0 /* InstanceInfoView.swift in Sources */,
|
9F2B92FC295DA94500DE16D0 /* InstanceInfoView.swift in Sources */,
|
||||||
C9B22677297F6C2E001F9EFE /* ContentSettingsView.swift in Sources */,
|
C9B22677297F6C2E001F9EFE /* ContentSettingsView.swift in Sources */,
|
||||||
9F15D6042B3DC2180008C220 /* NavigationSheet.swift in Sources */,
|
9F15D6042B3DC2180008C220 /* NavigationSheet.swift in Sources */,
|
||||||
9FA6FD6229C04A8800E2312C /* TranslationSettingsView.swift in Sources */,
|
9FA6FD6229C04A8800E2312C /* TranslationSettingsView.swift in Sources */,
|
||||||
9FB183272AE9279F00BBB692 /* IceCubesApp+Tabbar.swift in Sources */,
|
|
||||||
9F35DB4C2952005C00B3281A /* MessagesTab.swift in Sources */,
|
9F35DB4C2952005C00B3281A /* MessagesTab.swift in Sources */,
|
||||||
9FAD85CF2975B68900496AB1 /* SideBarView.swift in Sources */,
|
9FAD85CF2975B68900496AB1 /* SideBarView.swift in Sources */,
|
||||||
9FAE4ACB293783B000772766 /* SettingsTab.swift in Sources */,
|
9FAE4ACB293783B000772766 /* SettingsTab.swift in Sources */,
|
||||||
@ -850,9 +848,11 @@
|
|||||||
9F654BEF299AC45B00D27FA5 /* ReportView.swift in Sources */,
|
9F654BEF299AC45B00D27FA5 /* ReportView.swift in Sources */,
|
||||||
D08A9C3529956CFA00204A4A /* SwipeActionsSettingsView.swift in Sources */,
|
D08A9C3529956CFA00204A4A /* SwipeActionsSettingsView.swift in Sources */,
|
||||||
9F7335F22967608F00AFF0BA /* AddRemoteTimelineView.swift in Sources */,
|
9F7335F22967608F00AFF0BA /* AddRemoteTimelineView.swift in Sources */,
|
||||||
|
9F6028562B3F36AE00476078 /* AppView.swift in Sources */,
|
||||||
9F55C68D2955968700F94077 /* ExploreTab.swift in Sources */,
|
9F55C68D2955968700F94077 /* ExploreTab.swift in Sources */,
|
||||||
9F1E8B47298EBCBB00609F80 /* HapticSettingsView.swift in Sources */,
|
9F1E8B47298EBCBB00609F80 /* HapticSettingsView.swift in Sources */,
|
||||||
9F2A5411296A1429009B2D7C /* PushNotificationsView.swift in Sources */,
|
9F2A5411296A1429009B2D7C /* PushNotificationsView.swift in Sources */,
|
||||||
|
9F6028582B3F3B7600476078 /* ToolbarTab.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
135
IceCubesApp/App/Main/AppView.swift
Normal file
135
IceCubesApp/App/Main/AppView.swift
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
import Account
|
||||||
|
import AppAccount
|
||||||
|
import AVFoundation
|
||||||
|
import DesignSystem
|
||||||
|
import Env
|
||||||
|
import KeychainSwift
|
||||||
|
import MediaUI
|
||||||
|
import Network
|
||||||
|
import RevenueCat
|
||||||
|
import Status
|
||||||
|
import SwiftUI
|
||||||
|
import Timeline
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
struct AppView: View {
|
||||||
|
@Environment(AppAccountsManager.self) private var appAccountsManager
|
||||||
|
@Environment(UserPreferences.self) private var userPreferences
|
||||||
|
@Environment(Theme.self) private var theme
|
||||||
|
@Environment(StreamWatcher.self) private var watcher
|
||||||
|
|
||||||
|
@Environment(\.horizontalSizeClass) var horizontalSizeClass
|
||||||
|
|
||||||
|
@Binding var selectedTab: Tab
|
||||||
|
@Binding var sidebarRouterPath: RouterPath
|
||||||
|
|
||||||
|
@State var popToRootTab: Tab = .other
|
||||||
|
@State var iosTabs = iOSTabs.shared
|
||||||
|
@State var sideBarLoadedTabs: Set<Tab> = Set()
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
if (UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac) &&
|
||||||
|
horizontalSizeClass == .regular {
|
||||||
|
sidebarView
|
||||||
|
} else {
|
||||||
|
tabBarView
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var availableTabs: [Tab] {
|
||||||
|
if UIDevice.current.userInterfaceIdiom == .phone || horizontalSizeClass == .compact {
|
||||||
|
return appAccountsManager.currentClient.isAuth ? iosTabs.tabs : Tab.loggedOutTab()
|
||||||
|
}
|
||||||
|
return appAccountsManager.currentClient.isAuth ? Tab.loggedInTabs() : Tab.loggedOutTab()
|
||||||
|
}
|
||||||
|
|
||||||
|
var tabBarView: some View {
|
||||||
|
TabView(selection: .init(get: {
|
||||||
|
selectedTab
|
||||||
|
}, set: { newTab in
|
||||||
|
if newTab == selectedTab {
|
||||||
|
/// Stupid hack to trigger onChange binding in tab views.
|
||||||
|
popToRootTab = .other
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
|
||||||
|
popToRootTab = selectedTab
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HapticManager.shared.fireHaptic(.tabSelection)
|
||||||
|
SoundEffectManager.shared.playSound(.tabSelection)
|
||||||
|
|
||||||
|
selectedTab = newTab
|
||||||
|
})) {
|
||||||
|
ForEach(availableTabs) { tab in
|
||||||
|
tab.makeContentView(selectedTab: $selectedTab, popToRootTab: $popToRootTab)
|
||||||
|
.tabItem {
|
||||||
|
if userPreferences.showiPhoneTabLabel {
|
||||||
|
tab.label
|
||||||
|
} else {
|
||||||
|
Image(systemName: tab.iconName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.tag(tab)
|
||||||
|
.badge(badgeFor(tab: tab))
|
||||||
|
.toolbarBackground(theme.primaryBackgroundColor.opacity(0.50), for: .tabBar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.id(appAccountsManager.currentClient.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func badgeFor(tab: Tab) -> Int {
|
||||||
|
if tab == .notifications, selectedTab != tab,
|
||||||
|
let token = appAccountsManager.currentAccount.oauthToken
|
||||||
|
{
|
||||||
|
return watcher.unreadNotificationsCount + (userPreferences.notificationsCount[token] ?? 0)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
var sidebarView: some View {
|
||||||
|
SideBarView(selectedTab: $selectedTab,
|
||||||
|
popToRootTab: $popToRootTab,
|
||||||
|
tabs: availableTabs)
|
||||||
|
{
|
||||||
|
HStack(spacing: 0) {
|
||||||
|
ZStack {
|
||||||
|
if selectedTab == .profile {
|
||||||
|
ProfileTab(popToRootTab: $popToRootTab)
|
||||||
|
}
|
||||||
|
ForEach(availableTabs) { tab in
|
||||||
|
if tab == selectedTab || sideBarLoadedTabs.contains(tab) {
|
||||||
|
tab
|
||||||
|
.makeContentView(selectedTab: $selectedTab, popToRootTab: $popToRootTab)
|
||||||
|
.opacity(tab == selectedTab ? 1 : 0)
|
||||||
|
.transition(.opacity)
|
||||||
|
.id("\(tab)\(appAccountsManager.currentAccount.id)")
|
||||||
|
.onAppear {
|
||||||
|
sideBarLoadedTabs.insert(tab)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
EmptyView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if appAccountsManager.currentClient.isAuth,
|
||||||
|
userPreferences.showiPadSecondaryColumn
|
||||||
|
{
|
||||||
|
Divider().edgesIgnoringSafeArea(.all)
|
||||||
|
notificationsSecondaryColumn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.onChange(of: appAccountsManager.currentAccount.id) {
|
||||||
|
sideBarLoadedTabs.removeAll()
|
||||||
|
}
|
||||||
|
.environment(sidebarRouterPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
var notificationsSecondaryColumn: some View {
|
||||||
|
NotificationsTab(selectedTab: .constant(.notifications),
|
||||||
|
popToRootTab: $popToRootTab, lockedType: nil)
|
||||||
|
.environment(\.isSecondaryColumn, true)
|
||||||
|
.frame(maxWidth: .secondaryColumnWidth)
|
||||||
|
.id(appAccountsManager.currentAccount.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,7 +6,7 @@ import SwiftUI
|
|||||||
extension IceCubesApp {
|
extension IceCubesApp {
|
||||||
var appScene: some Scene {
|
var appScene: some Scene {
|
||||||
WindowGroup(id: "MainWindow") {
|
WindowGroup(id: "MainWindow") {
|
||||||
appView
|
AppView(selectedTab: $selectedTab, sidebarRouterPath: $sidebarRouterPath)
|
||||||
.applyTheme(theme)
|
.applyTheme(theme)
|
||||||
.onAppear {
|
.onAppear {
|
||||||
setNewClientsInEnv(client: appAccountsManager.currentClient)
|
setNewClientsInEnv(client: appAccountsManager.currentClient)
|
||||||
@ -63,15 +63,6 @@ extension IceCubesApp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder
|
|
||||||
private var appView: some View {
|
|
||||||
if UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac {
|
|
||||||
sidebarView
|
|
||||||
} else {
|
|
||||||
tabBarView
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SceneBuilder
|
@SceneBuilder
|
||||||
var otherScenes: some Scene {
|
var otherScenes: some Scene {
|
||||||
WindowGroup(for: WindowDestinationEditor.self) { destination in
|
WindowGroup(for: WindowDestinationEditor.self) { destination in
|
||||||
|
@ -1,50 +0,0 @@
|
|||||||
import Env
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
extension IceCubesApp {
|
|
||||||
var sidebarView: some View {
|
|
||||||
SideBarView(selectedTab: $selectedTab,
|
|
||||||
popToRootTab: $popToRootTab,
|
|
||||||
tabs: availableTabs)
|
|
||||||
{
|
|
||||||
HStack(spacing: 0) {
|
|
||||||
ZStack {
|
|
||||||
if selectedTab == .profile {
|
|
||||||
ProfileTab(popToRootTab: $popToRootTab)
|
|
||||||
}
|
|
||||||
ForEach(availableTabs) { tab in
|
|
||||||
if tab == selectedTab || sideBarLoadedTabs.contains(tab) {
|
|
||||||
tab
|
|
||||||
.makeContentView(selectedTab: $selectedTab, popToRootTab: $popToRootTab)
|
|
||||||
.opacity(tab == selectedTab ? 1 : 0)
|
|
||||||
.transition(.opacity)
|
|
||||||
.id("\(tab)\(appAccountsManager.currentAccount.id)")
|
|
||||||
.onAppear {
|
|
||||||
sideBarLoadedTabs.insert(tab)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
EmptyView()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if appAccountsManager.currentClient.isAuth,
|
|
||||||
userPreferences.showiPadSecondaryColumn
|
|
||||||
{
|
|
||||||
Divider().edgesIgnoringSafeArea(.all)
|
|
||||||
notificationsSecondaryColumn
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.onChange(of: $appAccountsManager.currentAccount.id) {
|
|
||||||
sideBarLoadedTabs.removeAll()
|
|
||||||
}
|
|
||||||
.environment(sidebarRouterPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
var notificationsSecondaryColumn: some View {
|
|
||||||
NotificationsTab(selectedTab: .constant(.notifications),
|
|
||||||
popToRootTab: $popToRootTab, lockedType: nil)
|
|
||||||
.environment(\.isSecondaryColumn, true)
|
|
||||||
.frame(maxWidth: .secondaryColumnWidth)
|
|
||||||
.id(appAccountsManager.currentAccount.id)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
import Env
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
extension IceCubesApp {
|
|
||||||
var tabBarView: some View {
|
|
||||||
TabView(selection: .init(get: {
|
|
||||||
selectedTab
|
|
||||||
}, set: { newTab in
|
|
||||||
if newTab == selectedTab {
|
|
||||||
/// Stupid hack to trigger onChange binding in tab views.
|
|
||||||
popToRootTab = .other
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
|
|
||||||
popToRootTab = selectedTab
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HapticManager.shared.fireHaptic(.tabSelection)
|
|
||||||
SoundEffectManager.shared.playSound(.tabSelection)
|
|
||||||
|
|
||||||
selectedTab = newTab
|
|
||||||
})) {
|
|
||||||
ForEach(availableTabs) { tab in
|
|
||||||
tab.makeContentView(selectedTab: $selectedTab, popToRootTab: $popToRootTab)
|
|
||||||
.tabItem {
|
|
||||||
if userPreferences.showiPhoneTabLabel {
|
|
||||||
tab.label
|
|
||||||
} else {
|
|
||||||
Image(systemName: tab.iconName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.tag(tab)
|
|
||||||
.badge(badgeFor(tab: tab))
|
|
||||||
.toolbarBackground(theme.primaryBackgroundColor.opacity(0.50), for: .tabBar)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.id(appAccountsManager.currentClient.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func badgeFor(tab: Tab) -> Int {
|
|
||||||
if tab == .notifications, selectedTab != tab,
|
|
||||||
let token = appAccountsManager.currentAccount.oauthToken
|
|
||||||
{
|
|
||||||
return watcher.unreadNotificationsCount + (userPreferences.notificationsCount[token] ?? 0)
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
}
|
|
@ -26,21 +26,12 @@ struct IceCubesApp: App {
|
|||||||
@State var watcher = StreamWatcher()
|
@State var watcher = StreamWatcher()
|
||||||
@State var quickLook = QuickLook.shared
|
@State var quickLook = QuickLook.shared
|
||||||
@State var theme = Theme.shared
|
@State var theme = Theme.shared
|
||||||
@State var sidebarRouterPath = RouterPath()
|
|
||||||
|
|
||||||
@State var selectedTab: Tab = .timeline
|
@State var selectedTab: Tab = .timeline
|
||||||
@State var popToRootTab: Tab = .other
|
@State var sidebarRouterPath = RouterPath()
|
||||||
@State var iosTabs = iOSTabs.shared
|
|
||||||
@State var sideBarLoadedTabs: Set<Tab> = Set()
|
|
||||||
@State var isSupporter: Bool = false
|
@State var isSupporter: Bool = false
|
||||||
|
|
||||||
var availableTabs: [Tab] {
|
|
||||||
if UIDevice.current.userInterfaceIdiom == .phone {
|
|
||||||
return appAccountsManager.currentClient.isAuth ? iosTabs.tabs : Tab.loggedOutTab()
|
|
||||||
}
|
|
||||||
return appAccountsManager.currentClient.isAuth ? Tab.loggedInTabs() : Tab.loggedOutTab()
|
|
||||||
}
|
|
||||||
|
|
||||||
var body: some Scene {
|
var body: some Scene {
|
||||||
appScene
|
appScene
|
||||||
otherScenes
|
otherScenes
|
||||||
|
@ -24,16 +24,7 @@ struct ExploreTab: View {
|
|||||||
.withSheetDestinations(sheetDestinations: $routerPath.presentedSheet)
|
.withSheetDestinations(sheetDestinations: $routerPath.presentedSheet)
|
||||||
.toolbarBackground(theme.primaryBackgroundColor.opacity(0.50), for: .navigationBar)
|
.toolbarBackground(theme.primaryBackgroundColor.opacity(0.50), for: .navigationBar)
|
||||||
.toolbar {
|
.toolbar {
|
||||||
statusEditorToolbarItem(routerPath: routerPath,
|
ToolbarTab(routerPath: $routerPath)
|
||||||
visibility: preferences.postVisibility)
|
|
||||||
if UIDevice.current.userInterfaceIdiom != .pad {
|
|
||||||
ToolbarItem(placement: .navigationBarLeading) {
|
|
||||||
AppAccountsSelectorView(routerPath: routerPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if UIDevice.current.userInterfaceIdiom == .pad, !preferences.showiPadSecondaryColumn {
|
|
||||||
SecondaryColumnToolbarItem()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.withSafariRouter()
|
.withSafariRouter()
|
||||||
|
@ -25,11 +25,7 @@ struct MessagesTab: View {
|
|||||||
.withAppRouter()
|
.withAppRouter()
|
||||||
.withSheetDestinations(sheetDestinations: $routerPath.presentedSheet)
|
.withSheetDestinations(sheetDestinations: $routerPath.presentedSheet)
|
||||||
.toolbar {
|
.toolbar {
|
||||||
if UIDevice.current.userInterfaceIdiom != .pad {
|
ToolbarTab(routerPath: $routerPath)
|
||||||
ToolbarItem(placement: .navigationBarLeading) {
|
|
||||||
AppAccountsSelectorView(routerPath: routerPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.toolbarBackground(theme.primaryBackgroundColor.opacity(0.50), for: .navigationBar)
|
.toolbarBackground(theme.primaryBackgroundColor.opacity(0.50), for: .navigationBar)
|
||||||
.id(client.id)
|
.id(client.id)
|
||||||
|
@ -27,20 +27,7 @@ struct NavigationTab<Content: View>: View {
|
|||||||
.withAppRouter()
|
.withAppRouter()
|
||||||
.withSheetDestinations(sheetDestinations: $routerPath.presentedSheet)
|
.withSheetDestinations(sheetDestinations: $routerPath.presentedSheet)
|
||||||
.toolbar {
|
.toolbar {
|
||||||
if !isSecondaryColumn {
|
ToolbarTab(routerPath: $routerPath)
|
||||||
statusEditorToolbarItem(routerPath: routerPath,
|
|
||||||
visibility: userPreferences.postVisibility)
|
|
||||||
if UIDevice.current.userInterfaceIdiom != .pad {
|
|
||||||
ToolbarItem(placement: .navigationBarLeading) {
|
|
||||||
AppAccountsSelectorView(routerPath: routerPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if UIDevice.current.userInterfaceIdiom == .pad {
|
|
||||||
if (!isSecondaryColumn && !userPreferences.showiPadSecondaryColumn) || isSecondaryColumn {
|
|
||||||
SecondaryColumnToolbarItem()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.toolbarBackground(theme.primaryBackgroundColor.opacity(0.50), for: .navigationBar)
|
.toolbarBackground(theme.primaryBackgroundColor.opacity(0.50), for: .navigationBar)
|
||||||
}
|
}
|
||||||
|
@ -40,20 +40,7 @@ struct NotificationsTab: View {
|
|||||||
Image(systemName: "bell.badge")
|
Image(systemName: "bell.badge")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !isSecondaryColumn {
|
ToolbarTab(routerPath: $routerPath)
|
||||||
statusEditorToolbarItem(routerPath: routerPath,
|
|
||||||
visibility: userPreferences.postVisibility)
|
|
||||||
if UIDevice.current.userInterfaceIdiom != .pad {
|
|
||||||
ToolbarItem(placement: .navigationBarLeading) {
|
|
||||||
AppAccountsSelectorView(routerPath: routerPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if UIDevice.current.userInterfaceIdiom == .pad {
|
|
||||||
if (!isSecondaryColumn && !userPreferences.showiPadSecondaryColumn) || isSecondaryColumn {
|
|
||||||
SecondaryColumnToolbarItem()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.toolbarBackground(theme.primaryBackgroundColor.opacity(0.50), for: .navigationBar)
|
.toolbarBackground(theme.primaryBackgroundColor.opacity(0.50), for: .navigationBar)
|
||||||
.id(client.id)
|
.id(client.id)
|
||||||
|
@ -14,6 +14,7 @@ import Timeline
|
|||||||
struct SettingsTabs: View {
|
struct SettingsTabs: View {
|
||||||
@Environment(\.dismiss) private var dismiss
|
@Environment(\.dismiss) private var dismiss
|
||||||
@Environment(\.modelContext) private var context
|
@Environment(\.modelContext) private var context
|
||||||
|
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
|
||||||
|
|
||||||
@Environment(PushNotificationsService.self) private var pushNotifications
|
@Environment(PushNotificationsService.self) private var pushNotifications
|
||||||
@Environment(UserPreferences.self) private var preferences
|
@Environment(UserPreferences.self) private var preferences
|
||||||
@ -160,7 +161,7 @@ struct SettingsTabs: View {
|
|||||||
NavigationLink(destination: SwipeActionsSettingsView()) {
|
NavigationLink(destination: SwipeActionsSettingsView()) {
|
||||||
Label("settings.general.swipeactions", systemImage: "hand.draw")
|
Label("settings.general.swipeactions", systemImage: "hand.draw")
|
||||||
}
|
}
|
||||||
if UIDevice.current.userInterfaceIdiom == .phone {
|
if UIDevice.current.userInterfaceIdiom == .phone || horizontalSizeClass == .compact {
|
||||||
NavigationLink(destination: TabbarEntriesSettingsView()) {
|
NavigationLink(destination: TabbarEntriesSettingsView()) {
|
||||||
Label("settings.general.tabbarEntries", systemImage: "platter.filled.bottom.iphone")
|
Label("settings.general.tabbarEntries", systemImage: "platter.filled.bottom.iphone")
|
||||||
}
|
}
|
||||||
|
@ -228,17 +228,7 @@ struct TimelineTab: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if client.isAuth {
|
if client.isAuth {
|
||||||
if UIDevice.current.userInterfaceIdiom != .pad {
|
ToolbarTab(routerPath: $routerPath)
|
||||||
ToolbarItem(placement: .navigationBarLeading) {
|
|
||||||
AppAccountsSelectorView(routerPath: routerPath)
|
|
||||||
.id(currentAccount.account?.id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
statusEditorToolbarItem(routerPath: routerPath,
|
|
||||||
visibility: preferences.postVisibility)
|
|
||||||
if UIDevice.current.userInterfaceIdiom == .pad, !preferences.showiPadSecondaryColumn {
|
|
||||||
SecondaryColumnToolbarItem()
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
ToolbarItem(placement: .navigationBarTrailing) {
|
ToolbarItem(placement: .navigationBarTrailing) {
|
||||||
addAccountButton
|
addAccountButton
|
||||||
|
32
IceCubesApp/App/Tabs/ToolbarTab.swift
Normal file
32
IceCubesApp/App/Tabs/ToolbarTab.swift
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import SwiftUI
|
||||||
|
import Env
|
||||||
|
import AppAccount
|
||||||
|
import DesignSystem
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
struct ToolbarTab: ToolbarContent {
|
||||||
|
@Environment(\.isSecondaryColumn) private var isSecondaryColumn: Bool
|
||||||
|
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
|
||||||
|
|
||||||
|
@Environment(UserPreferences.self) private var userPreferences
|
||||||
|
|
||||||
|
@Binding var routerPath: RouterPath
|
||||||
|
|
||||||
|
var body: some ToolbarContent {
|
||||||
|
if !isSecondaryColumn {
|
||||||
|
statusEditorToolbarItem(routerPath: routerPath,
|
||||||
|
visibility: userPreferences.postVisibility)
|
||||||
|
if UIDevice.current.userInterfaceIdiom != .pad ||
|
||||||
|
(UIDevice.current.userInterfaceIdiom == .pad && horizontalSizeClass == .compact) {
|
||||||
|
ToolbarItem(placement: .navigationBarLeading) {
|
||||||
|
AppAccountsSelectorView(routerPath: routerPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if UIDevice.current.userInterfaceIdiom == .pad && horizontalSizeClass == .regular {
|
||||||
|
if (!isSecondaryColumn && !userPreferences.showiPadSecondaryColumn) || isSecondaryColumn {
|
||||||
|
SecondaryColumnToolbarItem()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,15 @@ public extension View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
public extension ToolbarContent {
|
||||||
|
func statusEditorToolbarItem(routerPath _: RouterPath,
|
||||||
|
visibility: Models.Visibility) -> some ToolbarContent
|
||||||
|
{
|
||||||
|
StatusEditorToolbarItem(visibility: visibility)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
public struct StatusEditorToolbarItem: ToolbarContent {
|
public struct StatusEditorToolbarItem: ToolbarContent {
|
||||||
@Environment(\.openWindow) private var openWindow
|
@Environment(\.openWindow) private var openWindow
|
||||||
|
Loading…
x
Reference in New Issue
Block a user