Commit
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
import SwiftUI
|
||||
|
||||
struct CreatedClassView: View {
|
||||
@ObservedObject var _class: ClassModel
|
||||
@ObservedObject var _class: CoreDataClassModel
|
||||
var provider = ClassProvider.shared
|
||||
var body: some View {
|
||||
let existingCopy = try? provider.viewContext.existingObject(with: _class.objectID)
|
||||
|
50
Schedule ICTIS/Main/Views/FilterGroupsView.swift
Normal file
50
Schedule ICTIS/Main/Views/FilterGroupsView.swift
Normal file
@ -0,0 +1,50 @@
|
||||
//
|
||||
// FilterGroupsView.swift
|
||||
// Schedule ICTIS
|
||||
//
|
||||
// Created by Mironov Egor on 21.03.2025.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct FilterGroupsView: View {
|
||||
@ObservedObject var vm: ScheduleViewModel
|
||||
var body: some View {
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
HStack(spacing: 12) {
|
||||
ForEach(vm.filteringGroups, id: \.self) { group in
|
||||
VStack {
|
||||
Text(group)
|
||||
.foregroundColor(Color("customGray3"))
|
||||
.font(.custom("Montserrat-Medium", fixedSize: 14))
|
||||
.padding(.horizontal, 15)
|
||||
.padding(.vertical, 7)
|
||||
}
|
||||
.background(Color.white)
|
||||
.overlay (
|
||||
Group {
|
||||
if vm.showOnlyChoosenGroup == group {
|
||||
RoundedRectangle(cornerRadius: 20)
|
||||
.stroke(Color("blueColor"), lineWidth: 3)
|
||||
}
|
||||
}
|
||||
)
|
||||
.cornerRadius(20)
|
||||
.onTapGesture {
|
||||
vm.showOnlyChoosenGroup = group
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.horizontal)
|
||||
}
|
||||
.onAppear {
|
||||
vm.updateFilteringGroups()
|
||||
}
|
||||
.padding(.bottom, 10)
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
@Previewable @ObservedObject var vm = ScheduleViewModel()
|
||||
FilterGroupsView(vm: vm)
|
||||
}
|
@ -11,9 +11,9 @@ struct MainView: View {
|
||||
@State private var searchText: String = ""
|
||||
@State private var isShowingMonthSlider: Bool = false
|
||||
@ObservedObject var vm: ScheduleViewModel
|
||||
@ObservedObject var networkMonitor: NetworkMonitor
|
||||
@FocusState private var isFocusedSearchBar: Bool
|
||||
@State private var isScrolling: Bool = false
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
SearchBarView(text: $searchText, isFocused: _isFocusedSearchBar, vm: vm, isShowingMonthSlider: $isShowingMonthSlider)
|
||||
@ -23,11 +23,12 @@ struct MainView: View {
|
||||
}
|
||||
}
|
||||
CurrentDateView()
|
||||
FilterGroupsView(vm: vm)
|
||||
if vm.isLoading {
|
||||
LoadingScheduleView()
|
||||
}
|
||||
else {
|
||||
ScheduleView(vm: vm, isScrolling: $isScrolling)
|
||||
ScheduleView(vm: vm, networkMonitor: networkMonitor, isScrolling: $isScrolling)
|
||||
}
|
||||
}
|
||||
.alert(isPresented: $vm.isShowingAlertForIncorrectGroup, error: vm.errorInNetwork) { error in
|
||||
@ -87,12 +88,10 @@ struct MainView: View {
|
||||
else {
|
||||
MonthTabView(vm: vm)
|
||||
.transition(.opacity)
|
||||
.animation(.easeInOut(duration: 0.25), value: isShowingMonthSlider)
|
||||
.animation(.linear(duration: 0.5), value: isShowingMonthSlider)
|
||||
}
|
||||
}
|
||||
.padding(.horizontal)
|
||||
}
|
||||
}
|
||||
#Preview {
|
||||
ContentView()
|
||||
}
|
||||
|
||||
|
@ -1,131 +1,254 @@
|
||||
//
|
||||
// ScheduleView.swift
|
||||
// Schedule ICTIS
|
||||
//
|
||||
// Created by Mironov Egor on 05.12.2024.
|
||||
// ктбо2-6
|
||||
|
||||
import SwiftUI
|
||||
import CoreData
|
||||
|
||||
struct ScheduleView: View {
|
||||
@ObservedObject var vm: ScheduleViewModel
|
||||
@FetchRequest(fetchRequest: ClassModel.all()) private var classes // Делаем запрос в CoreData и получаем список сохраненных пар
|
||||
@State private var selectedClass: ClassModel? = nil
|
||||
@ObservedObject var networkMonitor: NetworkMonitor
|
||||
@FetchRequest(fetchRequest: CoreDataClassModel.all()) private var classes // Список пар добавленных пользователем
|
||||
@FetchRequest(fetchRequest: JsonClassModel.all()) private var subjects // Список пар сохраненных в CoreData
|
||||
@State private var selectedClass: CoreDataClassModel? = nil
|
||||
@State private var lastOffset: CGFloat = 0
|
||||
@State private var scrollTimer: Timer? = nil
|
||||
@State private var isShowingMyPairs = false
|
||||
@Binding var isScrolling: Bool
|
||||
var provider = ClassProvider.shared
|
||||
var body: some View {
|
||||
if vm.isLoading {
|
||||
LoadingScheduleView()
|
||||
|
||||
private var hasSubjectsToShow: Bool {
|
||||
subjects.contains { subject in
|
||||
subject.week == vm.week
|
||||
}
|
||||
else {
|
||||
if vm.errorInNetwork != .invalidResponse {
|
||||
ZStack (alignment: .top) {
|
||||
ScrollView(.vertical, showsIndicators: false) {
|
||||
VStack (spacing: 30) {
|
||||
VStack (alignment: .leading, spacing: 10) {
|
||||
ForEach(0..<vm.classesGroups.count, id: \.self) { dayIndex in
|
||||
if dayIndex == vm.selectedIndex {
|
||||
ForEach(vm.classesGroups[dayIndex]) { info in
|
||||
VStack (alignment: .trailing) {
|
||||
Text(info.group)
|
||||
.font(.custom("Montserrat-Regular", fixedSize: 11))
|
||||
.foregroundColor(Color("grayForNameGroup"))
|
||||
HStack(spacing: 15) {
|
||||
VStack {
|
||||
Text(convertTimeString(info.time)[0])
|
||||
.font(.custom("Montserrat-Regular", fixedSize: 15))
|
||||
.padding(.bottom, 1)
|
||||
Text(convertTimeString(info.time)[1])
|
||||
.font(.custom("Montserrat-Regular", fixedSize: 15))
|
||||
.padding(.top, 1)
|
||||
}
|
||||
.frame(width: 48)
|
||||
.padding(.top, 7)
|
||||
.padding(.bottom, 7)
|
||||
.padding(.leading, 10)
|
||||
Rectangle()
|
||||
.frame(width: 2)
|
||||
.frame(maxHeight: UIScreen.main.bounds.height - 18)
|
||||
.padding(.top, 7)
|
||||
.padding(.bottom, 7)
|
||||
.foregroundColor(getColorForClass(info.subject))
|
||||
Text(info.subject)
|
||||
.font(.custom("Montserrat-Medium", fixedSize: 16))
|
||||
.lineSpacing(3)
|
||||
.padding(.top, 9)
|
||||
.padding(.bottom, 9)
|
||||
Spacer()
|
||||
}
|
||||
.frame(maxWidth: UIScreen.main.bounds.width - 40, maxHeight: 230)
|
||||
.background(Color.white)
|
||||
.cornerRadius(20)
|
||||
.shadow(color: .black.opacity(0.25), radius: 4, x: 2, y: 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if classes.contains(where: { daysAreEqual($0.day, vm.selectedDay) }) {
|
||||
VStack(alignment: .leading, spacing: 20) {
|
||||
Text("Мои пары")
|
||||
.font(.custom("Montserrat-Bold", fixedSize: 20))
|
||||
ForEach(classes) { _class in
|
||||
if daysAreEqual(_class.day, vm.selectedDay) {
|
||||
CreatedClassView(_class: _class)
|
||||
.onTapGesture {
|
||||
selectedClass = _class
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(width: UIScreen.main.bounds.width)
|
||||
.padding(.bottom, 100)
|
||||
.padding(.top, 10)
|
||||
.background(GeometryReader { geometry in
|
||||
Color.clear.preference(key: ViewOffsetKey.self, value: geometry.frame(in: .global).minY)
|
||||
})
|
||||
}
|
||||
.onPreferenceChange(ViewOffsetKey.self) { offset in
|
||||
if offset != lastOffset {
|
||||
// Скролл происходит
|
||||
isScrolling = true
|
||||
|
||||
// Останавливаем предыдущий таймер
|
||||
scrollTimer?.invalidate()
|
||||
// Запускаем новый таймер
|
||||
scrollTimer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: false) { _ in
|
||||
// Скролл остановился
|
||||
isScrolling = false
|
||||
}
|
||||
}
|
||||
lastOffset = offset
|
||||
}
|
||||
.onDisappear {
|
||||
scrollTimer?.invalidate()
|
||||
}
|
||||
VStack {
|
||||
LinearGradient(gradient: Gradient(colors: [Color("background").opacity(0.95), Color.white.opacity(0.1)]), startPoint: .top, endPoint: .bottom)
|
||||
}
|
||||
.frame(width: UIScreen.main.bounds.width, height: 15)
|
||||
}
|
||||
//Sheet будет открываться, когда selectedClass будет становиться не nil
|
||||
.sheet(item: $selectedClass,
|
||||
onDismiss: {
|
||||
selectedClass = nil
|
||||
},
|
||||
content: { _class in
|
||||
CreateEditClassView(vm: .init(provider: provider, _class: _class), day: vm.selectedDay)
|
||||
})
|
||||
}
|
||||
|
||||
private var hasClassesToShow: Bool {
|
||||
classes.contains { _class in
|
||||
_class.day == vm.selectedDay
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
ZStack(alignment: .top) {
|
||||
if networkMonitor.isConnected {
|
||||
onlineContent
|
||||
} else {
|
||||
offlineContent
|
||||
}
|
||||
else {
|
||||
gradientOverlay
|
||||
}
|
||||
.onAppear {
|
||||
deleteClassesFormCoreDataIfMonday()
|
||||
if networkMonitor.isConnected {
|
||||
checkSavingOncePerDay()
|
||||
}
|
||||
}
|
||||
.sheet(item: $selectedClass, onDismiss: { selectedClass = nil }) { _class in
|
||||
CreateEditClassView(vm: .init(provider: provider, _class: _class), day: vm.selectedDay)
|
||||
}
|
||||
}
|
||||
|
||||
// Онлайн-контент (с интернетом)
|
||||
private var onlineContent: some View {
|
||||
Group {
|
||||
if vm.errorInNetwork == .timeout {
|
||||
NetworkErrorView()
|
||||
} else if vm.isLoading {
|
||||
LoadingScheduleView()
|
||||
} else if vm.errorInNetwork != .invalidResponse {
|
||||
scheduleScrollView(isOnline: true)
|
||||
} else {
|
||||
NoScheduleView()
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
if vm.classesGroups.isEmpty {
|
||||
vm.fetchWeekSchedule()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Оффлайн-контент (без интернета)
|
||||
private var offlineContent: some View {
|
||||
scheduleScrollView(isOnline: false)
|
||||
}
|
||||
|
||||
// Общий ScrollView для расписания
|
||||
private func scheduleScrollView(isOnline: Bool) -> some View {
|
||||
ScrollView(.vertical, showsIndicators: false) {
|
||||
VStack(spacing: 30) {
|
||||
subjectsSection(isOnline: isOnline)
|
||||
myPairsSection
|
||||
}
|
||||
.frame(width: UIScreen.main.bounds.width)
|
||||
.padding(.bottom, 100)
|
||||
.padding(.top, 10)
|
||||
.background(GeometryReader { geometry in
|
||||
Color.clear.preference(key: ViewOffsetKey.self, value: geometry.frame(in: .global).minY)
|
||||
})
|
||||
}
|
||||
.onPreferenceChange(ViewOffsetKey.self) { offset in
|
||||
if offset != lastOffset {
|
||||
isScrolling = true
|
||||
scrollTimer?.invalidate()
|
||||
scrollTimer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: false) { _ in
|
||||
isScrolling = false
|
||||
}
|
||||
}
|
||||
lastOffset = offset
|
||||
}
|
||||
.onDisappear {
|
||||
scrollTimer?.invalidate()
|
||||
}
|
||||
}
|
||||
|
||||
// Секция с парами
|
||||
private func subjectsSection(isOnline: Bool) -> some View {
|
||||
VStack(alignment: .leading, spacing: 10) {
|
||||
if isOnline {
|
||||
ForEach(0..<vm.classesGroups.count, id: \.self) { dayIndex in
|
||||
if dayIndex == vm.selectedIndex {
|
||||
ForEach(vm.classesGroups[dayIndex]) { info in
|
||||
if vm.showOnlyChoosenGroup == "Все" || info.group == vm.showOnlyChoosenGroup {
|
||||
SubjectView(info: ClassInfo(subject: info.subject, group: info.group, time: info.time), vm: vm)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let filteredSubjects = subjects.filter { $0.day == Int16(vm.selectedIndex) }
|
||||
if (filteredSubjects.isEmpty || vm.week != 0) && !hasClassesToShow {
|
||||
NetworkErrorView()
|
||||
} else {
|
||||
ForEach(filteredSubjects, id: \.self) { subject in
|
||||
if (vm.showOnlyChoosenGroup == "Все" || subject.group == vm.showOnlyChoosenGroup) && vm.week == 0 {
|
||||
SubjectView(info: ClassInfo(subject: subject.name!, group: subject.group!, time: subject.time!), vm: vm)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Секция "Мои пары"
|
||||
private var myPairsSection: some View {
|
||||
Group {
|
||||
if classes.contains(where: { daysAreEqual($0.day, vm.selectedDay) }) {
|
||||
VStack(alignment: .leading, spacing: 20) {
|
||||
Text("Мои пары")
|
||||
.font(.custom("Montserrat-Bold", fixedSize: 20))
|
||||
ForEach(classes) { _class in
|
||||
if daysAreEqual(_class.day, vm.selectedDay) {
|
||||
CreatedClassView(_class: _class)
|
||||
.onTapGesture {
|
||||
selectedClass = _class
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Градиентный оверлей
|
||||
private var gradientOverlay: some View {
|
||||
VStack {
|
||||
LinearGradient(
|
||||
gradient: Gradient(colors: [Color("background").opacity(0.95), Color.white.opacity(0.1)]),
|
||||
startPoint: .top,
|
||||
endPoint: .bottom
|
||||
)
|
||||
}
|
||||
.frame(width: UIScreen.main.bounds.width, height: 15)
|
||||
}
|
||||
}
|
||||
|
||||
extension ScheduleView {
|
||||
private func deleteClassesFormCoreDataIfMonday() {
|
||||
let today = Date()
|
||||
let calendar = Calendar.current
|
||||
let weekday = calendar.component(.weekday, from: today)
|
||||
|
||||
if weekday == 6 {
|
||||
for _class in classes {
|
||||
if _class.day < today {
|
||||
do {
|
||||
try provider.delete(_class, in: provider.viewContext)
|
||||
} catch {
|
||||
print("❌ - Ошибка при удалении: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func saveGroupsToMemory() {
|
||||
var indexOfTheDay: Int16 = 0
|
||||
let context = provider.newContext // Создаем новый контекст
|
||||
|
||||
context.perform {
|
||||
for dayIndex in 0..<self.vm.classesGroups.count {
|
||||
let classesForDay = self.vm.classesGroups[dayIndex]
|
||||
|
||||
// Проходим по всем занятиям текущего дня
|
||||
for classInfo in classesForDay {
|
||||
let newClass = JsonClassModel(context: context)
|
||||
|
||||
// Заполняем атрибуты
|
||||
newClass.name = classInfo.subject
|
||||
newClass.group = classInfo.group
|
||||
newClass.time = classInfo.time
|
||||
newClass.day = indexOfTheDay
|
||||
newClass.week = Int16(vm.week)
|
||||
}
|
||||
indexOfTheDay += 1
|
||||
}
|
||||
|
||||
// Сохраняем изменения в CoreData
|
||||
do {
|
||||
try self.provider.persist(in: context)
|
||||
print("✅ Успешно сохранено в CoreData")
|
||||
} catch {
|
||||
print("❌ Ошибка при сохранении в CoreData: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
func deleteAllJsonClassModelsSync() throws {
|
||||
let context = provider.viewContext
|
||||
|
||||
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = JsonClassModel.fetchRequest()
|
||||
let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
|
||||
|
||||
try context.execute(deleteRequest)
|
||||
try context.save()
|
||||
print("✅ Все объекты JsonClassModel успешно удалены")
|
||||
}
|
||||
|
||||
func checkSavingOncePerDay() {
|
||||
let today = Date()
|
||||
let calendar = Calendar.current
|
||||
let todayStart = calendar.startOfDay(for: today) // Начало текущего дня
|
||||
|
||||
// Получаем дату последнего выполнения из UserDefaults
|
||||
let lastCheckDate = UserDefaults.standard.object(forKey: "LastSaving") as? Date ?? .distantPast
|
||||
let lastCheckStart = calendar.startOfDay(for: lastCheckDate)
|
||||
|
||||
print("Дата последнего сохранения расписания в CoreData: \(lastCheckDate)")
|
||||
|
||||
// Проверяем, был ли уже выполнен код сегодня
|
||||
if lastCheckStart < todayStart && networkMonitor.isConnected {
|
||||
print("✅ Интернет есть, сохранение пар в CoreData")
|
||||
vm.fillDictForVm()
|
||||
vm.fetchWeekSchedule()
|
||||
do {
|
||||
try deleteAllJsonClassModelsSync()
|
||||
} catch {
|
||||
print("Ошибка при удалении: \(error)")
|
||||
return
|
||||
}
|
||||
saveGroupsToMemory()
|
||||
|
||||
// Сохраняем текущую дату как дату последнего выполнения
|
||||
UserDefaults.standard.set(today, forKey: "LastSaving")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,7 +259,3 @@ struct ViewOffsetKey: PreferenceKey {
|
||||
value += nextValue()
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
ContentView()
|
||||
}
|
||||
|
@ -31,9 +31,11 @@ struct SearchBarView: View {
|
||||
if (!text.isEmpty) {
|
||||
vm.nameToHtml[vm.searchingGroup] = nil
|
||||
vm.removeFromSchedule(group: vm.searchingGroup)
|
||||
text = transformStringToFormat(text)
|
||||
vm.searchingGroup = text
|
||||
vm.nameToHtml[text] = ""
|
||||
vm.fetchWeekSchedule()
|
||||
vm.updateFilteringGroups()
|
||||
}
|
||||
self.text = ""
|
||||
}
|
||||
@ -88,6 +90,3 @@ struct SearchBarView: View {
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
ContentView()
|
||||
}
|
||||
|
61
Schedule ICTIS/Main/Views/SubjectView.swift
Normal file
61
Schedule ICTIS/Main/Views/SubjectView.swift
Normal file
@ -0,0 +1,61 @@
|
||||
//
|
||||
// SubjectView.swift
|
||||
// Schedule ICTIS
|
||||
//
|
||||
// Created by Egor Mironov on 02.04.2025.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct SubjectView: View {
|
||||
let info: ClassInfo
|
||||
@ObservedObject var vm: ScheduleViewModel
|
||||
@State private var onlyOneGroup: Bool = false
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .trailing) {
|
||||
if !onlyOneGroup {
|
||||
Text(info.group)
|
||||
.font(.custom("Montserrat-Regular", fixedSize: 11))
|
||||
.foregroundColor(Color("grayForNameGroup"))
|
||||
}
|
||||
HStack(spacing: 15) {
|
||||
VStack {
|
||||
Text(convertTimeString(info.time)[0])
|
||||
.font(.custom("Montserrat-Regular", fixedSize: 15))
|
||||
.padding(.bottom, 1)
|
||||
Text(convertTimeString(info.time)[1])
|
||||
.font(.custom("Montserrat-Regular", fixedSize: 15))
|
||||
.padding(.top, 1)
|
||||
}
|
||||
.frame(width: 48)
|
||||
.padding(.top, 7)
|
||||
.padding(.bottom, 7)
|
||||
.padding(.leading, 10)
|
||||
Rectangle()
|
||||
.frame(width: 2)
|
||||
.frame(maxHeight: UIScreen.main.bounds.height - 18)
|
||||
.padding(.top, 7)
|
||||
.padding(.bottom, 7)
|
||||
.foregroundColor(getColorForClass(info.subject))
|
||||
Text(info.subject)
|
||||
.font(.custom("Montserrat-Medium", fixedSize: 16))
|
||||
.lineSpacing(3)
|
||||
.padding(.top, 9)
|
||||
.padding(.bottom, 9)
|
||||
Spacer()
|
||||
}
|
||||
.frame(maxWidth: UIScreen.main.bounds.width - 40, maxHeight: 230)
|
||||
.background(Color.white)
|
||||
.cornerRadius(20)
|
||||
.shadow(color: .black.opacity(0.25), radius: 4, x: 2, y: 2)
|
||||
}
|
||||
.onAppear {
|
||||
onlyOneGroup = (vm.showOnlyChoosenGroup != vm.filteringGroups[0])
|
||||
}
|
||||
.padding(.bottom, onlyOneGroup ? 17 : 0)
|
||||
.onChange(of: vm.showOnlyChoosenGroup) { oldValue, newValue in
|
||||
onlyOneGroup = (newValue != vm.filteringGroups[0])
|
||||
}
|
||||
}
|
||||
}
|
@ -15,31 +15,31 @@ struct MonthTabView: View {
|
||||
@ObservedObject var vm: ScheduleViewModel
|
||||
var body: some View {
|
||||
VStack {
|
||||
HStack (spacing: 34) {
|
||||
HStack (spacing: 33) {
|
||||
ForEach(MockData.daysOfWeek.indices, id: \.self) { index in
|
||||
Text(MockData.daysOfWeek[index])
|
||||
.font(.custom("Montserrat-SemiBold", fixedSize: 15))
|
||||
.foregroundColor(MockData.daysOfWeek[index] == "Вс" ? Color(.red) : Color("customGray2"))
|
||||
.padding(.top, 13)
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
}
|
||||
.padding(.top, 14)
|
||||
TabView(selection: $currentMonthIndex) {
|
||||
ForEach(monthSlider.indices, id: \.self) { index in
|
||||
let month = monthSlider[index]
|
||||
MonthView(month)
|
||||
.tag(index)
|
||||
.transition(.slide)
|
||||
}
|
||||
}
|
||||
.padding(.top, -25)
|
||||
.padding(.bottom, -10)
|
||||
.padding(.horizontal, -15)
|
||||
.tabViewStyle(.page(indexDisplayMode: .never))
|
||||
//.animation(.easeIn(duration: 0.3), value: currentMonthIndex)
|
||||
}
|
||||
.onAppear(perform: {
|
||||
.frame(height: 220)
|
||||
.padding(.top, 26)
|
||||
.padding(.bottom, 20)
|
||||
.onAppear {
|
||||
updateMonthScreenViewForNewGroup()
|
||||
})
|
||||
}
|
||||
.onChange(of: currentMonthIndex, initial: false) { oldValue, newValue in
|
||||
if newValue == 0 || newValue == (monthSlider.count - 1) {
|
||||
createMonth = true
|
||||
@ -82,6 +82,3 @@ struct MonthTabView: View {
|
||||
}
|
||||
|
||||
|
||||
#Preview {
|
||||
ContentView()
|
||||
}
|
||||
|
@ -44,7 +44,3 @@ struct WeekTabView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
ContentView()
|
||||
}
|
||||
|
Reference in New Issue
Block a user