Source code for the WriteFreely SwiftUI app for iOS, iPadOS, and macOS
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.
 
 
 

140 lines
4.6 KiB

  1. import SwiftUI
  2. struct PostListView: View {
  3. @EnvironmentObject var model: WriteFreelyModel
  4. @State var selectedCollection: PostCollection
  5. #if os(iOS)
  6. @State private var isPresentingSettings = false
  7. #endif
  8. var body: some View {
  9. #if os(iOS)
  10. GeometryReader { geometry in
  11. List {
  12. ForEach(showPosts(for: selectedCollection)) { post in
  13. NavigationLink(
  14. destination: PostEditorView(post: post)
  15. ) {
  16. PostCellView(
  17. post: post
  18. )
  19. }
  20. }
  21. }
  22. .environmentObject(model)
  23. .navigationTitle(selectedCollection.title)
  24. .toolbar {
  25. ToolbarItem(placement: .primaryAction) {
  26. Button(action: {
  27. let post = Post()
  28. model.store.add(post)
  29. }, label: {
  30. Image(systemName: "square.and.pencil")
  31. })
  32. }
  33. ToolbarItem(placement: .bottomBar) {
  34. HStack {
  35. Button(action: {
  36. isPresentingSettings = true
  37. }, label: {
  38. Image(systemName: "gear")
  39. }).sheet(
  40. isPresented: $isPresentingSettings,
  41. onDismiss: {
  42. isPresentingSettings = false
  43. },
  44. content: {
  45. SettingsView(isPresented: $isPresentingSettings)
  46. }
  47. )
  48. .padding(.leading)
  49. Spacer()
  50. Text(pluralizedPostCount(for: showPosts(for: selectedCollection)))
  51. .foregroundColor(.secondary)
  52. Spacer()
  53. Button(action: {
  54. reloadFromServer()
  55. }, label: {
  56. Image(systemName: "arrow.clockwise")
  57. })
  58. .disabled(!model.account.isLoggedIn)
  59. }
  60. .padding()
  61. .frame(width: geometry.size.width)
  62. }
  63. }
  64. }
  65. #else //if os(macOS)
  66. List {
  67. ForEach(showPosts(for: selectedCollection)) { post in
  68. NavigationLink(
  69. destination: PostEditorView(post: post)
  70. ) {
  71. PostCellView(
  72. post: post
  73. )
  74. }
  75. }
  76. }
  77. .navigationTitle(selectedCollection.title)
  78. .navigationSubtitle(pluralizedPostCount(for: showPosts(for: selectedCollection)))
  79. .toolbar {
  80. Button(action: {
  81. let post = Post()
  82. model.store.add(post)
  83. }, label: {
  84. Image(systemName: "square.and.pencil")
  85. })
  86. Button(action: {
  87. reloadFromServer()
  88. }, label: {
  89. Image(systemName: "arrow.clockwise")
  90. })
  91. .disabled(!model.account.isLoggedIn)
  92. }
  93. #endif
  94. }
  95. private func pluralizedPostCount(for posts: [Post]) -> String {
  96. if posts.count == 1 {
  97. return "1 post"
  98. } else {
  99. return "\(posts.count) posts"
  100. }
  101. }
  102. private func showPosts(for collection: PostCollection) -> [Post] {
  103. var posts: [Post]
  104. if collection == CollectionListModel.allPostsCollection {
  105. posts = model.store.posts
  106. } else if collection == CollectionListModel.draftsCollection {
  107. posts = model.store.posts.filter { $0.collection == nil }
  108. } else {
  109. posts = model.store.posts.filter { $0.collection?.title == collection.title }
  110. }
  111. return posts
  112. }
  113. private func reloadFromServer() {
  114. DispatchQueue.main.async {
  115. model.collections.clearUserCollection()
  116. model.fetchUserCollections()
  117. model.fetchUserPosts()
  118. }
  119. }
  120. }
  121. struct PostList_Previews: PreviewProvider {
  122. static var previews: some View {
  123. let model = WriteFreelyModel()
  124. for post in testPostData {
  125. model.store.add(post)
  126. }
  127. return Group {
  128. PostListView(selectedCollection: CollectionListModel.allPostsCollection)
  129. .environmentObject(model)
  130. }
  131. }
  132. }