Consolidate images and files
This commit is contained in:
10
CHDataManagement/Main/MainContentView.swift
Normal file
10
CHDataManagement/Main/MainContentView.swift
Normal file
@ -0,0 +1,10 @@
|
||||
import SwiftUI
|
||||
|
||||
protocol MainContentView: View {
|
||||
|
||||
associatedtype Item: Identifiable
|
||||
|
||||
init(item: Item)
|
||||
|
||||
static var itemDescription: String { get }
|
||||
}
|
185
CHDataManagement/Main/MainView.swift
Normal file
185
CHDataManagement/Main/MainView.swift
Normal file
@ -0,0 +1,185 @@
|
||||
import SwiftUI
|
||||
import SFSafeSymbols
|
||||
|
||||
|
||||
#warning("Consolidate images and files")
|
||||
#warning("Allow selection of pages as navigation bar items")
|
||||
#warning("Transfer images of posts to other language")
|
||||
|
||||
@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? = .generation
|
||||
|
||||
@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:
|
||||
List(SettingsSection.allCases, selection: $selectedSection) { item in
|
||||
Label(item.rawValue, systemSymbol: item.icon).tag(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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:
|
||||
GenerationDetailView(section: 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:
|
||||
Text("")
|
||||
}
|
||||
}
|
||||
|
||||
@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
|
||||
content.saveToDisk()
|
||||
}
|
||||
|
||||
private func loadContent() {
|
||||
do {
|
||||
try content.loadFromDisk()
|
||||
} catch {
|
||||
print("Failed to load content: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
25
CHDataManagement/Main/SelectedContentView.swift
Normal file
25
CHDataManagement/Main/SelectedContentView.swift
Normal file
@ -0,0 +1,25 @@
|
||||
import SwiftUI
|
||||
|
||||
struct SelectedContentView<Contained>: View where Contained: MainContentView {
|
||||
|
||||
@Binding
|
||||
var selected: Contained.Item?
|
||||
|
||||
init(selected: Binding<Contained.Item?>) {
|
||||
self._selected = selected
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
if let item = selected {
|
||||
Contained(item: item)
|
||||
} else {
|
||||
HStack {
|
||||
Spacer()
|
||||
Text("Select \(Contained.itemDescription) from the sidebar")
|
||||
.font(.largeTitle)
|
||||
.foregroundColor(.secondary)
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
20
CHDataManagement/Main/SelectedDetailView.swift
Normal file
20
CHDataManagement/Main/SelectedDetailView.swift
Normal file
@ -0,0 +1,20 @@
|
||||
import SwiftUI
|
||||
|
||||
struct SelectedDetailView<Contained>: View where Contained: MainContentView {
|
||||
|
||||
@Binding
|
||||
var selected: Contained.Item?
|
||||
|
||||
init(selected: Binding<Contained.Item?>) {
|
||||
self._selected = selected
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
if let item = selected {
|
||||
Contained(item: item)
|
||||
.id(item.id)
|
||||
} else {
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
}
|
18
CHDataManagement/Main/TabSelection.swift
Normal file
18
CHDataManagement/Main/TabSelection.swift
Normal file
@ -0,0 +1,18 @@
|
||||
import SwiftUI
|
||||
import SFSafeSymbols
|
||||
|
||||
enum MainViewTab {
|
||||
case posts
|
||||
case pages
|
||||
case tags
|
||||
case files
|
||||
case generation
|
||||
|
||||
var canAddItems: Bool {
|
||||
if case .generation = self {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user