2020-07-25 11:02:11 +00:00
|
|
|
import SwiftUI
|
2020-10-29 21:20:20 +00:00
|
|
|
import Combine
|
2020-07-25 11:02:11 +00:00
|
|
|
|
2020-08-17 17:46:23 +00:00
|
|
|
struct PostListView: View {
|
2020-08-18 18:06:02 +00:00
|
|
|
@EnvironmentObject var model: WriteFreelyModel
|
2022-07-27 13:56:32 +00:00
|
|
|
@EnvironmentObject var errorHandling: ErrorHandling
|
2020-10-29 20:09:35 +00:00
|
|
|
@Environment(\.managedObjectContext) var managedObjectContext
|
2020-09-08 20:17:58 +00:00
|
|
|
|
2020-10-29 21:20:20 +00:00
|
|
|
@State private var postCount: Int = 0
|
2021-11-28 13:01:54 +00:00
|
|
|
@State private var filteredListViewId: Int = 0
|
2020-08-17 19:51:07 +00:00
|
|
|
|
2021-09-24 18:45:28 +00:00
|
|
|
var selectedCollection: WFACollection?
|
|
|
|
var showAllPosts: Bool
|
|
|
|
|
2021-01-04 17:58:35 +00:00
|
|
|
#if os(iOS)
|
|
|
|
private var frameHeight: CGFloat {
|
|
|
|
var height: CGFloat = 50
|
|
|
|
let bottom = UIApplication.shared.windows.first?.safeAreaInsets.bottom ?? 0
|
|
|
|
height += bottom
|
|
|
|
return height
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-07-25 11:02:11 +00:00
|
|
|
var body: some View {
|
2020-08-07 14:13:36 +00:00
|
|
|
#if os(iOS)
|
2021-01-04 15:04:27 +00:00
|
|
|
ZStack(alignment: .bottom) {
|
2021-01-13 22:03:42 +00:00
|
|
|
PostListFilteredView(
|
2021-09-24 18:45:28 +00:00
|
|
|
collection: selectedCollection,
|
|
|
|
showAllPosts: showAllPosts,
|
2021-01-13 22:03:42 +00:00
|
|
|
postCount: $postCount
|
|
|
|
)
|
2021-11-28 13:01:54 +00:00
|
|
|
.id(self.filteredListViewId)
|
2021-01-04 15:04:27 +00:00
|
|
|
.navigationTitle(
|
2021-09-24 18:45:28 +00:00
|
|
|
showAllPosts ? "All Posts" : selectedCollection?.title ?? (
|
2021-01-04 15:04:27 +00:00
|
|
|
model.account.server == "https://write.as" ? "Anonymous" : "Drafts"
|
|
|
|
)
|
2020-09-04 18:53:53 +00:00
|
|
|
)
|
2021-01-04 15:04:27 +00:00
|
|
|
.toolbar {
|
|
|
|
ToolbarItem(placement: .primaryAction) {
|
2021-01-11 15:52:12 +00:00
|
|
|
ZStack {
|
2022-09-07 12:29:13 +00:00
|
|
|
// We have to add a Spacer as a sibling view to the Button in some kind of Stack so that any
|
|
|
|
// a11y modifiers are applied as expected: bug report filed as FB8956392.
|
|
|
|
if #unavailable(iOS 16) {
|
|
|
|
Spacer()
|
|
|
|
}
|
2020-10-16 20:19:38 +00:00
|
|
|
Button(action: {
|
2021-01-25 18:22:15 +00:00
|
|
|
let managedPost = model.editor.generateNewLocalPost(withFont: model.preferences.font)
|
2021-01-11 15:52:12 +00:00
|
|
|
withAnimation {
|
2021-01-13 22:03:42 +00:00
|
|
|
self.model.showAllPosts = false
|
2022-11-03 10:56:11 +00:00
|
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
|
|
|
self.model.selectedPost = managedPost
|
|
|
|
}
|
2020-11-25 19:41:53 +00:00
|
|
|
}
|
2020-10-16 20:19:38 +00:00
|
|
|
}, label: {
|
2021-01-11 15:52:12 +00:00
|
|
|
ZStack {
|
|
|
|
Image("does.not.exist")
|
|
|
|
.accessibilityHidden(true)
|
|
|
|
Image(systemName: "square.and.pencil")
|
|
|
|
.accessibilityHidden(true)
|
|
|
|
.imageScale(.large) // These modifiers compensate for the resizing
|
|
|
|
.padding(.vertical, 12) // done to the Image (and the button tap target)
|
|
|
|
.padding(.leading, 12) // by the SwiftUI layout system from adding a
|
|
|
|
.padding(.trailing, 8) // Spacer in this ZStack (FB8956392).
|
|
|
|
}
|
|
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
2020-10-16 20:19:38 +00:00
|
|
|
})
|
2021-01-11 15:52:12 +00:00
|
|
|
.accessibilityLabel(Text("Compose"))
|
|
|
|
.accessibilityHint(Text("Compose a new local draft"))
|
2020-10-16 20:19:38 +00:00
|
|
|
}
|
2020-08-10 20:50:24 +00:00
|
|
|
}
|
2020-08-11 14:51:50 +00:00
|
|
|
}
|
2021-01-04 17:58:35 +00:00
|
|
|
VStack {
|
|
|
|
HStack(spacing: 0) {
|
|
|
|
Button(action: {
|
|
|
|
model.isPresentingSettingsView = true
|
|
|
|
}, label: {
|
|
|
|
Image(systemName: "gear")
|
2021-01-11 16:58:59 +00:00
|
|
|
.padding(.vertical, 4)
|
|
|
|
.padding(.horizontal, 8)
|
2021-01-04 17:58:35 +00:00
|
|
|
})
|
2021-01-11 15:52:12 +00:00
|
|
|
.accessibilityLabel(Text("Settings"))
|
|
|
|
.accessibilityHint(Text("Open the Settings sheet"))
|
2021-09-24 18:45:28 +00:00
|
|
|
.sheet(
|
|
|
|
isPresented: $model.isPresentingSettingsView,
|
|
|
|
onDismiss: { model.isPresentingSettingsView = false },
|
|
|
|
content: {
|
|
|
|
SettingsView()
|
|
|
|
.environmentObject(model)
|
|
|
|
}
|
|
|
|
)
|
2021-01-04 17:58:35 +00:00
|
|
|
Spacer()
|
|
|
|
Text(postCount == 1 ? "\(postCount) post" : "\(postCount) posts")
|
|
|
|
.foregroundColor(.secondary)
|
|
|
|
Spacer()
|
|
|
|
if model.isProcessingRequest {
|
|
|
|
ProgressView()
|
2021-01-11 16:58:59 +00:00
|
|
|
.padding(.vertical, 4)
|
|
|
|
.padding(.horizontal, 8)
|
2021-01-04 17:58:35 +00:00
|
|
|
} else {
|
2023-10-23 21:15:41 +00:00
|
|
|
if model.hasNetworkConnection {
|
|
|
|
Button(action: {
|
|
|
|
DispatchQueue.main.async {
|
|
|
|
model.fetchUserCollections()
|
|
|
|
model.fetchUserPosts()
|
|
|
|
}
|
|
|
|
}, label: {
|
|
|
|
Image(systemName: "arrow.clockwise")
|
|
|
|
.padding(.vertical, 4)
|
|
|
|
.padding(.horizontal, 8)
|
|
|
|
})
|
|
|
|
.accessibilityLabel(Text("Refresh Posts"))
|
|
|
|
.accessibilityHint(Text("Fetch changes from the server"))
|
|
|
|
.disabled(!model.account.isLoggedIn)
|
|
|
|
} else {
|
|
|
|
Image(systemName: "wifi.exclamationmark")
|
2021-01-11 16:58:59 +00:00
|
|
|
.padding(.vertical, 4)
|
|
|
|
.padding(.horizontal, 8)
|
2023-10-23 21:15:41 +00:00
|
|
|
.foregroundColor(.secondary)
|
|
|
|
}
|
2021-01-04 17:58:35 +00:00
|
|
|
}
|
|
|
|
}
|
2021-01-11 16:58:59 +00:00
|
|
|
.padding(.top, 8)
|
|
|
|
.padding(.horizontal, 8)
|
2021-01-04 17:58:35 +00:00
|
|
|
Spacer()
|
|
|
|
}
|
|
|
|
.frame(height: frameHeight)
|
|
|
|
.background(Color(UIColor.systemGray5))
|
|
|
|
.overlay(Divider(), alignment: .top)
|
2020-08-07 14:13:36 +00:00
|
|
|
}
|
2022-04-02 12:07:03 +00:00
|
|
|
.ignoresSafeArea(.all, edges: .bottom)
|
2021-09-24 19:29:20 +00:00
|
|
|
.onAppear {
|
2024-07-28 10:02:02 +00:00
|
|
|
// Set the selected collection and whether or not we want to show all posts
|
2021-09-24 19:29:20 +00:00
|
|
|
model.selectedCollection = selectedCollection
|
|
|
|
model.showAllPosts = showAllPosts
|
2024-07-28 10:02:02 +00:00
|
|
|
|
|
|
|
// We use this to invalidate and refresh the view, so that new posts created outside of the app (e.g.,
|
|
|
|
// in the action extension) show up.
|
|
|
|
withAnimation {
|
|
|
|
self.filteredListViewId += 1
|
|
|
|
}
|
2021-09-24 19:29:20 +00:00
|
|
|
}
|
2022-07-27 13:56:32 +00:00
|
|
|
.onChange(of: model.hasError) { value in
|
|
|
|
if value {
|
|
|
|
if let error = model.currentError {
|
|
|
|
self.errorHandling.handle(error: error)
|
|
|
|
} else {
|
|
|
|
self.errorHandling.handle(error: AppError.genericError())
|
|
|
|
}
|
|
|
|
model.hasError = false
|
|
|
|
}
|
|
|
|
}
|
2021-03-24 17:31:40 +00:00
|
|
|
#else
|
2020-12-04 22:08:32 +00:00
|
|
|
PostListFilteredView(
|
2021-09-24 18:45:28 +00:00
|
|
|
collection: selectedCollection,
|
|
|
|
showAllPosts: showAllPosts,
|
2020-12-04 22:08:32 +00:00
|
|
|
postCount: $postCount
|
|
|
|
)
|
2020-12-17 16:27:58 +00:00
|
|
|
.toolbar {
|
|
|
|
ToolbarItemGroup(placement: .primaryAction) {
|
2021-01-27 15:18:26 +00:00
|
|
|
if model.selectedPost != nil {
|
|
|
|
ActivePostToolbarView(activePost: model.selectedPost!)
|
|
|
|
}
|
2020-12-17 16:27:58 +00:00
|
|
|
}
|
|
|
|
}
|
2020-12-04 22:08:32 +00:00
|
|
|
.navigationTitle(
|
2021-09-24 18:45:28 +00:00
|
|
|
showAllPosts ? "All Posts" : selectedCollection?.title ?? (
|
2020-12-04 22:08:32 +00:00
|
|
|
model.account.server == "https://write.as" ? "Anonymous" : "Drafts"
|
2020-09-04 18:53:53 +00:00
|
|
|
)
|
2020-12-04 22:08:32 +00:00
|
|
|
)
|
2021-10-08 18:29:18 +00:00
|
|
|
.onAppear {
|
|
|
|
model.selectedCollection = selectedCollection
|
|
|
|
model.showAllPosts = showAllPosts
|
|
|
|
}
|
2022-07-27 13:56:32 +00:00
|
|
|
.onChange(of: model.hasError) { value in
|
|
|
|
if value {
|
|
|
|
if let error = model.currentError {
|
|
|
|
self.errorHandling.handle(error: error)
|
|
|
|
} else {
|
|
|
|
self.errorHandling.handle(error: AppError.genericError())
|
|
|
|
}
|
|
|
|
model.hasError = false
|
|
|
|
}
|
|
|
|
}
|
2020-10-29 21:20:20 +00:00
|
|
|
#endif
|
2020-08-07 13:54:22 +00:00
|
|
|
}
|
2020-07-25 11:02:11 +00:00
|
|
|
}
|
|
|
|
|
2020-09-09 16:12:19 +00:00
|
|
|
struct PostListView_Previews: PreviewProvider {
|
|
|
|
static var previews: some View {
|
2021-10-08 21:15:38 +00:00
|
|
|
let context = LocalStorageManager.standard.container.viewContext
|
2020-09-09 16:12:19 +00:00
|
|
|
let model = WriteFreelyModel()
|
|
|
|
|
2021-09-24 18:45:28 +00:00
|
|
|
return PostListView(showAllPosts: true)
|
2020-09-09 16:12:19 +00:00
|
|
|
.environment(\.managedObjectContext, context)
|
|
|
|
.environmentObject(model)
|
|
|
|
}
|
|
|
|
}
|