199 lines
6.2 KiB
Swift
199 lines
6.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")
|
|
|
|
@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
|
|
|
|
@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) {
|
|
Button(action: save) {
|
|
Text("Save")
|
|
}
|
|
}
|
|
}
|
|
.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)
|
|
}
|
|
}
|
|
}
|
|
|
|
private func save() {
|
|
// Save all changed files
|
|
do {
|
|
try content.saveToDisk()
|
|
} catch {
|
|
print("Failed to save content: \(error.localizedDescription)")
|
|
}
|
|
}
|
|
|
|
private func loadContent() {
|
|
do {
|
|
try content.loadFromDisk()
|
|
} catch {
|
|
print("Failed to load content: \(error.localizedDescription)")
|
|
}
|
|
}
|
|
}
|
|
|