Source code for the WriteFreely SwiftUI app for iOS, iPadOS, and macOS
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 

176 linhas
7.5 KiB

  1. import SwiftUI
  2. import Combine
  3. struct PostListView: View {
  4. @EnvironmentObject var model: WriteFreelyModel
  5. @Environment(\.managedObjectContext) var managedObjectContext
  6. @State private var postCount: Int = 0
  7. var selectedCollection: WFACollection?
  8. var showAllPosts: Bool
  9. #if os(iOS)
  10. private var frameHeight: CGFloat {
  11. var height: CGFloat = 50
  12. let bottom = UIApplication.shared.windows.first?.safeAreaInsets.bottom ?? 0
  13. height += bottom
  14. return height
  15. }
  16. #endif
  17. var body: some View {
  18. #if os(iOS)
  19. ZStack(alignment: .bottom) {
  20. PostListFilteredView(
  21. collection: selectedCollection,
  22. showAllPosts: showAllPosts,
  23. postCount: $postCount
  24. )
  25. .navigationTitle(
  26. showAllPosts ? "All Posts" : selectedCollection?.title ?? (
  27. model.account.server == "https://write.as" ? "Anonymous" : "Drafts"
  28. )
  29. )
  30. .toolbar {
  31. ToolbarItem(placement: .primaryAction) {
  32. // We have to add a Spacer as a sibling view to the Button in some kind of Stack, so that any
  33. // a11y modifiers are applied as expected: bug report filed as FB8956392.
  34. ZStack {
  35. Spacer()
  36. Button(action: {
  37. let managedPost = model.editor.generateNewLocalPost(withFont: model.preferences.font)
  38. withAnimation {
  39. self.model.showAllPosts = false
  40. self.model.selectedPost = managedPost
  41. }
  42. }, label: {
  43. ZStack {
  44. Image("does.not.exist")
  45. .accessibilityHidden(true)
  46. Image(systemName: "square.and.pencil")
  47. .accessibilityHidden(true)
  48. .imageScale(.large) // These modifiers compensate for the resizing
  49. .padding(.vertical, 12) // done to the Image (and the button tap target)
  50. .padding(.leading, 12) // by the SwiftUI layout system from adding a
  51. .padding(.trailing, 8) // Spacer in this ZStack (FB8956392).
  52. }
  53. .frame(maxWidth: .infinity, maxHeight: .infinity)
  54. })
  55. .accessibilityLabel(Text("Compose"))
  56. .accessibilityHint(Text("Compose a new local draft"))
  57. }
  58. }
  59. }
  60. VStack {
  61. HStack(spacing: 0) {
  62. Button(action: {
  63. model.isPresentingSettingsView = true
  64. }, label: {
  65. Image(systemName: "gear")
  66. .padding(.vertical, 4)
  67. .padding(.horizontal, 8)
  68. })
  69. .accessibilityLabel(Text("Settings"))
  70. .accessibilityHint(Text("Open the Settings sheet"))
  71. .sheet(
  72. isPresented: $model.isPresentingSettingsView,
  73. onDismiss: { model.isPresentingSettingsView = false },
  74. content: {
  75. SettingsView()
  76. .environmentObject(model)
  77. }
  78. )
  79. Spacer()
  80. Text(postCount == 1 ? "\(postCount) post" : "\(postCount) posts")
  81. .foregroundColor(.secondary)
  82. .alert(isPresented: $model.isPresentingNetworkErrorAlert, content: {
  83. Alert(
  84. title: Text("Connection Error"),
  85. message: Text("""
  86. There is no internet connection at the moment. Please reconnect or try again later.
  87. """),
  88. dismissButton: .default(Text("OK"), action: {
  89. model.isPresentingNetworkErrorAlert = false
  90. })
  91. )
  92. })
  93. Spacer()
  94. if model.isProcessingRequest {
  95. ProgressView()
  96. .padding(.vertical, 4)
  97. .padding(.horizontal, 8)
  98. } else {
  99. Button(action: {
  100. DispatchQueue.main.async {
  101. model.fetchUserCollections()
  102. model.fetchUserPosts()
  103. }
  104. }, label: {
  105. Image(systemName: "arrow.clockwise")
  106. .padding(.vertical, 4)
  107. .padding(.horizontal, 8)
  108. })
  109. .accessibilityLabel(Text("Refresh Posts"))
  110. .accessibilityHint(Text("Fetch changes from the server"))
  111. .disabled(!model.account.isLoggedIn)
  112. }
  113. }
  114. .padding(.top, 8)
  115. .padding(.horizontal, 8)
  116. Spacer()
  117. }
  118. .frame(height: frameHeight)
  119. .background(Color(UIColor.systemGray5))
  120. .overlay(Divider(), alignment: .top)
  121. }
  122. .ignoresSafeArea()
  123. .onAppear {
  124. model.selectedCollection = selectedCollection
  125. model.showAllPosts = showAllPosts
  126. }
  127. #else
  128. PostListFilteredView(
  129. collection: selectedCollection,
  130. showAllPosts: showAllPosts,
  131. postCount: $postCount
  132. )
  133. .toolbar {
  134. ToolbarItemGroup(placement: .primaryAction) {
  135. if model.selectedPost != nil {
  136. ActivePostToolbarView(activePost: model.selectedPost!)
  137. .alert(isPresented: $model.isPresentingNetworkErrorAlert, content: {
  138. Alert(
  139. title: Text("Connection Error"),
  140. message: Text("""
  141. There is no internet connection at the moment. \
  142. Please reconnect or try again later.
  143. """),
  144. dismissButton: .default(Text("OK"), action: {
  145. model.isPresentingNetworkErrorAlert = false
  146. })
  147. )
  148. })
  149. }
  150. }
  151. }
  152. .navigationTitle(
  153. showAllPosts ? "All Posts" : selectedCollection?.title ?? (
  154. model.account.server == "https://write.as" ? "Anonymous" : "Drafts"
  155. )
  156. )
  157. #endif
  158. }
  159. }
  160. struct PostListView_Previews: PreviewProvider {
  161. static var previews: some View {
  162. let context = LocalStorageManager.standard.container.viewContext
  163. let model = WriteFreelyModel()
  164. return PostListView(showAllPosts: true)
  165. .environment(\.managedObjectContext, context)
  166. .environmentObject(model)
  167. }
  168. }