Page MenuHomeMusing Studio

No OneTemporary

diff --git a/Shared/Navigation/ContentView.swift b/Shared/Navigation/ContentView.swift
index 1b599c0..2f79f4c 100644
--- a/Shared/Navigation/ContentView.swift
+++ b/Shared/Navigation/ContentView.swift
@@ -1,108 +1,110 @@
import SwiftUI
struct ContentView: View {
@EnvironmentObject var model: WriteFreelyModel
var body: some View {
NavigationView {
#if os(macOS)
CollectionListView()
.toolbar {
Button(
action: {
NSApp.keyWindow?.contentViewController?.tryToPerform(
#selector(NSSplitViewController.toggleSidebar(_:)), with: nil
)
},
label: { Image(systemName: "sidebar.left") }
)
.help("Toggle the sidebar's visibility.")
Spacer()
Button(action: {
withAnimation {
self.model.selectedPost = nil
}
let managedPost = WFAPost(context: LocalStorageManager.persistentContainer.viewContext)
managedPost.createdDate = Date()
managedPost.title = ""
managedPost.body = ""
managedPost.status = PostStatus.local.rawValue
managedPost.collectionAlias = nil
switch model.preferences.font {
case 1:
managedPost.appearance = "sans"
case 2:
managedPost.appearance = "wrap"
default:
managedPost.appearance = "serif"
}
if let languageCode = Locale.current.languageCode {
managedPost.language = languageCode
managedPost.rtl = Locale.characterDirection(forLanguage: languageCode) == .rightToLeft
}
withAnimation {
DispatchQueue.main.async {
+ self.model.showAllPosts = false
+ self.model.selectedCollection = nil
self.model.selectedPost = managedPost
}
}
}, label: { Image(systemName: "square.and.pencil") })
.help("Create a new local draft.")
}
#else
CollectionListView()
#endif
#if os(macOS)
ZStack {
- PostListView(selectedCollection: nil, showAllPosts: false) //model.account.isLoggedIn)
+ PostListView()
if model.isProcessingRequest {
ZStack {
Color(NSColor.controlBackgroundColor).opacity(0.75)
ProgressView()
}
}
}
#else
- PostListView(selectedCollection: nil, showAllPosts: model.account.isLoggedIn)
+ PostListView()
#endif
Text("Select a post, or create a new local draft.")
.foregroundColor(.secondary)
}
.environmentObject(model)
#if os(iOS)
EmptyView()
.sheet(
isPresented: $model.isPresentingSettingsView,
onDismiss: { model.isPresentingSettingsView = false },
content: {
SettingsView()
.environmentObject(model)
}
)
.alert(isPresented: $model.isPresentingNetworkErrorAlert, content: {
Alert(
title: Text("Connection Error"),
message: Text("""
There is no internet connection at the moment. Please reconnect or try again later.
"""),
dismissButton: .default(Text("OK"), action: {
model.isPresentingNetworkErrorAlert = false
})
)
})
#endif
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
let context = LocalStorageManager.persistentContainer.viewContext
let model = WriteFreelyModel()
return ContentView()
.environment(\.managedObjectContext, context)
.environmentObject(model)
}
}
diff --git a/Shared/PostCollection/CollectionListView.swift b/Shared/PostCollection/CollectionListView.swift
index 23a4aa5..a084f82 100644
--- a/Shared/PostCollection/CollectionListView.swift
+++ b/Shared/PostCollection/CollectionListView.swift
@@ -1,51 +1,78 @@
import SwiftUI
struct CollectionListView: View {
@EnvironmentObject var model: WriteFreelyModel
@FetchRequest(
entity: WFACollection.entity(),
sortDescriptors: [NSSortDescriptor(keyPath: \WFACollection.title, ascending: true)]
) var collections: FetchedResults<WFACollection>
var body: some View {
- List {
+ List(selection: $model.selectedCollection) {
if model.account.isLoggedIn {
- NavigationLink(destination: PostListView(selectedCollection: nil, showAllPosts: true)) {
+ NavigationLink(
+ destination: PostListView(),
+ isActive: Binding<Bool>(
+ get: { () -> Bool in
+ model.selectedCollection == nil && model.showAllPosts
+ }, set: { newValue in
+ if newValue {
+ self.model.selectedCollection = nil
+ self.model.showAllPosts = true
+ } else {
+ // No-op
+ }
+ }
+ )) {
Text("All Posts")
}
- NavigationLink(destination: PostListView(selectedCollection: nil, showAllPosts: false)) {
+ NavigationLink(
+ destination: PostListView(),
+ isActive: Binding<Bool>(
+ get: { () -> Bool in
+ model.selectedCollection == nil && !model.showAllPosts
+ }, set: { newValue in
+ if newValue {
+ self.model.selectedCollection = nil
+ self.model.showAllPosts = false
+ } else {
+ // No-op
+ }
+ }
+ )) {
Text(model.account.server == "https://write.as" ? "Anonymous" : "Drafts")
}
Section(header: Text("Your Blogs")) {
ForEach(collections, id: \.alias) { collection in
NavigationLink(
- destination: PostListView(selectedCollection: collection, showAllPosts: false)
- ) {
- Text(collection.title)
- }
+ collection.title,
+ destination: PostListView(),
+ tag: collection,
+ selection: $model.selectedCollection
+ )
}
}
} else {
NavigationLink(destination: PostListView(selectedCollection: nil, showAllPosts: false)) {
Text("Drafts")
}
}
}
.navigationTitle(
model.account.isLoggedIn ? "\(URL(string: model.account.server)?.host ?? "WriteFreely")" : "WriteFreely"
)
.listStyle(SidebarListStyle())
}
}
struct CollectionListView_LoggedOutPreviews: PreviewProvider {
static var previews: some View {
let context = LocalStorageManager.persistentContainer.viewContext
let model = WriteFreelyModel()
return CollectionListView()
.environment(\.managedObjectContext, context)
.environmentObject(model)
}
}
diff --git a/Shared/PostList/PostListFilteredView.swift b/Shared/PostList/PostListFilteredView.swift
index 3460033..29601d6 100644
--- a/Shared/PostList/PostListFilteredView.swift
+++ b/Shared/PostList/PostListFilteredView.swift
@@ -1,154 +1,140 @@
import SwiftUI
struct PostListFilteredView: View {
@EnvironmentObject var model: WriteFreelyModel
@Binding var postCount: Int
@FetchRequest(entity: WFACollection.entity(), sortDescriptors: []) var collections: FetchedResults<WFACollection>
var fetchRequest: FetchRequest<WFAPost>
- var showAllPosts: Bool {
- didSet {
- model.showAllPosts = showAllPosts
- }
- }
-
- var selectedCollection: WFACollection? {
- didSet {
- model.selectedCollection = selectedCollection
- }
- }
-
init(collection: WFACollection?, showAllPosts: Bool, postCount: Binding<Int>) {
- self.showAllPosts = showAllPosts
- self.selectedCollection = collection
if showAllPosts {
fetchRequest = FetchRequest<WFAPost>(
entity: WFAPost.entity(),
sortDescriptors: [NSSortDescriptor(key: "createdDate", ascending: false)]
)
} else {
if let collectionAlias = collection?.alias {
fetchRequest = FetchRequest<WFAPost>(
entity: WFAPost.entity(),
sortDescriptors: [NSSortDescriptor(key: "createdDate", ascending: false)],
predicate: NSPredicate(format: "collectionAlias == %@", collectionAlias)
)
} else {
fetchRequest = FetchRequest<WFAPost>(
entity: WFAPost.entity(),
sortDescriptors: [NSSortDescriptor(key: "createdDate", ascending: false)],
predicate: NSPredicate(format: "collectionAlias == nil")
)
}
}
_postCount = postCount
}
var body: some View {
#if os(iOS)
List {
ForEach(fetchRequest.wrappedValue, id: \.self) { post in
NavigationLink(
destination: PostEditorView(post: post),
tag: post,
- selection: $model.selectedPost
- ) {
- if showAllPosts {
- if let collection = collections.filter { $0.alias == post.collectionAlias }.first {
- PostCellView(post: post, collectionName: collection.title)
+ selection: $model.selectedPost,
+ label: {
+ if model.showAllPosts {
+ if let collection = collections.filter { $0.alias == post.collectionAlias }.first {
+ PostCellView(post: post, collectionName: collection.title)
+ } else {
+ let collectionName = model.account.server == "https://write.as" ? "Anonymous" : "Drafts"
+ PostCellView(post: post, collectionName: collectionName)
+ }
} else {
- let collectionName = model.account.server == "https://write.as" ? "Anonymous" : "Drafts"
- PostCellView(post: post, collectionName: collectionName)
+ PostCellView(post: post)
}
- } else {
- PostCellView(post: post)
- }
- }
- .deleteDisabled(post.status != PostStatus.local.rawValue)
+ })
+ .deleteDisabled(post.status != PostStatus.local.rawValue)
}
.onDelete(perform: { indexSet in
for index in indexSet {
let post = fetchRequest.wrappedValue[index]
delete(post)
}
})
}
.onAppear(perform: {
self.postCount = fetchRequest.wrappedValue.count
})
.onChange(of: fetchRequest.wrappedValue.count, perform: { value in
self.postCount = value
})
#else
List {
ForEach(fetchRequest.wrappedValue, id: \.self) { post in
NavigationLink(
destination: PostEditorView(post: post),
tag: post,
- selection: $model.selectedPost
- ) {
- if showAllPosts {
- if let collection = collections.filter { $0.alias == post.collectionAlias }.first {
- PostCellView(post: post, collectionName: collection.title)
+ selection: $model.selectedPost,
+ label: {
+ if model.showAllPosts {
+ if let collection = collections.filter { $0.alias == post.collectionAlias }.first {
+ PostCellView(post: post, collectionName: collection.title)
+ } else {
+ let collectionName = model.account.server == "https://write.as" ? "Anonymous" : "Drafts"
+ PostCellView(post: post, collectionName: collectionName)
+ }
} else {
- let collectionName = model.account.server == "https://write.as" ? "Anonymous" : "Drafts"
- PostCellView(post: post, collectionName: collectionName)
+ PostCellView(post: post)
}
- } else {
- PostCellView(post: post)
- }
- }
- .deleteDisabled(post.status != PostStatus.local.rawValue)
+ })
+ .deleteDisabled(post.status != PostStatus.local.rawValue)
}
.onDelete(perform: { indexSet in
for index in indexSet {
let post = fetchRequest.wrappedValue[index]
delete(post)
}
})
}
.alert(isPresented: $model.isPresentingDeleteAlert) {
Alert(
title: Text("Delete Post?"),
message: Text("This action cannot be undone."),
primaryButton: .cancel() {
model.postToDelete = nil
},
secondaryButton: .destructive(Text("Delete"), action: {
if let postToDelete = model.postToDelete {
model.selectedPost = nil
DispatchQueue.main.async {
model.editor.clearLastDraft()
model.posts.remove(postToDelete)
}
model.postToDelete = nil
}
})
)
}
.onDeleteCommand(perform: {
guard let selectedPost = model.selectedPost else { return }
if selectedPost.status == PostStatus.local.rawValue {
model.postToDelete = selectedPost
model.isPresentingDeleteAlert = true
}
})
#endif
}
func delete(_ post: WFAPost) {
DispatchQueue.main.async {
if post == model.selectedPost {
model.selectedPost = nil
model.editor.clearLastDraft()
}
model.posts.remove(post)
}
}
}
struct PostListFilteredView_Previews: PreviewProvider {
static var previews: some View {
return PostListFilteredView(collection: nil, showAllPosts: false, postCount: .constant(999))
}
}
diff --git a/Shared/PostList/PostListView.swift b/Shared/PostList/PostListView.swift
index 1d16962..271e4e8 100644
--- a/Shared/PostList/PostListView.swift
+++ b/Shared/PostList/PostListView.swift
@@ -1,173 +1,168 @@
import SwiftUI
import Combine
struct PostListView: View {
@EnvironmentObject var model: WriteFreelyModel
@Environment(\.managedObjectContext) var managedObjectContext
- @State var selectedCollection: WFACollection?
- @State var showAllPosts: Bool = false
@State private var postCount: Int = 0
#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
var body: some View {
#if os(iOS)
ZStack(alignment: .bottom) {
- PostListFilteredView(collection: selectedCollection, showAllPosts: showAllPosts, postCount: $postCount)
+ PostListFilteredView(
+ collection: model.selectedCollection,
+ showAllPosts: model.showAllPosts,
+ postCount: $postCount
+ )
.navigationTitle(
- showAllPosts ? "All Posts" : selectedCollection?.title ?? (
+ model.showAllPosts ? "All Posts" : model.selectedCollection?.title ?? (
model.account.server == "https://write.as" ? "Anonymous" : "Drafts"
)
)
.toolbar {
ToolbarItem(placement: .primaryAction) {
// 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.
ZStack {
Spacer()
Button(action: {
let managedPost = WFAPost(context: self.managedObjectContext)
managedPost.createdDate = Date()
managedPost.title = ""
managedPost.body = ""
managedPost.status = PostStatus.local.rawValue
managedPost.collectionAlias = nil
switch model.preferences.font {
case 1:
managedPost.appearance = "sans"
case 2:
managedPost.appearance = "wrap"
default:
managedPost.appearance = "serif"
}
if let languageCode = Locale.current.languageCode {
managedPost.language = languageCode
//swiftlint:disable:next line_length
managedPost.rtl = Locale.characterDirection(forLanguage: languageCode) == .rightToLeft
}
withAnimation {
- self.selectedCollection = nil
- self.showAllPosts = false
+ self.model.showAllPosts = false
+ self.model.selectedCollection = nil
self.model.selectedPost = managedPost
}
}, label: {
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)
})
.accessibilityLabel(Text("Compose"))
.accessibilityHint(Text("Compose a new local draft"))
}
}
}
VStack {
HStack(spacing: 0) {
Button(action: {
model.isPresentingSettingsView = true
}, label: {
Image(systemName: "gear")
.padding(.vertical, 4)
.padding(.horizontal, 8)
})
.accessibilityLabel(Text("Settings"))
.accessibilityHint(Text("Open the Settings sheet"))
Spacer()
Text(postCount == 1 ? "\(postCount) post" : "\(postCount) posts")
.foregroundColor(.secondary)
Spacer()
if model.isProcessingRequest {
ProgressView()
.padding(.vertical, 4)
.padding(.horizontal, 8)
} else {
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)
}
}
.padding(.top, 8)
.padding(.horizontal, 8)
Spacer()
}
.frame(height: frameHeight)
.background(Color(UIColor.systemGray5))
.overlay(Divider(), alignment: .top)
}
.ignoresSafeArea()
#else //if os(macOS)
PostListFilteredView(
- collection: selectedCollection,
- showAllPosts: showAllPosts,
+ collection: model.selectedCollection,
+ showAllPosts: model.showAllPosts,
postCount: $postCount
)
.toolbar {
ToolbarItemGroup(placement: .primaryAction) {
if let selectedPost = model.selectedPost {
ActivePostToolbarView(activePost: selectedPost)
.alert(isPresented: $model.isPresentingNetworkErrorAlert, content: {
Alert(
title: Text("Connection Error"),
message: Text("""
There is no internet connection at the moment. \
Please reconnect or try again later.
"""),
dismissButton: .default(Text("OK"), action: {
model.isPresentingNetworkErrorAlert = false
})
)
})
}
}
}
- .onDisappear {
- DispatchQueue.main.async {
- self.model.selectedCollection = nil
- self.model.showAllPosts = true
- self.model.selectedPost = nil
- }
- }
.navigationTitle(
- showAllPosts ? "All Posts" : selectedCollection?.title ?? (
+ model.showAllPosts ? "All Posts" : model.selectedCollection?.title ?? (
model.account.server == "https://write.as" ? "Anonymous" : "Drafts"
)
)
#endif
}
}
struct PostListView_Previews: PreviewProvider {
static var previews: some View {
let context = LocalStorageManager.persistentContainer.viewContext
let model = WriteFreelyModel()
return PostListView()
.environment(\.managedObjectContext, context)
.environmentObject(model)
}
}

File Metadata

Mime Type
text/x-diff
Expires
Fri, Jan 31, 9:45 AM (4 h, 38 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3145675

Event Timeline