Compare commits

..

No commits in common. "478020f6f2a21d88fb6699545bfa036ff9415b05" and "4f46f715aaf40a92a2d52fa7467c7c405befcd5d" have entirely different histories.

25 changed files with 141 additions and 630 deletions

View File

@ -4,20 +4,17 @@ import UIKit
struct RefreshableScrollView<Content: View>: UIViewRepresentable { struct RefreshableScrollView<Content: View>: UIViewRepresentable {
var content: Content var content: Content
var onRefresh: () -> Void var onRefresh: () -> Void
var onScroll: ((CGPoint) -> Void)?
var isRefreshing: Binding<Bool> var isRefreshing: Binding<Bool>
init(isRefreshing: Binding<Bool>, onRefresh: @escaping () -> Void, onScroll: ((CGPoint) -> Void)? = nil, @ViewBuilder content: () -> Content) { init(isRefreshing: Binding<Bool>, onRefresh: @escaping () -> Void, @ViewBuilder content: () -> Content) {
self.content = content() self.content = content()
self.onRefresh = onRefresh self.onRefresh = onRefresh
self.onScroll = onScroll
self.isRefreshing = isRefreshing self.isRefreshing = isRefreshing
} }
func makeUIView(context: Context) -> UIScrollView { func makeUIView(context: Context) -> UIScrollView {
let scrollView = UIScrollView() let scrollView = UIScrollView()
scrollView.delaysContentTouches = false scrollView.delaysContentTouches = false
scrollView.delegate = context.coordinator
let refreshControl = UIRefreshControl() let refreshControl = UIRefreshControl()
refreshControl.addTarget(context.coordinator, action: #selector(Coordinator.handleRefresh), for: .valueChanged) refreshControl.addTarget(context.coordinator, action: #selector(Coordinator.handleRefresh), for: .valueChanged)
@ -44,6 +41,7 @@ struct RefreshableScrollView<Content: View>: UIViewRepresentable {
if isRefreshing.wrappedValue { if isRefreshing.wrappedValue {
uiView.refreshControl?.beginRefreshing() uiView.refreshControl?.beginRefreshing()
} else { } else {
// Отложенное завершение, чтобы избежать цикла обновлений
DispatchQueue.main.async { DispatchQueue.main.async {
uiView.refreshControl?.endRefreshing() uiView.refreshControl?.endRefreshing()
} }
@ -56,7 +54,7 @@ struct RefreshableScrollView<Content: View>: UIViewRepresentable {
Coordinator(self) Coordinator(self)
} }
class Coordinator: NSObject, UIScrollViewDelegate { class Coordinator: NSObject {
var parent: RefreshableScrollView var parent: RefreshableScrollView
var hostingController: UIHostingController<Content>? var hostingController: UIHostingController<Content>?
@ -67,9 +65,5 @@ struct RefreshableScrollView<Content: View>: UIViewRepresentable {
@objc func handleRefresh() { @objc func handleRefresh() {
parent.onRefresh() parent.onRefresh()
} }
func scrollViewDidScroll(_ scrollView: UIScrollView) {
parent.onScroll?(scrollView.contentOffset)
}
} }
} }

View File

@ -1,104 +0,0 @@
import SwiftUI
struct TopBarView: View {
var title: String
// Состояния для ProfileTab
@Binding var selectedAccount: String
@Binding var sheetType: ProfileTab.SheetType?
var accounts: [String]
var viewModel: LoginViewModel
// Привязка для управления боковым меню
@Binding var isSideMenuPresented: Bool
var isHomeTab: Bool {
return title == "Home"
}
var isProfileTab: Bool {
return title == "Profile"
}
var body: some View {
VStack(spacing: 0) {
HStack {
// Кнопка "Гамбургер" для открытия меню
Button(action: {
withAnimation {
isSideMenuPresented.toggle()
}
}) {
Image(systemName: "line.horizontal.3")
.imageScale(.large)
.foregroundColor(.primary)
}
// Spacer()
if isHomeTab{
Text("Yobble")
.font(.largeTitle)
.fontWeight(.bold)
Spacer()
} else if isProfileTab {
Spacer()
Button(action: { sheetType = .accountShare }) {
HStack(spacing: 4) {
Text(selectedAccount)
.font(.headline)
.foregroundColor(.primary)
Image(systemName: "chevron.down")
.font(.subheadline)
.foregroundColor(.gray)
}
}
Spacer()
} else {
Text(title)
.font(.largeTitle)
.fontWeight(.bold)
Spacer()
}
if isHomeTab{
HStack(spacing: 20) {
// Кнопка поиска
Button(action: {
// пока ничего не делаем
}) {
Image(systemName: "magnifyingglass")
.imageScale(.large)
.foregroundColor(.primary)
}
// Кнопка уведомлений
Button(action: {
// пока ничего не делаем
}) {
Image(systemName: "bell")
.imageScale(.large)
.foregroundColor(.primary)
}
}
} else if isProfileTab {
NavigationLink(destination: SettingsView(viewModel: viewModel)) {
Image(systemName: "wrench")
.imageScale(.large)
.foregroundColor(.primary)
}
}
}
.padding()
.frame(height: 50) // Стандартная высота для нав. бара
// Divider()
}
.background(Color(UIColor.systemBackground))
}
}
struct TopBarView_Previews: PreviewProvider {
static var previews: some View {
/*@START_MENU_TOKEN@*/Text("Hello, World!")/*@END_MENU_TOKEN@*/
}
}

View File

@ -1,6 +0,0 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -1,21 +0,0 @@
{
"images" : [
{
"filename" : "placeholderPhoto.jpg",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -1,21 +0,0 @@
{
"images" : [
{
"filename" : "placeholderPhotoSquare.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 KiB

View File

@ -1,12 +0,0 @@
{
"data" : [
{
"filename" : "placeholderVideo.mp4",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

View File

@ -10,7 +10,7 @@ struct Post: Identifiable, Codable {
let description: String? // Описание поста let description: String? // Описание поста
let media: [MediaItem] // Массив медиафайлов let media: [MediaItem] // Массив медиафайлов
let mediaOrder: [UUID]? // Порядок отображения медиа let mediaOrder: [UUID]? // Порядок отображения медиа
let thumbnailID: UUID // Превью let thumbnailID: UUID? // Превью для видео
let duration: Double? // Длительность видео/аудио let duration: Double? // Длительность видео/аудио
let createdAt: Date // Дата создания let createdAt: Date // Дата создания
let updatedAt: Date // Дата обновления let updatedAt: Date // Дата обновления
@ -20,7 +20,7 @@ struct Post: Identifiable, Codable {
let commentsCount: Int // Кол-во комментариев let commentsCount: Int // Кол-во комментариев
let isLikedByCurrentUser: Bool // Лайк текущим юзером let isLikedByCurrentUser: Bool // Лайк текущим юзером
let isSavedByCurrentUser: Bool // Сохранено текущим юзером let isSavedByCurrentUser: Bool // Сохранено текущим юзером
let authorID: UUID // Автор let authorID: String // Автор
let authorUsername: String // Имя пользователя автора let authorUsername: String // Имя пользователя автора
let hashtags: [String]? // Хэштеги let hashtags: [String]? // Хэштеги
let location: String? // Гео let location: String? // Гео
@ -30,7 +30,6 @@ struct Post: Identifiable, Codable {
enum MediaType: String, Codable { enum MediaType: String, Codable {
case photo case photo
case live
case video case video
} }

View File

@ -96,13 +96,10 @@ class PostService {
for i in 0..<32 { for i in 0..<32 {
let mediaID = UUID() let mediaID = UUID()
// let thumbID = Bool.random() ? UUID() : nil let thumbID = Bool.random() ? UUID() : nil
let thumbID = UUID()
let postID = UUID() let postID = UUID()
let authorId = UUID() let authorId = "user_\(Int.random(in: 1...5))"
let authorUserName = "username_\(Int.random(in: 1...5))"
// let authorId = "user_\(Int.random(in: 1...5))"
let post = Post( let post = Post(
id: postID, id: postID,
title: sampleTitles[i], title: sampleTitles[i],
@ -122,7 +119,7 @@ class PostService {
isLikedByCurrentUser: Bool.random(), isLikedByCurrentUser: Bool.random(),
isSavedByCurrentUser: Bool.random(), isSavedByCurrentUser: Bool.random(),
authorID: authorId, authorID: authorId,
authorUsername: authorUserName, authorUsername: "username_\(authorId.split(separator: "_").last ?? "")",
hashtags: ["#тест", "#видео", "#swiftui", "#ui"].shuffled().prefix(2).map { $0 }, hashtags: ["#тест", "#видео", "#swiftui", "#ui"].shuffled().prefix(2).map { $0 },
location: Bool.random() ? "Москва" : nil, location: Bool.random() ? "Москва" : nil,
languageCode: Bool.random() ? ["ru", "en"] : ["ru"], languageCode: Bool.random() ? ["ru", "en"] : ["ru"],

View File

@ -1,32 +0,0 @@
import Foundation
import Combine
class NewHomeTabViewModel: ObservableObject {
@Published var posts: [Post] = []
@Published var isLoading = true
@Published var isRefreshing = false
private var hasLoadedData = false
func fetchDataIfNeeded() {
guard !hasLoadedData else { return }
refreshData()
}
func refreshData() {
DispatchQueue.main.async {
self.isRefreshing = true
}
PostService.shared.fetchAllPosts { [weak self] fetchedPosts in
guard let self = self else { return }
DispatchQueue.main.async {
self.posts = fetchedPosts
self.isLoading = false
self.hasLoadedData = true
self.isRefreshing = false
}
}
}
}

View File

@ -9,12 +9,16 @@ import SwiftUI
struct ChatsTab: View { struct ChatsTab: View {
var body: some View { var body: some View {
VStack { NavigationView {
Text("Здесь будут чаты") VStack {
.font(.title) Text("Чаты")
.foregroundColor(.gray) .font(.largeTitle)
.bold()
Spacer() .padding()
Spacer()
}
.navigationTitle("Чаты")
} }
} }
} }

View File

@ -4,32 +4,35 @@ struct HomeTab: View {
@State private var posts: [Post] = [] @State private var posts: [Post] = []
@State private var isLoading = true @State private var isLoading = true
@State private var isRefreshing = false @State private var isRefreshing = false
var onScroll: ((CGPoint) -> Void)?
var body: some View { var body: some View {
VStack { NavigationView {
if isLoading { VStack {
ProgressView("Загрузка ленты...") if isLoading {
} else { ProgressView("Загрузка ленты...")
RefreshableScrollView( } else {
isRefreshing: $isRefreshing, RefreshableScrollView(isRefreshing: $isRefreshing, onRefresh: {
onRefresh: { fetchData() }, fetchData()
onScroll: onScroll }) {
) { LazyVStack(spacing: 24) {
LazyVStack(spacing: 24) { ForEach(posts) { post in
ForEach(posts) { post in PostDetailView(post: post)
PostDetailView(post: post) }
} }
} }
} }
} }
} .navigationBarTitleDisplayMode(.inline)
.onAppear { .toolbar {
if posts.isEmpty { ToolbarItem(placement: .principal) {}
fetchData(isInitialLoad: true) }
.onAppear {
if posts.isEmpty {
fetchData(isInitialLoad: true)
}
} }
} }
.navigationViewStyle(StackNavigationViewStyle())
} }
private func fetchData(isInitialLoad: Bool = false) { private func fetchData(isInitialLoad: Bool = false) {

View File

@ -1,90 +1,40 @@
//
// MainView.swift
// VolnahubApp
//
// Created by cheykrym on 09/06/2025.
//
import SwiftUI import SwiftUI
struct MainView: View { struct MainView: View {
@ObservedObject var viewModel: LoginViewModel @ObservedObject var viewModel: LoginViewModel
@State private var selectedTab: Int = 0 @State private var selectedTab: Int = 0
@StateObject private var newHomeTabViewModel = NewHomeTabViewModel()
// Состояния для TopBarView
@State private var selectedAccount = "@user1"
@State private var accounts = ["@user1", "@user2", "@user3"]
@State private var sheetType: ProfileTab.SheetType? = nil
// Состояние для бокового меню
@State private var isSideMenuPresented = false
private var tabTitle: String {
switch selectedTab {
case 0: return "Home"
case 1: return "Search"
case 2: return "Chats"
case 3: return "Profile"
default: return "Home"
}
}
var body: some View { var body: some View {
NavigationView { VStack(spacing: 0) {
ZStack { ZStack {
// Основной контент switch selectedTab {
VStack(spacing: 0) { case 0:
TopBarView( HomeTab()
title: tabTitle, case 1:
selectedAccount: $selectedAccount, SearchTab()
sheetType: $sheetType, case 2:
accounts: accounts, ChatsTab()
viewModel: viewModel, case 3:
isSideMenuPresented: $isSideMenuPresented ProfileTab(viewModel: viewModel)
) default:
HomeTab()
ZStack {
NewHomeTab(viewModel: newHomeTabViewModel)
.opacity(selectedTab == 0 ? 1 : 0)
SearchTab()
.opacity(selectedTab == 1 ? 1 : 0)
ChatsTab()
.opacity(selectedTab == 2 ? 1 : 0)
ProfileTab(viewModel: viewModel, sheetType: $sheetType, selectedAccount: $selectedAccount, accounts: $accounts, onScroll: { _ in })
.opacity(selectedTab == 3 ? 1 : 0)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
CustomTabBar(selectedTab: $selectedTab) {
print("Create button tapped")
}
}
.ignoresSafeArea(edges: .bottom)
.navigationBarHidden(true)
.sheet(item: $sheetType) { type in
// ... sheet presentation logic
}
// Затемнение фона при открытом меню
.background(isSideMenuPresented ? Color.black.opacity(0.4) : Color.clear)
.onTapGesture {
if isSideMenuPresented {
withAnimation {
isSideMenuPresented = false
}
}
}
// Боковое меню
if isSideMenuPresented {
HStack {
SideMenuView(isPresented: $isSideMenuPresented)
.frame(width: UIScreen.main.bounds.width * 0.8)
Spacer()
}
.ignoresSafeArea(edges: .vertical) // Игнорируем safe area
.transition(.move(edge: .leading))
.zIndex(1) // Убедимся, что меню поверх всего
} }
} }
.frame(maxWidth: .infinity, maxHeight: .infinity)
CustomTabBar(selectedTab: $selectedTab) {
// Действие для кнопки "Создать"
print("Create button tapped")
}
} }
.navigationViewStyle(StackNavigationViewStyle()) .ignoresSafeArea(edges: .bottom)
} }
} }

View File

@ -1,114 +0,0 @@
import SwiftUI
struct NewHomeTab: View {
@ObservedObject var viewModel: NewHomeTabViewModel
private var column1Posts: [Post] {
viewModel.posts.enumerated().filter { $0.offset % 2 == 0 }.map { $0.element }
}
private var column2Posts: [Post] {
viewModel.posts.enumerated().filter { $0.offset % 2 != 0 }.map { $0.element }
}
var body: some View {
VStack {
if viewModel.isLoading {
ProgressView("Загрузка ленты...")
} else {
RefreshableScrollView(isRefreshing: $viewModel.isRefreshing, onRefresh: {
viewModel.refreshData()
}) {
HStack(alignment: .top, spacing: 6) {
LazyVStack(spacing: 6) {
ForEach(column1Posts) { post in
PostGridItem(post: post)
}
}
LazyVStack(spacing: 6) {
ForEach(column2Posts) { post in
PostGridItem(post: post)
}
}
}
.padding(.horizontal, 4)
}
}
}
.onAppear {
viewModel.fetchDataIfNeeded()
}
.background(Color(.secondarySystemBackground)) // Фон для всей вкладки
}
}
struct PostGridItem: View {
let post: Post
private var randomHeight: CGFloat {
CGFloat.random(in: 150...300)
}
var body: some View {
VStack(alignment: .leading, spacing: 0) { // Убираем отступ между картинкой и текстом
// 1. Медиа контент
if let _ = post.media.first {
Image("placeholderPhoto")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(height: randomHeight)
}
// Контейнер для текста, который создает эффект "расширения"
VStack(alignment: .leading, spacing: 8) {
// 2. Название поста
if let title = post.title, !title.isEmpty {
Text(title)
.font(.subheadline)
.lineLimit(2)
}
// 3. Информация об авторе и лайки
HStack {
Button(action: {
// пока ничего не делаем
}) {
HStack(spacing: 4) {
Image(systemName: "person.circle.fill")
.resizable()
.frame(width: 20, height: 20)
.foregroundColor(.gray)
Text(post.authorUsername)
.font(.footnote)
.lineLimit(1)
.foregroundColor(.primary)
}
}
.contentShape(Rectangle())
Spacer()
Button(action: {
// пока ничего не делаем
}) {
HStack(spacing: 4) {
Image(systemName: post.isLikedByCurrentUser ? "heart.fill" : "heart")
.foregroundColor(post.isLikedByCurrentUser ? .red : .primary)
Text("\(post.likes)")
.font(.subheadline)
.foregroundColor(.primary)
}
}
.contentShape(Rectangle())
}
}
.padding(8)
.background(Color(UIColor.systemBackground)) // Фон только для текстовой части
}
.cornerRadius(6) // Закругляем всю карточку
.clipped() // Обрезаем дочерние вью по закругленной форме родителя
.shadow(color: Color.black.opacity(0.1), radius: 5, x: 0, y: 2)
}
}

View File

@ -43,6 +43,15 @@ struct ProfileContentTabbedGrid: View {
.cornerRadius(8) .cornerRadius(8)
.font(.subheadline) .font(.subheadline)
Button {
// Создать пост
} label: {
Label("Создать", systemImage: "plus")
.font(.subheadline)
.padding(8)
.background(Color.blue.opacity(0.2))
.cornerRadius(8)
}
} else { } else {
TextField("Поиск", text: $searchQuery) TextField("Поиск", text: $searchQuery)
.padding(.horizontal, 10) .padding(.horizontal, 10)

View File

@ -3,17 +3,14 @@ import SwiftUI
struct ProfileTab: View { struct ProfileTab: View {
@ObservedObject var viewModel: LoginViewModel @ObservedObject var viewModel: LoginViewModel
@State private var isContentLoaded = true @State private var isContentLoaded = true
// Привязки к состояниям в MainView
@Binding var sheetType: SheetType?
@Binding var selectedAccount: String
@Binding var accounts: [String]
var onScroll: ((CGPoint) -> Void)?
@State private var accounts = ["@user1", "@user2", "@user3"]
@State private var selectedAccount = "@user1"
let followers = ["@alice", "@bob", "@charlie"] let followers = ["@alice", "@bob", "@charlie"]
let following = ["@dev", "@design", "@ios"] let following = ["@dev", "@design", "@ios"]
@State private var sheetType: SheetType? = nil
enum SheetType: Identifiable { enum SheetType: Identifiable {
case accountShare case accountShare
var id: Int { self.hashValue } var id: Int { self.hashValue }
@ -29,7 +26,7 @@ struct ProfileTab: View {
@State private var isShowingFollowing = false @State private var isShowingFollowing = false
var body: some View { var body: some View {
VStack { NavigationView {
if !isContentLoaded { if !isContentLoaded {
SplashScreenView() SplashScreenView()
} else { } else {
@ -49,13 +46,12 @@ struct ProfileTab: View {
) )
} }
RefreshableScrollView( RefreshableScrollView(isRefreshing: $isRefreshing, onRefresh: {
isRefreshing: $isRefreshing, fetchData()
onRefresh: { fetchData() }, }) {
onScroll: onScroll
) {
VStack(spacing: 12) { VStack(spacing: 12) {
header header
// .frame(minHeight: 300)
.frame(maxWidth: .infinity) .frame(maxWidth: .infinity)
.background(Color(.systemBackground)) .background(Color(.systemBackground))
@ -70,8 +66,43 @@ struct ProfileTab: View {
} }
} }
} }
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .principal) {
Button(action: { sheetType = .accountShare }) {
HStack(spacing: 4) {
Text(selectedAccount)
.font(.headline)
.foregroundColor(.primary)
Image(systemName: "chevron.down")
.font(.subheadline)
.foregroundColor(.gray)
}
}
}
ToolbarItem(placement: .navigationBarTrailing) {
NavigationLink(destination: SettingsView(viewModel: viewModel)) {
Image(systemName: "wrench")
.imageScale(.large)
}
}
}
.sheet(item: $sheetType) { type in
switch type {
case .accountShare:
AccountShareSheet(
isPresented: Binding(
get: { sheetType != nil },
set: { if !$0 { sheetType = nil } }
),
selectedAccount: $selectedAccount,
accounts: accounts
)
}
}
} }
} }
.navigationViewStyle(StackNavigationViewStyle())
.onAppear { .onAppear {
if allPosts.isEmpty { if allPosts.isEmpty {
fetchData(isInitialLoad: true) fetchData(isInitialLoad: true)

View File

@ -4,27 +4,25 @@ struct SearchTab: View {
@StateObject private var viewModel = SearchViewModel() @StateObject private var viewModel = SearchViewModel()
var body: some View { var body: some View {
VStack { NavigationView {
SearchBar(text: $viewModel.searchText) VStack {
.padding(.top, 8) SearchBar(text: $viewModel.searchText)
.padding(.top, 8)
List(viewModel.users) { user in
NavigationLink(destination: ProfileTab( List(viewModel.users) { user in
viewModel: LoginViewModel(), NavigationLink(destination: ProfileTab(viewModel: LoginViewModel())) { // Placeholder destination
sheetType: .constant(nil), HStack {
selectedAccount: .constant("@\(user.username)"), Image(systemName: "person.crop.circle")
accounts: .constant(["@\(user.username)"])) .resizable()
) { .frame(width: 40, height: 40)
HStack { .clipShape(Circle())
Image(systemName: "person.crop.circle") Text(user.username)
.resizable() }
.frame(width: 40, height: 40)
.clipShape(Circle())
Text(user.username)
} }
} }
.listStyle(PlainListStyle())
} }
.listStyle(PlainListStyle()) .navigationTitle("Поиск")
} }
} }
} }

View File

@ -1,116 +0,0 @@
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)
}
}
}

View File

@ -29,18 +29,9 @@
1A7940E72DF7B5E5002569DA /* SplashScreenView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A7940E62DF7B5E5002569DA /* SplashScreenView.swift */; }; 1A7940E72DF7B5E5002569DA /* SplashScreenView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A7940E62DF7B5E5002569DA /* SplashScreenView.swift */; };
1A7940F02DF7B7A3002569DA /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1A7940F22DF7B7A3002569DA /* Localizable.strings */; }; 1A7940F02DF7B7A3002569DA /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1A7940F22DF7B7A3002569DA /* Localizable.strings */; };
1A79410C2DF7C81D002569DA /* RegistrationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A79410B2DF7C81D002569DA /* RegistrationView.swift */; }; 1A79410C2DF7C81D002569DA /* RegistrationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A79410B2DF7C81D002569DA /* RegistrationView.swift */; };
1A9B014B2E4BF3CD00887E0B /* NewHomeTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A9B014A2E4BF3CD00887E0B /* NewHomeTab.swift */; };
1A9B01582E4BF50D00887E0B /* placeholderVideo.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 1A9B01572E4BF50D00887E0B /* placeholderVideo.mp4 */; };
1A9B015F2E4BF9C000887E0B /* placeholderPhotoSquare.png in Resources */ = {isa = PBXBuildFile; fileRef = 1A9B015D2E4BF9C000887E0B /* placeholderPhotoSquare.png */; };
1A9B01602E4BF9C000887E0B /* placeholderPhoto.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 1A9B015E2E4BF9C000887E0B /* placeholderPhoto.jpg */; };
1A9B01662E4BFA3600887E0B /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A9B01652E4BFA3600887E0B /* Media.xcassets */; };
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 */; };
1AB7F5162E32EC1C003756F3 /* RefreshableScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AB7F5142E32EC1C003756F3 /* RefreshableScrollView.swift */; };
1AB7F5172E32EC1C003756F3 /* TopBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AB7F5152E32EC1C003756F3 /* TopBarView.swift */; };
1ACE60F82E22F3DC00B37AC5 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ACE60F72E22F3DC00B37AC5 /* SettingsView.swift */; }; 1ACE60F82E22F3DC00B37AC5 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ACE60F72E22F3DC00B37AC5 /* SettingsView.swift */; };
1ACE61012E22F55C00B37AC5 /* EditProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ACE61002E22F55C00B37AC5 /* EditProfileView.swift */; }; 1ACE61012E22F55C00B37AC5 /* EditProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ACE61002E22F55C00B37AC5 /* EditProfileView.swift */; };
1ACE61052E22F56800B37AC5 /* SecuritySettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ACE61042E22F56800B37AC5 /* SecuritySettingsView.swift */; }; 1ACE61052E22F56800B37AC5 /* SecuritySettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ACE61042E22F56800B37AC5 /* SecuritySettingsView.swift */; };
@ -49,6 +40,7 @@
1ACE61192E22FF1400B37AC5 /* Post.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ACE61182E22FF1400B37AC5 /* Post.swift */; }; 1ACE61192E22FF1400B37AC5 /* Post.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ACE61182E22FF1400B37AC5 /* Post.swift */; };
1ACE61212E22FFD000B37AC5 /* ProfileContentTabbedGrid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ACE61202E22FFD000B37AC5 /* ProfileContentTabbedGrid.swift */; }; 1ACE61212E22FFD000B37AC5 /* ProfileContentTabbedGrid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ACE61202E22FFD000B37AC5 /* ProfileContentTabbedGrid.swift */; };
1AD757CD2E27608C0069C1FD /* PostFeedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AD757CC2E27608C0069C1FD /* PostFeedView.swift */; }; 1AD757CD2E27608C0069C1FD /* PostFeedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AD757CC2E27608C0069C1FD /* PostFeedView.swift */; };
1AD757D12E27640F0069C1FD /* RefreshableScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AD757D02E27640F0069C1FD /* RefreshableScrollView.swift */; };
1AE587052E23264800254F06 /* PostService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AE587042E23264800254F06 /* PostService.swift */; }; 1AE587052E23264800254F06 /* PostService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AE587042E23264800254F06 /* PostService.swift */; };
1AE587252E23337000254F06 /* ProfileContentGrid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AE587242E23337000254F06 /* ProfileContentGrid.swift */; }; 1AE587252E23337000254F06 /* ProfileContentGrid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AE587242E23337000254F06 /* ProfileContentGrid.swift */; };
1AEE5EAB2E21A83200A3DCA3 /* HomeTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AEE5EAA2E21A83200A3DCA3 /* HomeTab.swift */; }; 1AEE5EAB2E21A83200A3DCA3 /* HomeTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AEE5EAA2E21A83200A3DCA3 /* HomeTab.swift */; };
@ -73,7 +65,7 @@
1A7940A52DF77DF5002569DA /* User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = "<group>"; }; 1A7940A52DF77DF5002569DA /* User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = "<group>"; };
1A7940A92DF77E05002569DA /* LoginViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewModel.swift; sourceTree = "<group>"; }; 1A7940A92DF77E05002569DA /* LoginViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewModel.swift; sourceTree = "<group>"; };
1A7940AF2DF77E26002569DA /* LoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginView.swift; sourceTree = "<group>"; }; 1A7940AF2DF77E26002569DA /* LoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginView.swift; sourceTree = "<group>"; };
1A7940B52DF77F21002569DA /* MainView.swift */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = "<group>"; tabWidth = 4; }; 1A7940B52DF77F21002569DA /* MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = "<group>"; };
1A7940C52DF7A98E002569DA /* ContactsTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactsTab.swift; sourceTree = "<group>"; }; 1A7940C52DF7A98E002569DA /* ContactsTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactsTab.swift; sourceTree = "<group>"; };
1A7940C92DF7A99B002569DA /* ChatsTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatsTab.swift; sourceTree = "<group>"; }; 1A7940C92DF7A99B002569DA /* ChatsTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatsTab.swift; sourceTree = "<group>"; };
1A7940CD2DF7A9AA002569DA /* ProfileTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileTab.swift; sourceTree = "<group>"; }; 1A7940CD2DF7A9AA002569DA /* ProfileTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileTab.swift; sourceTree = "<group>"; };
@ -83,18 +75,9 @@
1A7940F12DF7B7A3002569DA /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; }; 1A7940F12DF7B7A3002569DA /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
1A7940F72DF7B7EC002569DA /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = "<group>"; }; 1A7940F72DF7B7EC002569DA /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = "<group>"; };
1A79410B2DF7C81D002569DA /* RegistrationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegistrationView.swift; sourceTree = "<group>"; }; 1A79410B2DF7C81D002569DA /* RegistrationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegistrationView.swift; sourceTree = "<group>"; };
1A9B014A2E4BF3CD00887E0B /* NewHomeTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewHomeTab.swift; sourceTree = "<group>"; };
1A9B01572E4BF50D00887E0B /* placeholderVideo.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; name = placeholderVideo.mp4; path = ../../../../Volumes/Untitled/xcode/volnahub/Shared/Media/placeholderVideo.mp4; sourceTree = DEVELOPER_DIR; };
1A9B015D2E4BF9C000887E0B /* placeholderPhotoSquare.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = placeholderPhotoSquare.png; path = ../../../../Volumes/Untitled/xcode/volnahub/Shared/Media/placeholderPhotoSquare.png; 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>"; };
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>"; };
1AB7F5142E32EC1C003756F3 /* RefreshableScrollView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RefreshableScrollView.swift; sourceTree = "<group>"; };
1AB7F5152E32EC1C003756F3 /* TopBarView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopBarView.swift; sourceTree = "<group>"; };
1ACE60F72E22F3DC00B37AC5 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; }; 1ACE60F72E22F3DC00B37AC5 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
1ACE61002E22F55C00B37AC5 /* EditProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditProfileView.swift; sourceTree = "<group>"; }; 1ACE61002E22F55C00B37AC5 /* EditProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditProfileView.swift; sourceTree = "<group>"; };
1ACE61042E22F56800B37AC5 /* SecuritySettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecuritySettingsView.swift; sourceTree = "<group>"; }; 1ACE61042E22F56800B37AC5 /* SecuritySettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecuritySettingsView.swift; sourceTree = "<group>"; };
@ -103,6 +86,7 @@
1ACE61182E22FF1400B37AC5 /* Post.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Post.swift; sourceTree = "<group>"; }; 1ACE61182E22FF1400B37AC5 /* Post.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Post.swift; sourceTree = "<group>"; };
1ACE61202E22FFD000B37AC5 /* ProfileContentTabbedGrid.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileContentTabbedGrid.swift; sourceTree = "<group>"; }; 1ACE61202E22FFD000B37AC5 /* ProfileContentTabbedGrid.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileContentTabbedGrid.swift; sourceTree = "<group>"; };
1AD757CC2E27608C0069C1FD /* PostFeedView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PostFeedView.swift; sourceTree = "<group>"; }; 1AD757CC2E27608C0069C1FD /* PostFeedView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PostFeedView.swift; sourceTree = "<group>"; };
1AD757D02E27640F0069C1FD /* RefreshableScrollView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RefreshableScrollView.swift; path = Components/RefreshableScrollView.swift; sourceTree = "<group>"; };
1AE587042E23264800254F06 /* PostService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostService.swift; sourceTree = "<group>"; }; 1AE587042E23264800254F06 /* PostService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostService.swift; sourceTree = "<group>"; };
1AE587242E23337000254F06 /* ProfileContentGrid.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileContentGrid.swift; sourceTree = "<group>"; }; 1AE587242E23337000254F06 /* ProfileContentGrid.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileContentGrid.swift; sourceTree = "<group>"; };
1AEE5EAA2E21A83200A3DCA3 /* HomeTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeTab.swift; sourceTree = "<group>"; }; 1AEE5EAA2E21A83200A3DCA3 /* HomeTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeTab.swift; sourceTree = "<group>"; };
@ -141,8 +125,7 @@
1A7940792DF77BC2002569DA /* Shared */ = { 1A7940792DF77BC2002569DA /* Shared */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
1A9B01502E4BF49200887E0B /* Media */, 1AD757D02E27640F0069C1FD /* RefreshableScrollView.swift */,
1AB7F5132E32EBF1003756F3 /* Components */,
1A7940FA2DF7B898002569DA /* Resources */, 1A7940FA2DF7B898002569DA /* Resources */,
1A7940E52DF7B341002569DA /* Services */, 1A7940E52DF7B341002569DA /* Services */,
1A7940A02DF77DCD002569DA /* Network */, 1A7940A02DF77DCD002569DA /* Network */,
@ -198,7 +181,6 @@
1A79409E2DF77DBD002569DA /* ViewModels */ = { 1A79409E2DF77DBD002569DA /* ViewModels */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
1A9B016D2E4BFB9000887E0B /* NewHomeTabViewModel.swift */,
1A2302102E3050C60067BF4F /* SearchViewModel.swift */, 1A2302102E3050C60067BF4F /* SearchViewModel.swift */,
1A7940A92DF77E05002569DA /* LoginViewModel.swift */, 1A7940A92DF77E05002569DA /* LoginViewModel.swift */,
); );
@ -240,26 +222,6 @@
path = Resources; path = Resources;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
1A9B01502E4BF49200887E0B /* Media */ = {
isa = PBXGroup;
children = (
1A9B01652E4BFA3600887E0B /* Media.xcassets */,
1A9B015E2E4BF9C000887E0B /* placeholderPhoto.jpg */,
1A9B015D2E4BF9C000887E0B /* placeholderPhotoSquare.png */,
1A9B01572E4BF50D00887E0B /* placeholderVideo.mp4 */,
);
path = Media;
sourceTree = "<group>";
};
1AB7F5132E32EBF1003756F3 /* Components */ = {
isa = PBXGroup;
children = (
1AB7F5142E32EC1C003756F3 /* RefreshableScrollView.swift */,
1AB7F5152E32EC1C003756F3 /* TopBarView.swift */,
);
path = Components;
sourceTree = "<group>";
};
1ACE60FF2E22F54700B37AC5 /* Settings */ = { 1ACE60FF2E22F54700B37AC5 /* Settings */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -290,10 +252,8 @@
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 */,
1AEE5EAA2E21A83200A3DCA3 /* HomeTab.swift */, 1AEE5EAA2E21A83200A3DCA3 /* HomeTab.swift */,
1AEE5EB22E21A85800A3DCA3 /* SearchTab.swift */, 1AEE5EB22E21A85800A3DCA3 /* SearchTab.swift */,
1A7940C92DF7A99B002569DA /* ChatsTab.swift */, 1A7940C92DF7A99B002569DA /* ChatsTab.swift */,
@ -399,12 +359,8 @@
isa = PBXResourcesBuildPhase; isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
1A9B01582E4BF50D00887E0B /* placeholderVideo.mp4 in Resources */,
1A7940912DF77BC3002569DA /* Assets.xcassets in Resources */, 1A7940912DF77BC3002569DA /* Assets.xcassets in Resources */,
1A7940F02DF7B7A3002569DA /* Localizable.strings in Resources */, 1A7940F02DF7B7A3002569DA /* Localizable.strings in Resources */,
1A9B01602E4BF9C000887E0B /* placeholderPhoto.jpg in Resources */,
1A9B01662E4BFA3600887E0B /* Media.xcassets in Resources */,
1A9B015F2E4BF9C000887E0B /* placeholderPhotoSquare.png in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -426,27 +382,22 @@
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 */,
1A9B016E2E4BFB9000887E0B /* NewHomeTabViewModel.swift in Sources */,
1A7940E72DF7B5E5002569DA /* SplashScreenView.swift in Sources */, 1A7940E72DF7B5E5002569DA /* SplashScreenView.swift in Sources */,
1A7940B02DF77E26002569DA /* LoginView.swift in Sources */, 1A7940B02DF77E26002569DA /* LoginView.swift in Sources */,
1A79410C2DF7C81D002569DA /* RegistrationView.swift in Sources */, 1A79410C2DF7C81D002569DA /* RegistrationView.swift in Sources */,
1A0276112DF9247000D8BC53 /* CustomTextField.swift in Sources */, 1A0276112DF9247000D8BC53 /* CustomTextField.swift in Sources */,
1AB7F5172E32EC1C003756F3 /* TopBarView.swift in Sources */,
1A7940CE2DF7A9AA002569DA /* ProfileTab.swift in Sources */, 1A7940CE2DF7A9AA002569DA /* ProfileTab.swift in Sources */,
1ACE61212E22FFD000B37AC5 /* ProfileContentTabbedGrid.swift in Sources */, 1ACE61212E22FFD000B37AC5 /* ProfileContentTabbedGrid.swift in Sources */,
1AB4F8F72E22ECAC002B6E40 /* FollowingView.swift in Sources */, 1AB4F8F72E22ECAC002B6E40 /* FollowingView.swift in Sources */,
1A7940DE2DF7B0D7002569DA /* config.swift in Sources */, 1A7940DE2DF7B0D7002569DA /* config.swift in Sources */,
1A9B014B2E4BF3CD00887E0B /* NewHomeTab.swift in Sources */,
1A2302112E3050C60067BF4F /* SearchViewModel.swift in Sources */, 1A2302112E3050C60067BF4F /* SearchViewModel.swift in Sources */,
1AE587252E23337000254F06 /* ProfileContentGrid.swift in Sources */, 1AE587252E23337000254F06 /* ProfileContentGrid.swift in Sources */,
1A6FB9552E32D2B200E89EBE /* CustomTabBar.swift in Sources */, 1A6FB9552E32D2B200E89EBE /* CustomTabBar.swift in Sources */,
1A0276032DF909F900D8BC53 /* refreshtokenex.swift in Sources */, 1A0276032DF909F900D8BC53 /* refreshtokenex.swift in Sources */,
1A7940B62DF77F21002569DA /* MainView.swift in Sources */, 1A7940B62DF77F21002569DA /* MainView.swift in Sources */,
1AB7F5162E32EC1C003756F3 /* RefreshableScrollView.swift in Sources */,
1A7940E22DF7B1C5002569DA /* KeychainService.swift in Sources */, 1A7940E22DF7B1C5002569DA /* KeychainService.swift in Sources */,
1A7940A62DF77DF5002569DA /* User.swift in Sources */, 1A7940A62DF77DF5002569DA /* User.swift in Sources */,
1A7940A22DF77DE9002569DA /* AuthService.swift in Sources */, 1A7940A22DF77DE9002569DA /* AuthService.swift in Sources */,
@ -462,6 +413,7 @@
1A7940AA2DF77E05002569DA /* LoginViewModel.swift in Sources */, 1A7940AA2DF77E05002569DA /* LoginViewModel.swift in Sources */,
1AB4F8F32E22EC9F002B6E40 /* FollowersView.swift in Sources */, 1AB4F8F32E22EC9F002B6E40 /* FollowersView.swift in Sources */,
1A79408D2DF77BC3002569DA /* yobbleApp.swift in Sources */, 1A79408D2DF77BC3002569DA /* yobbleApp.swift in Sources */,
1AD757D12E27640F0069C1FD /* RefreshableScrollView.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

View File

@ -17,12 +17,12 @@
<key>yobble (iOS).xcscheme_^#shared#^_</key> <key>yobble (iOS).xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>1</integer> <integer>0</integer>
</dict> </dict>
<key>yobble (macOS).xcscheme_^#shared#^_</key> <key>yobble (macOS).xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>0</integer> <integer>1</integer>
</dict> </dict>
</dict> </dict>
</dict> </dict>