2024-12-19 16:25:05 +01:00

226 lines
7.2 KiB
Swift

import SwiftUI
import SFSafeSymbols
#warning("Show all warnings on page content")
#warning("Button to delete file")
#warning("Fix podcast")
#warning("Add link to other language")
#warning("Transfer images of posts to other language")
#warning("Show tag selection view for pages")
#warning("Button to replace files")
#warning("Replace links to files inside pages when id changes")
#warning("Calculate file sizes")
#warning("Specify image aspect ratio to prevent page jumps")
#warning("Add version and source url properties to file resources")
#warning("Consolidate all errors in Content")
#warning("Generate pages for posts")
#warning("Clean up mock content")
#warning("Show posts linking to a page")
#warning("Add author to settings and page headers")
@main
struct MainView: App {
private let sidebarWidth: CGFloat = 250
private let detailWidth: CGFloat = 300
@StateObject
private var content: Content = .init()
@State
private var language: ContentLanguage = .english
@State
private var selectedTab: MainViewTab = .posts
@State
private var selectedPost: Post?
@State
private var selectedPage: Page?
@State
private var selectedTag: Tag?
@State
private var selectedImage: ImageResource?
@State
private var selectedFile: FileResource?
@State
private var selectedSection: SettingsSection = .folders
@State
private var showAddSheet = false
@State
private var showInitialSetupSheet = false
@ViewBuilder
var sidebar: some View {
switch selectedTab {
case .posts:
PostListView(selectedPost: $selectedPost)
case .pages:
PageListView(selectedPage: $selectedPage)
case .tags:
TagListView(selectedTag: $selectedTag)
case .files:
FileListView(selectedFile: $selectedFile)
case .generation:
SettingsListView(selectedSection: $selectedSection)
}
}
@ViewBuilder
var viewContent: some View {
switch selectedTab {
case .posts:
SelectedContentView<PostContentView>(selected: $selectedPost)
case .pages:
SelectedContentView<PageContentView>(selected: $selectedPage)
case .tags:
SelectedContentView<TagContentView>(selected: $selectedTag)
case .files:
SelectedContentView<FileContentView>(selected: $selectedFile)
case .generation:
GenerationContentView(selected: $selectedSection)
}
}
@ViewBuilder
var detail: some View {
switch selectedTab {
case .posts:
SelectedDetailView<PostDetailView>(selected: $selectedPost)
case .pages:
SelectedDetailView<PageDetailView>(selected: $selectedPage)
case .tags:
SelectedDetailView<TagDetailView>(selected: $selectedTag)
case .files:
SelectedDetailView<FileDetailView>(selected: $selectedFile)
case .generation:
GenerationDetailView(section: selectedSection)
}
}
@ViewBuilder
var addItemSheet: some View {
switch selectedTab {
case .posts:
AddPostView(selected: $selectedPost)
case .pages:
AddPageView(selected: $selectedPage)
case .tags:
AddTagView(selected: $selectedTag)
case .files:
AddFileView(selectedImage: $selectedImage, selectedFile: $selectedFile)
case .generation:
Text("Not implemented")
}
}
var body: some Scene {
WindowGroup {
NavigationSplitView {
sidebar
.toolbar {
ToolbarItem(placement: .navigation) {
Picker("", selection: $selectedTab) {
Text("Posts").tag(MainViewTab.posts)
Text("Pages").tag(MainViewTab.pages)
Text("Tags").tag(MainViewTab.tags)
Text("Files").tag(MainViewTab.files)
Text("Generation").tag(MainViewTab.generation)
}.pickerStyle(.segmented)
}
}
.navigationSplitViewColumnWidth(min: sidebarWidth, ideal: sidebarWidth, max: sidebarWidth)
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button(action: { showAddSheet = true }) {
Label("Add", systemSymbol: .plus)
}
.disabled(!selectedTab.canAddItems)
}
}
} content: {
viewContent
} detail: {
detail
.navigationSplitViewColumnWidth(min: detailWidth, ideal: detailWidth, max: detailWidth)
}
.toolbar {
ToolbarItem(placement: .primaryAction) {
Picker("", selection: $language) {
Text("English")
.tag(ContentLanguage.english)
Text("German")
.tag(ContentLanguage.german)
}.pickerStyle(.segmented)
}
ToolbarItem(placement: .primaryAction) {
if content.storage.contentScope != nil {
Button(action: save) {
Text("Save")
}
} else {
Button(action: showInitialSheet) {
Text("Setup")
}
.background(RoundedRectangle(cornerRadius: 8).fill(Color.red))
}
}
}
.navigationTitle("")
.environment(\.language, language)
.environmentObject(content)
.onAppear(perform: loadContent)
.onReceive(Timer.publish(every: 60.0, on: .main, in: .common).autoconnect()) { _ in
save()
}
.sheet(isPresented: $showAddSheet) {
addItemSheet
.environment(\.language, language)
.environmentObject(content)
}
.sheet(isPresented: $showInitialSetupSheet) {
InitialSetupView()
.environment(\.language, language)
.environmentObject(content)
}
}
}
private func save() {
do {
try content.saveToDisk()
} catch {
print("Failed to save content: \(error.localizedDescription)")
}
}
private func loadContent() {
guard content.storage.contentScope != nil else {
showInitialSheet()
return
}
do {
try content.loadFromDisk()
} catch {
print("Failed to load content: \(error.localizedDescription)")
}
}
private func showInitialSheet() {
DispatchQueue.main.async {
selectedSection = .folders
selectedTab = .generation
showInitialSetupSheet = true
}
}
}