You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
PadelClub/PadelClub/Views/Navigation/MainView.swift

256 lines
9.7 KiB

//
// MainView.swift
// PadelClub
//
// Created by Razmig Sarkissian on 29/02/2024.
//
import SwiftUI
import LeStorage
import StoreKit
struct MainView: View {
@EnvironmentObject var dataStore: DataStore
//TODO: IOS BUG
//@Environment(\.requestReview) var requestReview
@Environment(NavigationViewModel.self) private var navigation: NavigationViewModel
@Environment(ImportObserver.self) private var importObserver: ImportObserver
@State private var mainViewId: UUID = UUID()
var lastDataSource: String? {
dataStore.appSettings.lastDataSource
}
var selectedTabHandler: Binding<TabDestination?> { Binding(
get: { navigation.selectedTab },
set: {
if $0 == navigation.selectedTab {
// switch navigation.selectedTab {
// case .activity:
// navigation.path.removeLast()
// case .toolbox:
// navigation.toolboxPath = NavigationPath()
// case .umpire:
// navigation.umpirePath = NavigationPath()
// case .ongoing:
// navigation.ongoingPath = NavigationPath()
// case .tournamentOrganizer:
// break
// case .none:
// break
// }
} else {
navigation.selectedTab = $0
}
}
)}
private func _isConnected() -> Bool {
return StoreCenter.main.hasToken() && StoreCenter.main.userId != nil
}
var badgeText: Text? {
return (dataStore.appSettings.didCreateAccount && _isConnected() == false) ? Text("!").font(.headline) : nil
}
var body: some View {
TabView(selection: selectedTabHandler) {
ActivityView()
.tabItem(for: .activity)
.onAppear {
print("on appear main view")
if importObserver.willCheckDataIntegrity == false {
importObserver.willCheckDataIntegrity = true
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
_checkingDataIntegrity()
importObserver.willCheckDataIntegrity = false
}
}
#if DEBUG
#else
//_requestReviewIfAppropriated()
#endif
}
.toolbarBackground(.visible, for: .tabBar)
TournamentOrganizerView()
.tabItem(for: .tournamentOrganizer)
.toolbarBackground(.visible, for: .tabBar)
OngoingContainerView()
.tabItem(for: .ongoing)
.badge(self.dataStore.runningMatches().count)
.toolbarBackground(.visible, for: .tabBar)
ToolboxView()
.tabItem(for: .toolbox)
.toolbarBackground(.visible, for: .tabBar)
UmpireView()
.tabItem(for: .umpire)
.badge(badgeText)
.toolbarBackground(.visible, for: .tabBar)
// PadelClubView()
// .tabItem(for: .padelClub)
}
.id(mainViewId)
.onChange(of: dataStore.user.id) {
print("dataStore.user.id = ", dataStore.user.id)
print("StoreCenter.main.userId = ", StoreCenter.main.userId ?? "")
if StoreCenter.main.userId == nil { // user disconnected
navigation.path.removeLast(navigation.path.count)
mainViewId = UUID()
}
}
.environmentObject(dataStore)
.task {
//await self._checkSourceFileAvailability()
if StoreCenter.main.hasToken() {
do {
try await dataStore.clubs.loadDataFromServerIfAllowed()
} catch {
Logger.error(error)
}
let ids = dataStore.user.clubs
var save = false
ids.forEach { clubId in
if dataStore.clubs.findById(clubId) == nil {
dataStore.user.clubs.removeAll(where: { $0 == clubId })
save = true
}
}
if save {
dataStore.saveUser()
}
}
}
// .refreshable {
// Task {
// await self._checkSourceFileAvailability()
// }
// }
.overlay(alignment: .bottom) {
if importObserver.isImportingFile() {
_activityStatusBoxView()
} else {
_activityStatusBoxView()
.deferredRendering(for: .seconds(3))
}
}
}
@MainActor
private func _requestReviewIfAppropriated() {
let isConnected = StoreCenter.main.userId != nil
let numberOfSignificantTournaments = dataStore.tournaments.filter({ $0.isDeleted == false && $0.endDate != nil }).count
if isConnected || numberOfSignificantTournaments > 0 {
//requestReview()
}
}
func _activityStatusBoxView() -> some View {
return _activityStatus()
.toastFormatted()
}
@ViewBuilder
func _activityStatus() -> some View {
if importObserver.isImportingFile() {
HStack(spacing: 20) {
ProgressView()
.progressViewStyle(CircularProgressViewStyle(tint: Color.black))
Text(importObserver.currentlyImportingLabel())
}
} else if let mostRecentDateAvailable = SourceFileManager.shared.mostRecentDateAvailable, let lastDataSourceDate = SourceFileManager.shared.lastDataSourceDate() {
if mostRecentDateAvailable > lastDataSourceDate {
Label(mostRecentDateAvailable.monthYearFormatted + " disponible", systemImage: "exclamationmark.triangle")
.labelStyle(.titleAndIcon)
} else {
Label(mostRecentDateAvailable.monthYearFormatted, systemImage: "checkmark")
.labelStyle(.titleAndIcon)
}
}
}
private func _checkSourceFileAvailability() async {
print("dataStore.appSettings.lastDataSource :", dataStore.appSettings.lastDataSource ?? "none")
print("check internet")
print("check files on internet")
print("check if any files on internet are more recent than here")
importObserver.checkingFiles = true
await SourceFileManager.shared.fetchData()
importObserver.checkingFilesAttempt += 1
importObserver.checkingFiles = false
if let mostRecentDateAvailable = SourceFileManager.shared.mostRecentDateAvailable, mostRecentDateAvailable > SourceFileManager.shared.lastDataSourceDate() ?? .distantPast {
print("importing \(mostRecentDateAvailable)")
await _startImporting(importingDate: mostRecentDateAvailable)
}
}
private func _startImporting(importingDate: Date) async {
await MainActor.run {
importObserver.currentImportDate = importingDate
}
let lastDataSource = await FileImportManager.shared.importDataFromFFT(importingDate: importingDate)
dataStore.appSettings.lastDataSource = lastDataSource
dataStore.appSettingsStorage.write()
await _calculateMonthData(dataSource: lastDataSource)
await MainActor.run {
importObserver.currentImportDate = nil
}
await _downloadPreviousDate()
}
private func _calculateMonthData(dataSource: String?) async {
if let dataSource, let mostRecentDate = URL.importDateFormatter.date(from: dataSource) {
await MonthData.calculateCurrentUnrankedValues(fromDate: mostRecentDate)
}
}
private func _downloadPreviousDate() async {
await SourceFileManager.shared.getAllFiles(initialDate: "05-2024")
}
private func _checkingDataIntegrity() {
guard importObserver.checkingFiles == false, importObserver.isImportingFile() == false else {
return
}
if lastDataSource == nil {
Task {
await self._checkSourceFileAvailability()
}
} else if let lastDataSource, lastDataSource != URL.importDateFormatter.string(from: Date()) {
Task {
await self._checkSourceFileAvailability()
}
} else if let lastDataSource, let mostRecentDateImported = URL.importDateFormatter.date(from: lastDataSource) {
let monthData = dataStore.monthData.sorted(by: \.creationDate)
if let current = monthData.last {
Task {
let updated = await SourceFileManager.shared.fetchData(fromDate: mostRecentDateImported)
let fileURL = SourceFileManager.shared.allFiles(true).first(where: { $0.dateFromPath == mostRecentDateImported && $0.index == 0 })
print("file updated", updated)
if let updated, updated == 1 {
await _startImporting(importingDate: mostRecentDateImported)
} else if current.dataModelIdentifier != PersistenceController.getModelVersion() && current.fileModelIdentifier != fileURL?.fileModelIdentifier() {
await _startImporting(importingDate: mostRecentDateImported)
} else if updated == 0 {
await _calculateMonthData(dataSource: current.monthKey)
}
}
}
}
}
}
//#Preview {
// MainView()
//}