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.
 
 
 

148 regels
5.2 KiB

  1. import SwiftUI
  2. #if os(macOS)
  3. import Sparkle
  4. #endif
  5. @main
  6. struct CheckForDebugModifier {
  7. static func main() {
  8. #if os(macOS)
  9. if NSEvent.modifierFlags.contains(.shift) {
  10. // Clear the launch-to-last-draft values to load a new draft.
  11. UserDefaults.shared.setValue(false, forKey: WFDefaults.showAllPostsFlag)
  12. UserDefaults.shared.setValue(nil, forKey: WFDefaults.selectedCollectionURL)
  13. UserDefaults.shared.setValue(nil, forKey: WFDefaults.lastDraftURL)
  14. } else {
  15. // No-op
  16. }
  17. #endif
  18. WriteFreely_MultiPlatformApp.main()
  19. }
  20. }
  21. struct WriteFreely_MultiPlatformApp: App {
  22. @StateObject private var model = WriteFreelyModel.shared
  23. #if os(macOS)
  24. @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
  25. @StateObject var updaterViewModel = MacUpdatesViewModel()
  26. @State private var selectedTab = 0
  27. #endif
  28. var body: some Scene {
  29. WindowGroup {
  30. ContentView()
  31. .onAppear(perform: {
  32. if model.editor.showAllPostsFlag {
  33. DispatchQueue.main.async {
  34. self.model.selectedCollection = nil
  35. self.model.showAllPosts = true
  36. showLastDraftOrCreateNewLocalPost()
  37. }
  38. } else {
  39. DispatchQueue.main.async {
  40. self.model.selectedCollection = model.editor.fetchSelectedCollectionFromAppStorage()
  41. self.model.showAllPosts = false
  42. showLastDraftOrCreateNewLocalPost()
  43. }
  44. }
  45. })
  46. .withErrorHandling()
  47. .environmentObject(model)
  48. .environment(\.managedObjectContext, LocalStorageManager.standard.container.viewContext)
  49. // .preferredColorScheme(preferences.selectedColorScheme) // See PreferencesModel for info.
  50. }
  51. .commands {
  52. #if os(macOS)
  53. CommandGroup(after: .appInfo) {
  54. CheckForUpdatesView(updaterViewModel: updaterViewModel)
  55. }
  56. #endif
  57. CommandGroup(replacing: .newItem, addition: {
  58. Button("New Post") {
  59. createNewLocalPost()
  60. }
  61. .keyboardShortcut("n", modifiers: [.command])
  62. })
  63. CommandGroup(after: .newItem) {
  64. Button("Refresh Posts") {
  65. DispatchQueue.main.async {
  66. model.fetchUserCollections()
  67. model.fetchUserPosts()
  68. }
  69. }
  70. .disabled(!model.account.isLoggedIn)
  71. .keyboardShortcut("r", modifiers: [.command])
  72. }
  73. SidebarCommands()
  74. #if os(macOS)
  75. PostCommands(model: model)
  76. #endif
  77. CommandGroup(after: .help) {
  78. Button("Visit Support Forum") {
  79. #if os(macOS)
  80. NSWorkspace().open(model.helpURL)
  81. #else
  82. UIApplication.shared.open(model.helpURL)
  83. #endif
  84. }
  85. }
  86. ToolbarCommands()
  87. TextEditingCommands()
  88. }
  89. #if os(macOS)
  90. Settings {
  91. TabView(selection: $selectedTab) {
  92. MacAccountView()
  93. .environmentObject(model)
  94. .tabItem {
  95. Image(systemName: "person.crop.circle")
  96. Text("Account")
  97. }
  98. .tag(0)
  99. MacPreferencesView(preferences: model.preferences)
  100. .tabItem {
  101. Image(systemName: "gear")
  102. Text("Preferences")
  103. }
  104. .tag(1)
  105. MacUpdatesView(updaterViewModel: updaterViewModel)
  106. .tabItem {
  107. Image(systemName: "arrow.down.circle")
  108. Text("Updates")
  109. }
  110. .tag(2)
  111. }
  112. .frame(minWidth: 500, maxWidth: 500, minHeight: 200)
  113. .padding()
  114. // .preferredColorScheme(preferences.selectedColorScheme) // See PreferencesModel for info.
  115. }
  116. #endif
  117. }
  118. private func showLastDraftOrCreateNewLocalPost() {
  119. if model.editor.lastDraftURL != nil {
  120. self.model.selectedPost = model.editor.fetchLastDraftFromAppStorage()
  121. } else {
  122. createNewLocalPost()
  123. }
  124. }
  125. private func createNewLocalPost() {
  126. withAnimation {
  127. // Un-set the currently selected post
  128. self.model.selectedPost = nil
  129. }
  130. // Create the new-post managed object
  131. let managedPost = model.editor.generateNewLocalPost(withFont: model.preferences.font)
  132. withAnimation {
  133. // Set it as the selectedPost
  134. DispatchQueue.main.asyncAfter(deadline: .now()) {
  135. self.model.selectedPost = managedPost
  136. }
  137. }
  138. }
  139. }