left bar
This commit is contained in:
parent
4ec99934e4
commit
fc214ed696
@ -9,6 +9,9 @@ struct TopBarView: View {
|
|||||||
var accounts: [String]
|
var accounts: [String]
|
||||||
var viewModel: LoginViewModel
|
var viewModel: LoginViewModel
|
||||||
|
|
||||||
|
// Привязка для управления боковым меню
|
||||||
|
@Binding var isSideMenuPresented: Bool
|
||||||
|
|
||||||
var isHomeTab: Bool {
|
var isHomeTab: Bool {
|
||||||
return title == "Home"
|
return title == "Home"
|
||||||
}
|
}
|
||||||
@ -20,6 +23,19 @@ struct TopBarView: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
HStack {
|
HStack {
|
||||||
|
// Кнопка "Гамбургер" для открытия меню
|
||||||
|
Button(action: {
|
||||||
|
withAnimation {
|
||||||
|
isSideMenuPresented.toggle()
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Image(systemName: "line.horizontal.3")
|
||||||
|
.imageScale(.large)
|
||||||
|
.foregroundColor(.primary)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spacer()
|
||||||
|
|
||||||
if isHomeTab{
|
if isHomeTab{
|
||||||
Text("Yobble")
|
Text("Yobble")
|
||||||
.font(.largeTitle)
|
.font(.largeTitle)
|
||||||
@ -70,3 +86,9 @@ struct TopBarView: View {
|
|||||||
.background(Color(UIColor.systemBackground))
|
.background(Color(UIColor.systemBackground))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct TopBarView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
/*@START_MENU_TOKEN@*/Text("Hello, World!")/*@END_MENU_TOKEN@*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,10 +1,3 @@
|
|||||||
//
|
|
||||||
// MainView.swift
|
|
||||||
// VolnahubApp
|
|
||||||
//
|
|
||||||
// Created by cheykrym on 09/06/2025.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct MainView: View {
|
struct MainView: View {
|
||||||
@ -17,109 +10,75 @@ struct MainView: View {
|
|||||||
@State private var accounts = ["@user1", "@user2", "@user3"]
|
@State private var accounts = ["@user1", "@user2", "@user3"]
|
||||||
@State private var sheetType: ProfileTab.SheetType? = nil
|
@State private var sheetType: ProfileTab.SheetType? = nil
|
||||||
|
|
||||||
// Состояния для скрытия TopBar
|
// Состояние для бокового меню
|
||||||
@State private var topBarVisible = true
|
@State private var isSideMenuPresented = false
|
||||||
@State private var lastScrollY: CGFloat = 0
|
|
||||||
|
|
||||||
private var tabTitle: String {
|
private var tabTitle: String {
|
||||||
switch selectedTab {
|
switch selectedTab {
|
||||||
case 0:
|
case 0: return "Home"
|
||||||
return "Home"
|
case 1: return "Search"
|
||||||
case 1:
|
case 2: return "Chats"
|
||||||
return "Search"
|
case 3: return "Profile"
|
||||||
case 2:
|
default: return "Home"
|
||||||
return "Chats"
|
|
||||||
case 3:
|
|
||||||
return "Profile"
|
|
||||||
default:
|
|
||||||
return "Home"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
NavigationView {
|
NavigationView {
|
||||||
|
ZStack {
|
||||||
|
// Основной контент
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
if topBarVisible {
|
|
||||||
TopBarView(
|
TopBarView(
|
||||||
title: tabTitle,
|
title: tabTitle,
|
||||||
selectedAccount: $selectedAccount,
|
selectedAccount: $selectedAccount,
|
||||||
sheetType: $sheetType,
|
sheetType: $sheetType,
|
||||||
accounts: accounts,
|
accounts: accounts,
|
||||||
viewModel: viewModel
|
viewModel: viewModel,
|
||||||
|
isSideMenuPresented: $isSideMenuPresented
|
||||||
)
|
)
|
||||||
.transition(AnyTransition.move(edge: .top).combined(with: .opacity))
|
|
||||||
}
|
|
||||||
|
|
||||||
ZStack {
|
ZStack {
|
||||||
switch selectedTab {
|
switch selectedTab {
|
||||||
case 0:
|
case 0: NewHomeTab(viewModel: newHomeTabViewModel)
|
||||||
// HomeTab(onScroll: handleScroll)
|
case 1: SearchTab()
|
||||||
NewHomeTab(viewModel: newHomeTabViewModel)
|
case 2: ChatsTab()
|
||||||
case 1:
|
case 3: ProfileTab(viewModel: viewModel, sheetType: $sheetType, selectedAccount: $selectedAccount, accounts: $accounts, onScroll: { _ in })
|
||||||
SearchTab() // SearchTab не имеет скролла, поэтому onScroll не нужен
|
default: NewHomeTab(viewModel: newHomeTabViewModel)
|
||||||
case 2:
|
|
||||||
ChatsTab() // ChatsTab тоже
|
|
||||||
case 3:
|
|
||||||
ProfileTab(
|
|
||||||
viewModel: viewModel,
|
|
||||||
sheetType: $sheetType,
|
|
||||||
selectedAccount: $selectedAccount,
|
|
||||||
accounts: $accounts,
|
|
||||||
onScroll: handleScroll
|
|
||||||
)
|
|
||||||
default:
|
|
||||||
HomeTab(onScroll: handleScroll)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
|
|
||||||
if topBarVisible {
|
|
||||||
CustomTabBar(selectedTab: $selectedTab) {
|
CustomTabBar(selectedTab: $selectedTab) {
|
||||||
print("Create button tapped")
|
print("Create button tapped")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
.ignoresSafeArea(edges: .bottom)
|
.ignoresSafeArea(edges: .bottom)
|
||||||
.navigationBarHidden(true)
|
.navigationBarHidden(true)
|
||||||
.sheet(item: $sheetType) { type in
|
.sheet(item: $sheetType) { type in
|
||||||
switch type {
|
// ... sheet presentation logic
|
||||||
case .accountShare:
|
}
|
||||||
AccountShareSheet(
|
// Затемнение фона при открытом меню
|
||||||
isPresented: Binding(
|
.background(isSideMenuPresented ? Color.black.opacity(0.4) : Color.clear)
|
||||||
get: { sheetType != nil },
|
.onTapGesture {
|
||||||
set: { if !$0 { sheetType = nil } }
|
if isSideMenuPresented {
|
||||||
),
|
withAnimation {
|
||||||
selectedAccount: $selectedAccount,
|
isSideMenuPresented = false
|
||||||
accounts: accounts
|
}
|
||||||
)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Боковое меню
|
||||||
|
if isSideMenuPresented {
|
||||||
|
SideMenuView(isPresented: $isSideMenuPresented)
|
||||||
|
.frame(width: UIScreen.main.bounds.width * 0.8)
|
||||||
|
.offset(x: isSideMenuPresented ? 0 : -UIScreen.main.bounds.width)
|
||||||
|
.transition(.move(edge: .leading))
|
||||||
|
.zIndex(1) // Убедимся, что меню поверх всего
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationViewStyle(StackNavigationViewStyle())
|
.navigationViewStyle(StackNavigationViewStyle())
|
||||||
}
|
}
|
||||||
|
|
||||||
private func handleScroll(offset: CGPoint) {
|
|
||||||
let currentY = offset.y
|
|
||||||
|
|
||||||
// Показываем бар, если скроллим вверх или дошли до верха
|
|
||||||
// if currentY < lastScrollY || currentY <= 0 {
|
|
||||||
// if !topBarVisible {
|
|
||||||
// withAnimation(.default) {
|
|
||||||
// topBarVisible = true
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// // Скрываем, если скроллим вниз и отступили от верха
|
|
||||||
// else if currentY > lastScrollY && currentY > 50 {
|
|
||||||
// if topBarVisible {
|
|
||||||
// withAnimation(.default) {
|
|
||||||
// topBarVisible = false
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
lastScrollY = currentY
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MainView_Previews: PreviewProvider {
|
struct MainView_Previews: PreviewProvider {
|
||||||
|
|||||||
116
Shared/Views/Tab/SideMenuView.swift
Normal file
116
Shared/Views/Tab/SideMenuView.swift
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct SideMenuView: View {
|
||||||
|
@Binding var isPresented: Bool
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(alignment: .leading, spacing: 0) {
|
||||||
|
// Header
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
Image(systemName: "person.circle.fill")
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 60, height: 60)
|
||||||
|
.foregroundColor(.gray)
|
||||||
|
Text("Your Name")
|
||||||
|
.font(.title2).bold()
|
||||||
|
Text("@yourusername")
|
||||||
|
.font(.subheadline)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
}
|
||||||
|
.padding(20)
|
||||||
|
|
||||||
|
// Menu Items
|
||||||
|
ScrollView {
|
||||||
|
VStack(alignment: .leading, spacing: 20) {
|
||||||
|
// Section 1
|
||||||
|
VStack(alignment: .leading, spacing: 15) {
|
||||||
|
SideMenuButton(icon: "person.2.fill", title: "People You May Like", action: {})
|
||||||
|
SideMenuButton(icon: "star.fill", title: "Fun Fest", action: {})
|
||||||
|
SideMenuButton(icon: "lightbulb.fill", title: "Creator Center", action: {})
|
||||||
|
}
|
||||||
|
|
||||||
|
Divider()
|
||||||
|
|
||||||
|
// Section 2
|
||||||
|
VStack(alignment: .leading, spacing: 15) {
|
||||||
|
Text("CATEGORY").font(.caption).foregroundColor(.secondary)
|
||||||
|
SideMenuButton(icon: "doc.text", title: "Drafts", action: {})
|
||||||
|
SideMenuButton(icon: "bubble.left", title: "My Comments", action: {})
|
||||||
|
SideMenuButton(icon: "clock", title: "History", action: {})
|
||||||
|
SideMenuButton(icon: "arrow.down.circle", title: "My Downloads", action: {})
|
||||||
|
}
|
||||||
|
|
||||||
|
Divider()
|
||||||
|
|
||||||
|
// Section 3
|
||||||
|
VStack(alignment: .leading, spacing: 15) {
|
||||||
|
Text("SERVICES").font(.caption).foregroundColor(.secondary)
|
||||||
|
SideMenuButton(icon: "shippingbox", title: "Orders", action: {})
|
||||||
|
SideMenuButton(icon: "cart", title: "Cart", action: {})
|
||||||
|
SideMenuButton(icon: "wallet.pass", title: "Wallet", action: {})
|
||||||
|
}
|
||||||
|
|
||||||
|
Divider()
|
||||||
|
|
||||||
|
// Section 4
|
||||||
|
VStack(alignment: .leading, spacing: 15) {
|
||||||
|
SideMenuButton(icon: "square.grid.2x2", title: "Applets", action: {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
// Footer
|
||||||
|
HStack(spacing: 20) {
|
||||||
|
Spacer()
|
||||||
|
SideMenuFooterButton(icon: "qrcode.viewfinder", title: "Scan", action: {})
|
||||||
|
SideMenuFooterButton(icon: "questionmark.circle", title: "Help Center", action: {})
|
||||||
|
SideMenuFooterButton(icon: "gear", title: "Settings", action: {})
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
.background(Color(UIColor.systemBackground))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper Views for buttons
|
||||||
|
struct SideMenuButton: View {
|
||||||
|
let icon: String
|
||||||
|
let title: String
|
||||||
|
let action: () -> Void
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
Button(action: action) {
|
||||||
|
HStack(spacing: 15) {
|
||||||
|
Image(systemName: icon)
|
||||||
|
.font(.title3)
|
||||||
|
.frame(width: 30)
|
||||||
|
Text(title)
|
||||||
|
.font(.headline)
|
||||||
|
}
|
||||||
|
.foregroundColor(.primary)
|
||||||
|
.padding(.vertical, 8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SideMenuFooterButton: View {
|
||||||
|
let icon: String
|
||||||
|
let title: String
|
||||||
|
let action: () -> Void
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
Button(action: action) {
|
||||||
|
VStack {
|
||||||
|
Image(systemName: icon)
|
||||||
|
.font(.title2)
|
||||||
|
Text(title)
|
||||||
|
.font(.caption)
|
||||||
|
}
|
||||||
|
.foregroundColor(.primary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -35,6 +35,7 @@
|
|||||||
1A9B01602E4BF9C000887E0B /* placeholderPhoto.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 1A9B015E2E4BF9C000887E0B /* placeholderPhoto.jpg */; };
|
1A9B01602E4BF9C000887E0B /* placeholderPhoto.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 1A9B015E2E4BF9C000887E0B /* placeholderPhoto.jpg */; };
|
||||||
1A9B01662E4BFA3600887E0B /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A9B01652E4BFA3600887E0B /* Media.xcassets */; };
|
1A9B01662E4BFA3600887E0B /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A9B01652E4BFA3600887E0B /* Media.xcassets */; };
|
||||||
1A9B016E2E4BFB9000887E0B /* NewHomeTabViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A9B016D2E4BFB9000887E0B /* NewHomeTabViewModel.swift */; };
|
1A9B016E2E4BFB9000887E0B /* NewHomeTabViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A9B016D2E4BFB9000887E0B /* NewHomeTabViewModel.swift */; };
|
||||||
|
1A9B017C2E4C087F00887E0B /* SideMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A9B017B2E4C087F00887E0B /* SideMenuView.swift */; };
|
||||||
1AB4F8CD2E22E341002B6E40 /* AccountShareSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AB4F8CC2E22E341002B6E40 /* AccountShareSheet.swift */; };
|
1AB4F8CD2E22E341002B6E40 /* AccountShareSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AB4F8CC2E22E341002B6E40 /* AccountShareSheet.swift */; };
|
||||||
1AB4F8F32E22EC9F002B6E40 /* FollowersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AB4F8F22E22EC9F002B6E40 /* FollowersView.swift */; };
|
1AB4F8F32E22EC9F002B6E40 /* FollowersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AB4F8F22E22EC9F002B6E40 /* FollowersView.swift */; };
|
||||||
1AB4F8F72E22ECAC002B6E40 /* FollowingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AB4F8F62E22ECAC002B6E40 /* FollowingView.swift */; };
|
1AB4F8F72E22ECAC002B6E40 /* FollowingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AB4F8F62E22ECAC002B6E40 /* FollowingView.swift */; };
|
||||||
@ -88,6 +89,7 @@
|
|||||||
1A9B015E2E4BF9C000887E0B /* placeholderPhoto.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = placeholderPhoto.jpg; path = ../../../../Volumes/Untitled/xcode/volnahub/Shared/Media/placeholderPhoto.jpg; sourceTree = DEVELOPER_DIR; };
|
1A9B015E2E4BF9C000887E0B /* placeholderPhoto.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = placeholderPhoto.jpg; path = ../../../../Volumes/Untitled/xcode/volnahub/Shared/Media/placeholderPhoto.jpg; sourceTree = DEVELOPER_DIR; };
|
||||||
1A9B01652E4BFA3600887E0B /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Media.xcassets; sourceTree = "<group>"; };
|
1A9B01652E4BFA3600887E0B /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Media.xcassets; sourceTree = "<group>"; };
|
||||||
1A9B016D2E4BFB9000887E0B /* NewHomeTabViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NewHomeTabViewModel.swift; sourceTree = "<group>"; };
|
1A9B016D2E4BFB9000887E0B /* NewHomeTabViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NewHomeTabViewModel.swift; sourceTree = "<group>"; };
|
||||||
|
1A9B017B2E4C087F00887E0B /* SideMenuView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SideMenuView.swift; sourceTree = "<group>"; };
|
||||||
1AB4F8CC2E22E341002B6E40 /* AccountShareSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountShareSheet.swift; sourceTree = "<group>"; };
|
1AB4F8CC2E22E341002B6E40 /* AccountShareSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountShareSheet.swift; sourceTree = "<group>"; };
|
||||||
1AB4F8F22E22EC9F002B6E40 /* FollowersView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowersView.swift; sourceTree = "<group>"; };
|
1AB4F8F22E22EC9F002B6E40 /* FollowersView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowersView.swift; sourceTree = "<group>"; };
|
||||||
1AB4F8F62E22ECAC002B6E40 /* FollowingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowingView.swift; sourceTree = "<group>"; };
|
1AB4F8F62E22ECAC002B6E40 /* FollowingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowingView.swift; sourceTree = "<group>"; };
|
||||||
@ -288,6 +290,7 @@
|
|||||||
1AEE5EA92E21A4FC00A3DCA3 /* Tab */ = {
|
1AEE5EA92E21A4FC00A3DCA3 /* Tab */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
1A9B017B2E4C087F00887E0B /* SideMenuView.swift */,
|
||||||
1A6FB9542E32D2B200E89EBE /* CustomTabBar.swift */,
|
1A6FB9542E32D2B200E89EBE /* CustomTabBar.swift */,
|
||||||
1A7940B52DF77F21002569DA /* MainView.swift */,
|
1A7940B52DF77F21002569DA /* MainView.swift */,
|
||||||
1A9B014A2E4BF3CD00887E0B /* NewHomeTab.swift */,
|
1A9B014A2E4BF3CD00887E0B /* NewHomeTab.swift */,
|
||||||
@ -423,6 +426,7 @@
|
|||||||
1AEE5EAB2E21A83200A3DCA3 /* HomeTab.swift in Sources */,
|
1AEE5EAB2E21A83200A3DCA3 /* HomeTab.swift in Sources */,
|
||||||
1ACE60F82E22F3DC00B37AC5 /* SettingsView.swift in Sources */,
|
1ACE60F82E22F3DC00B37AC5 /* SettingsView.swift in Sources */,
|
||||||
1AD757CD2E27608C0069C1FD /* PostFeedView.swift in Sources */,
|
1AD757CD2E27608C0069C1FD /* PostFeedView.swift in Sources */,
|
||||||
|
1A9B017C2E4C087F00887E0B /* SideMenuView.swift in Sources */,
|
||||||
1A7940C62DF7A98E002569DA /* ContactsTab.swift in Sources */,
|
1A7940C62DF7A98E002569DA /* ContactsTab.swift in Sources */,
|
||||||
1ACE61092E22F57100B37AC5 /* AppPreferencesView.swift in Sources */,
|
1ACE61092E22F57100B37AC5 /* AppPreferencesView.swift in Sources */,
|
||||||
1ACE61052E22F56800B37AC5 /* SecuritySettingsView.swift in Sources */,
|
1ACE61052E22F56800B37AC5 /* SecuritySettingsView.swift in Sources */,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user